Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma
Pull rdma fix from Jason Gunthorpe: "One bug for missing user input validation: refuse invalid port numbers in the modify_qp system call" * tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma: RDMA/uverbs: Expand primary and alt AV port checks
This commit is contained in:
@@ -1984,15 +1984,64 @@ static int modify_qp(struct ib_uverbs_file *file,
|
||||
goto release_qp;
|
||||
}
|
||||
|
||||
if ((cmd->base.attr_mask & IB_QP_AV) &&
|
||||
!rdma_is_port_valid(qp->device, cmd->base.dest.port_num)) {
|
||||
ret = -EINVAL;
|
||||
goto release_qp;
|
||||
if ((cmd->base.attr_mask & IB_QP_AV)) {
|
||||
if (!rdma_is_port_valid(qp->device, cmd->base.dest.port_num)) {
|
||||
ret = -EINVAL;
|
||||
goto release_qp;
|
||||
}
|
||||
|
||||
if (cmd->base.attr_mask & IB_QP_STATE &&
|
||||
cmd->base.qp_state == IB_QPS_RTR) {
|
||||
/* We are in INIT->RTR TRANSITION (if we are not,
|
||||
* this transition will be rejected in subsequent checks).
|
||||
* In the INIT->RTR transition, we cannot have IB_QP_PORT set,
|
||||
* but the IB_QP_STATE flag is required.
|
||||
*
|
||||
* Since kernel 3.14 (commit dbf727de7440), the uverbs driver,
|
||||
* when IB_QP_AV is set, has required inclusion of a valid
|
||||
* port number in the primary AV. (AVs are created and handled
|
||||
* differently for infiniband and ethernet (RoCE) ports).
|
||||
*
|
||||
* Check the port number included in the primary AV against
|
||||
* the port number in the qp struct, which was set (and saved)
|
||||
* in the RST->INIT transition.
|
||||
*/
|
||||
if (cmd->base.dest.port_num != qp->real_qp->port) {
|
||||
ret = -EINVAL;
|
||||
goto release_qp;
|
||||
}
|
||||
} else {
|
||||
/* We are in SQD->SQD. (If we are not, this transition will
|
||||
* be rejected later in the verbs layer checks).
|
||||
* Check for both IB_QP_PORT and IB_QP_AV, these can be set
|
||||
* together in the SQD->SQD transition.
|
||||
*
|
||||
* If only IP_QP_AV was set, add in IB_QP_PORT as well (the
|
||||
* verbs layer driver does not track primary port changes
|
||||
* resulting from path migration. Thus, in SQD, if the primary
|
||||
* AV is modified, the primary port should also be modified).
|
||||
*
|
||||
* Note that in this transition, the IB_QP_STATE flag
|
||||
* is not allowed.
|
||||
*/
|
||||
if (((cmd->base.attr_mask & (IB_QP_AV | IB_QP_PORT))
|
||||
== (IB_QP_AV | IB_QP_PORT)) &&
|
||||
cmd->base.port_num != cmd->base.dest.port_num) {
|
||||
ret = -EINVAL;
|
||||
goto release_qp;
|
||||
}
|
||||
if ((cmd->base.attr_mask & (IB_QP_AV | IB_QP_PORT))
|
||||
== IB_QP_AV) {
|
||||
cmd->base.attr_mask |= IB_QP_PORT;
|
||||
cmd->base.port_num = cmd->base.dest.port_num;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((cmd->base.attr_mask & IB_QP_ALT_PATH) &&
|
||||
(!rdma_is_port_valid(qp->device, cmd->base.alt_port_num) ||
|
||||
!rdma_is_port_valid(qp->device, cmd->base.alt_dest.port_num))) {
|
||||
!rdma_is_port_valid(qp->device, cmd->base.alt_dest.port_num) ||
|
||||
cmd->base.alt_port_num != cmd->base.alt_dest.port_num)) {
|
||||
ret = -EINVAL;
|
||||
goto release_qp;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user