RDMA/restrack: don't use uaccess_kernel()
PATCH v2 1/1 RDMA/restrack: don't use uaccess_kernel()
uaccess_kernel() isn't sufficient to determine if an rdma resource is user-mode or not. For example, resources allocated in the add_one() function of an ib_client get falsely labeled as user mode, when they are kernel mode allocations. EG: mad qps.
The result is that these qps are skipped over during a nldev query because of an erroneous namespace mismatch.
So now we determine if the resource is user-mode by looking at the object struct's uobject or similar pointer to know if it was allocated for user mode applications.
---
Changes since v1:
changed _create_qp() to take the qp ib_uobject ptr so it is availble to rdma_restrack_add()
--- drivers/infiniband/core/core_priv.h | 4 +++- drivers/infiniband/core/restrack.c | 35 +++++++++++++++++++++++++++++++++-- drivers/infiniband/core/uverbs_cmd.c | 4 ++-- drivers/infiniband/core/verbs.c | 3 +-- 4 files changed, 39 insertions(+), 7 deletions(-)
drivers/infiniband/core/core_priv.h +3 -1
@@ -305,7 +305,8 @@ static inline int ib_mad_enforce_security(struct ib_mad_agent_private *map,static inline struct ib_qp *_ib_create_qp (struct ib_device *dev,struct ib_pd *pd,struct ib_qp_init_attr *attr, -struct ib_udata *udata) +struct ib_udata *udata, +struct ib_uobject *uobj) {struct ib_qp *qp;
@@ -315,6 +316,7 @@ static inline struct ib_qp *_ib_create_qp(struct ib_device *dev, qp->device = dev; qp->pd = pd; + qp->uobject = uobj;/* * We don't track XRC QPs for now, because they don't have PD * and more importantly they are created internaly by driver,
drivers/infiniband/core/restrack.c +33 -2
@@ -7,7 +7,6 @@#include <rdma/restrack.h> #include <linux/mutex.h> #include <linux/sched/task.h> -#include <linux/uaccess.h> #include <linux/pid_namespace.h> void rdma_restrack_init (struct rdma_restrack_root *res)
@@ -93,6 +92,38 @@ static struct ib_device *res_to_dev(struct rdma_restrack_entry *res)return dev; } +static bool res_is_user (struct rdma_restrack_entry *res) +{ +enum rdma_restrack_type type = res->type; +struct ib_xrcd *xrcd; +struct ib_pd *pd; +struct ib_cq *cq; +struct ib_qp *qp; +bool is_user = false; + +switch (type) { +case RDMA_RESTRACK_PD : + pd = container_of(res, struct ib_pd, res); + is_user = pd->uobject; +break ; +case RDMA_RESTRACK_CQ : + cq = container_of(res, struct ib_cq, res); + is_user = cq->uobject; +break ; +case RDMA_RESTRACK_QP : + qp = container_of(res, struct ib_qp, res); + is_user = qp->uobject; +break ; +case RDMA_RESTRACK_XRCD : + xrcd = container_of(res, struct ib_xrcd, res); + is_user = xrcd->inode; +break ; +default : +WARN_ONCE (true,"Wrong resource tracking type %u\n" , type); + } +return is_user; +} +void rdma_restrack_add (struct rdma_restrack_entry *res) {struct ib_device *dev =res_to_dev (res);
@@ -100,7 +131,7 @@ void rdma_restrack_add(struct rdma_restrack_entry *res)if (!dev)return ; -if (!uaccess_kernel ()) { +if (res_is_user (res)) {get_task_struct (current); res->task = current; res->kern_name =NULL ;
drivers/infiniband/core/uverbs_cmd.c +2 -2
@@ -1518,7 +1518,8 @@ static int create_qp(struct ib_uverbs_file *file,if (cmd->qp_type ==IB_QPT_XRC_TGT ) qp =ib_create_qp (pd, &attr);else - qp =_ib_create_qp (device, pd, &attr, uhw); + qp =_ib_create_qp (device, pd, &attr, uhw, + &obj->uevent.uobject);if (IS_ERR (qp)) { ret =PTR_ERR (qp);
@@ -1551,7 +1552,6 @@ static int create_qp(struct ib_uverbs_file *file,if (ind_tbl)atomic_inc (&ind_tbl->usecnt); } - qp->uobject = &obj->uevent.uobject; obj->uevent.uobject.object = qp;
drivers/infiniband/core/verbs.c +1 -2
@@ -887,7 +887,7 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,if (qp_init_attr->cap.max_rdma_ctxs)rdma_rw_init_qp (device, qp_init_attr); - qp =_ib_create_qp (device, pd, qp_init_attr,NULL ); + qp =_ib_create_qp (device, pd, qp_init_attr,NULL ,NULL );if (IS_ERR (qp))return qp;
@@ -898,7 +898,6 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd, } qp->real_qp = qp; - qp->uobject =NULL ; qp->qp_type = qp_init_attr->qp_type; qp->rwq_ind_tbl = qp_init_attr->rwq_ind_tbl;
Signature · 6 lines
1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
A message that is not in the archive (sent off-list or not yet received): 20180216165919.997D72BB6D-ff04S8wfc4plDsoTORJclLwze2ij/[email protected]
Quoted 18 lines · Steve Wise
uaccess_kernel()isn't sufficient to determine if an rdma resource is user-mode or not. For example, resources allocated in theadd_one()function of anib_clientget falsely labeled as user mode, when they are kernel mode allocations. EG: mad qps.The result is that these qps are skipped over during a nldev query because of an erroneous namespace mismatch.
So now we determine if the resource is user-mode by looking at the object struct's uobject or similar pointer to know if it was allocated for user mode applications.
Fixes 02d8883f520e ("RDMA/restrack: Add general infrastructure to track RDMA resources")Signed-off-by Steve Wise <[email protected]>Changes since v1:
Quoted 8 lines
changed
_create_qp()to take the qpib_uobjectptr so it is availble tordma_restrack_add()drivers/infiniband/core/core_priv.h | 4 +++- drivers/infiniband/core/restrack.c | 35 +++++++++++++++++++++++++++++++++-- drivers/infiniband/core/uverbs_cmd.c | 4 ++-- drivers/infiniband/core/verbs.c | 3 +-- 4 files changed, 39 insertions(+), 7 deletions(-)
I took this to for-rc, but when I fixed the XRCD conflict with Leon's patch I ended up retyping it to this - don't really need all rambly boilerplate. Someone should fix the other one too..
static bool res_is_user(struct rdma_restrack_entry *res)
{
switch (res->type) {
case RDMA_RESTRACK_PD:
return container_of(res, struct ib_pd, res)->uobject;
case RDMA_RESTRACK_CQ:
return container_of(res, struct ib_cq, res)->uobject;
case RDMA_RESTRACK_QP:
return container_of(res, struct ib_qp, res)->uobject;
default:
WARN_ONCE(true, "Wrong resource tracking type %u\n", res->type);
return false;
}
}Jason
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
A message that is not in the archive (sent off-list or not yet received): 20180216172537.GA10123-uk2M96/[email protected]
Quoted 11 lines · Steve Wise
Quoted 9 lines
uaccess_kernel()isn't sufficient to determine if an rdma resource is user-mode or not. For example, resources allocated in theadd_one()function of anib_clientget falsely labeled as user mode, when they are kernel mode allocations. EG: mad qps.The result is that these qps are skipped over during a nldev query because of an erroneous namespace mismatch.
So now we determine if the resource is user-mode by looking at the
object
Quoted 15 lines
Quoted 4 lines
struct's uobject or similar pointer to know if it was allocated for user mode applications.
Fixes 02d8883f520e ("RDMA/restrack: Add general infrastructure to trackRDMA resources")
Quoted 10 lines
Signed-off-by Steve Wise <[email protected]>Changes since v1:
changed
_create_qp()to take the qpib_uobjectptr so it is availble tordma_restrack_add()drivers/infiniband/core/core_priv.h | 4 +++- drivers/infiniband/core/restrack.c | 35
Quoted 8 lines
+++++++++++++++++++++++++++++++++--
Quoted 3 lines
drivers/infiniband/core/uverbs_cmd.c | 4 ++-- drivers/infiniband/core/verbs.c | 3 +-- 4 files changed, 39 insertions(+), 7 deletions(-)I took this to for-rc, but when I fixed the XRCD conflict with Leon's patch I ended up retyping it to this - don't really need all rambly boilerplate. Someone should fix the other one too..
I don't know what you mean by 'rambly boilerplate'?
Quoted 16 lines
static bool
res_is_user(struct rdma_restrack_entry *res){ switch (res->type) { case RDMA_RESTRACK_PD: return container_of(res, struct ib_pd, res)->uobject; case RDMA_RESTRACK_CQ: return container_of(res, struct ib_cq, res)->uobject; case RDMA_RESTRACK_QP: return container_of(res, struct ib_qp, res)->uobject; default: WARN_ONCE(true, "Wrong resource tracking type %u\n", res->type); return false; } }
This looks clean to me. Thanks.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 5 lines · Steve Wise
Quoted 3 lines
I took this to for-rc, but when I fixed the XRCD conflict with Leon's patch I ended up retyping it to this - don't really need all rambly boilerplate. Someone should fix the other one too..
I don't know what you mean by 'rambly boilerplate'?
Just that there is lots of unncessary statements to get to a fairly simple result...
Jason
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Leon Romanovsky
Reviewed-byQuoted 34 lines · Steve Wise
uaccess_kernel()isn't sufficient to determine if an rdma resource is user-mode or not. For example, resources allocated in theadd_one()function of anib_clientget falsely labeled as user mode, when they are kernel mode allocations. EG: mad qps.The result is that these qps are skipped over during a nldev query because of an erroneous namespace mismatch.
So now we determine if the resource is user-mode by looking at the object struct's uobject or similar pointer to know if it was allocated for user mode applications.
Fixes 02d8883f520e ("RDMA/restrack: Add general infrastructure to track RDMA resources")Signed-off-by Steve Wise <[email protected]>---
Changes since v1:
changed
_create_qp()to take the qpib_uobjectptr so it is availble tordma_restrack_add()--- drivers/infiniband/core/core_priv.h | 4 +++- drivers/infiniband/core/restrack.c | 35 +++++++++++++++++++++++++++++++++-- drivers/infiniband/core/uverbs_cmd.c | 4 ++-- drivers/infiniband/core/verbs.c | 3 +-- 4 files changed, 39 insertions(+), 7 deletions(-)drivers/infiniband/core/core_priv.h +0
-0
drivers/infiniband/core/core_priv.h static inline int ib_mad_enforce_security(struct ib_mad_agent_private *map, · line 309
Quoted 6 lines
drivers/infiniband/core/core_priv.h +2
-1@@ -305,7 +305,8 @@ static inline int ib_mad_enforce_security(struct ib_mad_agent_private *map,static inline struct ib_qp *_ib_create_qp (struct ib_device *dev,struct ib_pd *pd,struct ib_qp_init_attr *attr, -struct ib_udata *udata) +struct ib_udata *udata, +struct ib_uobject *uobj)
I'm fine with this solution either, but believe that v1 was cleaner way to address this issue, because udata tells us already that we are creating user/kernel QP and QP has already PD associated with it.
Also I tried to move to _ib_create_qp() as less as possible initialization logic.
Thanks,