aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNoa Osherovich <noaos@mellanox.com>2017-08-23 01:35:40 -0400
committerDoug Ledford <dledford@redhat.com>2017-08-24 15:33:33 -0400
commit498ca3c82a7b11e152a46c253f6b2087c929ce00 (patch)
tree095d8d2ce4f7c6aeeaa3d6c5bab735ba1c4d205d
parent65159c051c45f269cf40a14f9404248f2d524920 (diff)
IB/core: Avoid accessing non-allocated memory when inferring port type
Commit 44c58487d51a ("IB/core: Define 'ib' and 'roce' rdma_ah_attr types") introduced the concept of type in ah_attr: * During ib_register_device, each port is checked for its type which is stored in ib_device's port_immutable array. * During uverbs' modify_qp, the type is inferred using the port number in ib_uverbs_qp_dest struct (address vector) by accessing the relevant port_immutable array and the type is passed on to providers. IB spec (version 1.3) enforces a valid port value only in Reset to Init. During Init to RTR, the address vector must be valid but port number is not mentioned as a field in the address vector, so its value is not validated, which leads to accesses to a non-allocated memory when inferring the port type. Save the real port number in ib_qp during modify to Init (when the comp_mask indicates that the port number is valid) and use this value to infer the port type. Avoid copying the address vector fields if the matching bit is not set in the attr_mask. Address vector can't be modified before the port, so no valid flow is affected. Fixes: 44c58487d51a ('IB/core: Define 'ib' and 'roce' rdma_ah_attr types') Signed-off-by: Noa Osherovich <noaos@mellanox.com> Reviewed-by: Yishai Hadas <yishaih@mellanox.com> Signed-off-by: Leon Romanovsky <leon@kernel.org> Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c11
-rw-r--r--drivers/infiniband/core/verbs.c7
-rw-r--r--include/rdma/ib_verbs.h1
3 files changed, 14 insertions, 5 deletions
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 55822ae71955..739bd69ef1d4 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -1522,6 +1522,7 @@ static int create_qp(struct ib_uverbs_file *file,
1522 qp->qp_type = attr.qp_type; 1522 qp->qp_type = attr.qp_type;
1523 atomic_set(&qp->usecnt, 0); 1523 atomic_set(&qp->usecnt, 0);
1524 atomic_inc(&pd->usecnt); 1524 atomic_inc(&pd->usecnt);
1525 qp->port = 0;
1525 if (attr.send_cq) 1526 if (attr.send_cq)
1526 atomic_inc(&attr.send_cq->usecnt); 1527 atomic_inc(&attr.send_cq->usecnt);
1527 if (attr.recv_cq) 1528 if (attr.recv_cq)
@@ -1962,8 +1963,9 @@ static int modify_qp(struct ib_uverbs_file *file,
1962 attr->alt_timeout = cmd->base.alt_timeout; 1963 attr->alt_timeout = cmd->base.alt_timeout;
1963 attr->rate_limit = cmd->rate_limit; 1964 attr->rate_limit = cmd->rate_limit;
1964 1965
1965 attr->ah_attr.type = rdma_ah_find_type(qp->device, 1966 if (cmd->base.attr_mask & IB_QP_AV)
1966 cmd->base.dest.port_num); 1967 attr->ah_attr.type = rdma_ah_find_type(qp->device,
1968 cmd->base.dest.port_num);
1967 if (cmd->base.dest.is_global) { 1969 if (cmd->base.dest.is_global) {
1968 rdma_ah_set_grh(&attr->ah_attr, NULL, 1970 rdma_ah_set_grh(&attr->ah_attr, NULL,
1969 cmd->base.dest.flow_label, 1971 cmd->base.dest.flow_label,
@@ -1981,8 +1983,9 @@ static int modify_qp(struct ib_uverbs_file *file,
1981 rdma_ah_set_port_num(&attr->ah_attr, 1983 rdma_ah_set_port_num(&attr->ah_attr,
1982 cmd->base.dest.port_num); 1984 cmd->base.dest.port_num);
1983 1985
1984 attr->alt_ah_attr.type = rdma_ah_find_type(qp->device, 1986 if (cmd->base.attr_mask & IB_QP_ALT_PATH)
1985 cmd->base.dest.port_num); 1987 attr->alt_ah_attr.type =
1988 rdma_ah_find_type(qp->device, cmd->base.dest.port_num);
1986 if (cmd->base.alt_dest.is_global) { 1989 if (cmd->base.alt_dest.is_global) {
1987 rdma_ah_set_grh(&attr->alt_ah_attr, NULL, 1990 rdma_ah_set_grh(&attr->alt_ah_attr, NULL,
1988 cmd->base.alt_dest.flow_label, 1991 cmd->base.alt_dest.flow_label,
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index 7f8fe443df46..b456e3ca1876 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -838,6 +838,7 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
838 spin_lock_init(&qp->mr_lock); 838 spin_lock_init(&qp->mr_lock);
839 INIT_LIST_HEAD(&qp->rdma_mrs); 839 INIT_LIST_HEAD(&qp->rdma_mrs);
840 INIT_LIST_HEAD(&qp->sig_mrs); 840 INIT_LIST_HEAD(&qp->sig_mrs);
841 qp->port = 0;
841 842
842 if (qp_init_attr->qp_type == IB_QPT_XRC_TGT) 843 if (qp_init_attr->qp_type == IB_QPT_XRC_TGT)
843 return ib_create_xrc_qp(qp, qp_init_attr); 844 return ib_create_xrc_qp(qp, qp_init_attr);
@@ -1297,7 +1298,11 @@ int ib_modify_qp_with_udata(struct ib_qp *qp, struct ib_qp_attr *attr,
1297 if (ret) 1298 if (ret)
1298 return ret; 1299 return ret;
1299 } 1300 }
1300 return ib_security_modify_qp(qp, attr, attr_mask, udata); 1301 ret = ib_security_modify_qp(qp, attr, attr_mask, udata);
1302 if (!ret && (attr_mask & IB_QP_PORT))
1303 qp->port = attr->port_num;
1304
1305 return ret;
1301} 1306}
1302EXPORT_SYMBOL(ib_modify_qp_with_udata); 1307EXPORT_SYMBOL(ib_modify_qp_with_udata);
1303 1308
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index b5732432bb29..88c32aba32f7 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -1683,6 +1683,7 @@ struct ib_qp {
1683 enum ib_qp_type qp_type; 1683 enum ib_qp_type qp_type;
1684 struct ib_rwq_ind_table *rwq_ind_tbl; 1684 struct ib_rwq_ind_table *rwq_ind_tbl;
1685 struct ib_qp_security *qp_sec; 1685 struct ib_qp_security *qp_sec;
1686 u8 port;
1686}; 1687};
1687 1688
1688struct ib_mr { 1689struct ib_mr {