mirror of
https://github.com/torvalds/linux.git
synced 2026-09-24 06:24:02 +02:00
RDMA/ucma: Serialize join and leave on copy_to_user failure
rdma_join_multicast() queues RoCE work that later reads the ucma_multicast
through event->param.ud.private_data, then list_add()s the CMA multicast
at the head of id_priv->mc_list. rdma_leave_multicast() matches only by
sockaddr and destroys the first hit.
ucma_process_join() used to drop ctx->mutex after a successful join and
retake it only if copy_to_user() failed. Two concurrent JOIN_MCAST calls
with the same address can therefore insert a second CMA entry before the
first thread's leave. leave then cancels the newer work and the older
worker still dereferences the ucma_multicast that the first thread frees.
Keep ctx->mutex held from rdma_join_multicast() through copy_to_user() and,
on -EFAULT, through rdma_leave_multicast() so leave cannot miss this join.
Do not leave if join itself failed: that path never published this address
on mc_list, and a leave-by-addr would destroy an earlier successful join.
Reported-by: syzbot+a6ffe86390c8a6afc818@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=a6ffe86390c8a6afc818
Fixes: fe454dc31e ("RDMA/ucma: Fix use-after-free bug in ucma_create_uevent")
Cc: stable@vger.kernel.org
Signed-off-by: Quanye Yang <quanyeyang@proton.me>
Link: https://patch.msgid.link/20260831-rdma-ucma-mc-uaf-v1-1-b8eeb7046aff@proton.me
Signed-off-by: Leon Romanovsky <leon@kernel.org>
This commit is contained in:
parent
2ae16aaa78
commit
662ade4de9
|
|
@ -1556,9 +1556,10 @@ static ssize_t ucma_process_join(struct ucma_file *file,
|
|||
mutex_lock(&ctx->mutex);
|
||||
ret = rdma_join_multicast(ctx->cm_id, (struct sockaddr *)&mc->addr,
|
||||
join_state, mc);
|
||||
mutex_unlock(&ctx->mutex);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
mutex_unlock(&ctx->mutex);
|
||||
goto err_xa_erase;
|
||||
}
|
||||
|
||||
resp.id = mc->id;
|
||||
if (copy_to_user(u64_to_user_ptr(cmd->response),
|
||||
|
|
@ -1566,6 +1567,7 @@ static ssize_t ucma_process_join(struct ucma_file *file,
|
|||
ret = -EFAULT;
|
||||
goto err_leave_multicast;
|
||||
}
|
||||
mutex_unlock(&ctx->mutex);
|
||||
|
||||
xa_store(&multicast_table, mc->id, mc, 0);
|
||||
|
||||
|
|
@ -1573,7 +1575,6 @@ static ssize_t ucma_process_join(struct ucma_file *file,
|
|||
return 0;
|
||||
|
||||
err_leave_multicast:
|
||||
mutex_lock(&ctx->mutex);
|
||||
rdma_leave_multicast(ctx->cm_id, (struct sockaddr *) &mc->addr);
|
||||
mutex_unlock(&ctx->mutex);
|
||||
ucma_cleanup_mc_events(mc);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user