]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
RDMA/rxe: Fix double free in rxe_srq_from_init
authorJiasheng Jiang <jiashengjiangcool@gmail.com>
Mon, 12 Jan 2026 01:54:12 +0000 (01:54 +0000)
committerLeon Romanovsky <leon@kernel.org>
Thu, 15 Jan 2026 09:59:53 +0000 (04:59 -0500)
In rxe_srq_from_init(), the queue pointer 'q' is assigned to
'srq->rq.queue' before copying the SRQ number to user space.
If copy_to_user() fails, the function calls rxe_queue_cleanup()
to free the queue, but leaves the now-invalid pointer in
'srq->rq.queue'.

The caller of rxe_srq_from_init() (rxe_create_srq) eventually
calls rxe_srq_cleanup() upon receiving the error, which triggers
a second rxe_queue_cleanup() on the same memory, leading to a
double free.

The call trace looks like this:
   kmem_cache_free+0x.../0x...
   rxe_queue_cleanup+0x1a/0x30 [rdma_rxe]
   rxe_srq_cleanup+0x42/0x60 [rdma_rxe]
   rxe_elem_release+0x31/0x70 [rdma_rxe]
   rxe_create_srq+0x12b/0x1a0 [rdma_rxe]
   ib_create_srq_user+0x9a/0x150 [ib_core]

Fix this by moving 'srq->rq.queue = q' after copy_to_user.

Fixes: aae0484e15f0 ("IB/rxe: avoid srq memory leak")
Signed-off-by: Jiasheng Jiang <jiashengjiangcool@gmail.com>
Link: https://patch.msgid.link/20260112015412.29458-1-jiashengjiangcool@gmail.com
Reviewed-by: Zhu Yanjun <yanjun.Zhu@linux.dev>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
drivers/infiniband/sw/rxe/rxe_srq.c

index 2a234f26ac1044aeaad2fb251c9389dde96d4e75..c9a7cd38953d316cc51a2326a3a8ade20e277a91 100644 (file)
@@ -77,9 +77,6 @@ int rxe_srq_from_init(struct rxe_dev *rxe, struct rxe_srq *srq,
                goto err_free;
        }
 
-       srq->rq.queue = q;
-       init->attr.max_wr = srq->rq.max_wr;
-
        if (uresp) {
                if (copy_to_user(&uresp->srq_num, &srq->srq_num,
                                 sizeof(uresp->srq_num))) {
@@ -88,6 +85,9 @@ int rxe_srq_from_init(struct rxe_dev *rxe, struct rxe_srq *srq,
                }
        }
 
+       srq->rq.queue = q;
+       init->attr.max_wr = srq->rq.max_wr;
+
        return 0;
 
 err_free: