Commit f48b7269 authored by Matan Barak's avatar Matan Barak Committed by Doug Ledford

IB/core: Add lock to multicast handlers

When two handlers used the same object in the old schema, we blocked
the process in the kernel. The new schema just returns -EBUSY. This
could lead to different behaviour in applications between the old
schema and the new schema. In most cases, using such handlers
concurrently could lead to crashing the process. For example, if
thread A destroys a QP and thread B modifies it, we could have the
destruction happens before the modification. In this case, we are
accessing freed memory which could lead to crashing the process.
This is true for most cases. However, attaching and detaching
a multicast address from QP concurrently is safe. Therefore, we
preserve the original behaviour by adding a lock there.
Signed-off-by: default avatarMatan Barak <matanb@mellanox.com>
Reviewed-by: default avatarYishai Hadas <yishaih@mellanox.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent fd3c7904
...@@ -163,6 +163,8 @@ struct ib_usrq_object { ...@@ -163,6 +163,8 @@ struct ib_usrq_object {
struct ib_uqp_object { struct ib_uqp_object {
struct ib_uevent_object uevent; struct ib_uevent_object uevent;
/* lock for mcast list */
struct mutex mcast_lock;
struct list_head mcast_list; struct list_head mcast_list;
struct ib_uxrcd_object *uxrcd; struct ib_uxrcd_object *uxrcd;
}; };
......
...@@ -1352,6 +1352,7 @@ static int create_qp(struct ib_uverbs_file *file, ...@@ -1352,6 +1352,7 @@ static int create_qp(struct ib_uverbs_file *file,
return PTR_ERR(obj); return PTR_ERR(obj);
obj->uxrcd = NULL; obj->uxrcd = NULL;
obj->uevent.uobject.user_handle = cmd->user_handle; obj->uevent.uobject.user_handle = cmd->user_handle;
mutex_init(&obj->mcast_lock);
if (cmd_sz >= offsetof(typeof(*cmd), rwq_ind_tbl_handle) + if (cmd_sz >= offsetof(typeof(*cmd), rwq_ind_tbl_handle) +
sizeof(cmd->rwq_ind_tbl_handle) && sizeof(cmd->rwq_ind_tbl_handle) &&
...@@ -2589,6 +2590,7 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file, ...@@ -2589,6 +2590,7 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file,
obj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject); obj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject);
mutex_lock(&obj->mcast_lock);
list_for_each_entry(mcast, &obj->mcast_list, list) list_for_each_entry(mcast, &obj->mcast_list, list)
if (cmd.mlid == mcast->lid && if (cmd.mlid == mcast->lid &&
!memcmp(cmd.gid, mcast->gid.raw, sizeof mcast->gid.raw)) { !memcmp(cmd.gid, mcast->gid.raw, sizeof mcast->gid.raw)) {
...@@ -2612,6 +2614,7 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file, ...@@ -2612,6 +2614,7 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file,
kfree(mcast); kfree(mcast);
out_put: out_put:
mutex_unlock(&obj->mcast_lock);
uobj_put_obj_read(qp); uobj_put_obj_read(qp);
return ret ? ret : in_len; return ret ? ret : in_len;
...@@ -2636,6 +2639,7 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file, ...@@ -2636,6 +2639,7 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
return -EINVAL; return -EINVAL;
obj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject); obj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject);
mutex_lock(&obj->mcast_lock);
ret = ib_detach_mcast(qp, (union ib_gid *) cmd.gid, cmd.mlid); ret = ib_detach_mcast(qp, (union ib_gid *) cmd.gid, cmd.mlid);
if (ret) if (ret)
...@@ -2650,6 +2654,7 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file, ...@@ -2650,6 +2654,7 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
} }
out_put: out_put:
mutex_unlock(&obj->mcast_lock);
uobj_put_obj_read(qp); uobj_put_obj_read(qp);
return ret ? ret : in_len; return ret ? ret : in_len;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment