Ensure that CM_ID exists prior to access it in ibcore.

Prior to access UCMA commands, the context should be initialized
and connected to CM_ID with ucma_create_id(). In case user skips
this step, he can provide non-valid ctx without CM_ID and cause
to multiple NULL dereferences.

Also there are situations where the create_id can be raced with
other user access, ensure that the context is only shared to
other threads once it is fully initialized to avoid the races.

Linux commit:
e8980d67d6017c8eee8f9c35f782c4bd68e004c9

MFC after:		1 week
Sponsored by:		Mellanox Technologies
This commit is contained in:
Hans Petter Selasky 2018-07-17 09:13:11 +00:00
parent f4546fa376
commit 7477a89ae2

View File

@ -124,7 +124,7 @@ static inline struct ucma_context *_ucma_find_context(int id,
ctx = idr_find(&ctx_idr, id);
if (!ctx)
ctx = ERR_PTR(-ENOENT);
else if (ctx->file != file)
else if (ctx->file != file || !ctx->cm_id)
ctx = ERR_PTR(-EINVAL);
return ctx;
}
@ -446,6 +446,7 @@ static ssize_t ucma_create_id(struct ucma_file *file, const char __user *inbuf,
struct rdma_ucm_create_id cmd;
struct rdma_ucm_create_id_resp resp;
struct ucma_context *ctx;
struct rdma_cm_id *cm_id;
enum ib_qp_type qp_type;
int ret;
@ -465,11 +466,10 @@ static ssize_t ucma_create_id(struct ucma_file *file, const char __user *inbuf,
if (!ctx)
return -ENOMEM;
ctx->uid = cmd.uid;
ctx->cm_id = rdma_create_id(TD_TO_VNET(curthread),
ucma_event_handler, ctx, cmd.ps, qp_type);
if (IS_ERR(ctx->cm_id)) {
ret = PTR_ERR(ctx->cm_id);
cm_id = rdma_create_id(TD_TO_VNET(curthread),
ucma_event_handler, ctx, cmd.ps, qp_type);
if (IS_ERR(cm_id)) {
ret = PTR_ERR(cm_id);
goto err1;
}
@ -479,10 +479,12 @@ static ssize_t ucma_create_id(struct ucma_file *file, const char __user *inbuf,
ret = -EFAULT;
goto err2;
}
ctx->cm_id = cm_id;
return 0;
err2:
rdma_destroy_id(ctx->cm_id);
rdma_destroy_id(cm_id);
err1:
mutex_lock(&mut);
idr_remove(&ctx_idr, ctx->id);