From: "yanjun.zhu" <yanjun.zhu@linux.dev>
To: Peiyang He <peiyang_he@smail.nju.edu.cn>,
jgg@ziepe.ca, leon@kernel.org, Zhu Yanjun <yanjun.zhu@linux.dev>
Cc: "syzkaller@googlegroups.com" <syzkaller@googlegroups.com>,
linux-rdma@vger.kernel.org,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: Re: [BUG] RDMA/rxe: memory leak in rxe_qp_from_attr
Date: Thu, 30 Jul 2026 11:07:33 -0700 [thread overview]
Message-ID: <a35ece69-60af-4a82-a0cd-da1aeb9c60dc@linux.dev> (raw)
In-Reply-To: <357830C4A3236804+c7b5ccba-01ba-468f-97c8-cb6053a8b771@smail.nju.edu.cn>
On 7/30/26 1:40 AM, Peiyang He wrote:
> Hello Linux kernel developers and maintainers,
>
> We hit a memory leak in rxe_qp_from_attr when fuzzing RDMA/RXE with Syzkaller.
>
> The leak is caused by two concurrent MODIFY_QP commands which both modify
> IB_QP_MAX_DEST_RD_ATOMIC on the same RXE QP. They are not serialized by a
> QP-wide lock. The uverbs layer only holds shared UVERBS_LOOKUP_READ access
> to the QP, so two threads may enter rxe_modify_qp() and then rxe_qp_from_attr()
> for the same object at the same time.
> It can leak a whole qp->resp.resources array each time triggered.
>
> The version of the kernel under test is commit 8cd9520d35a6c38db6567e97dd93b1f11f185dc6 (tag v7.1).
> We believe this OOB bug is still possible in the latest kernel.
>
> The relevant kernel config is:
>
> CONFIG_NET=y
> CONFIG_INET=y
> CONFIG_INFINIBAND=y
> CONFIG_INFINIBAND_USER_ACCESS=y
> CONFIG_INFINIBAND_ADDR_TRANS=y
> CONFIG_RDMA_RXE=y
> CONFIG_DEBUG_FS=y
> CONFIG_DEBUG_KERNEL=y
> CONFIG_DEBUG_KMEMLEAK=y
> CONFIG_DEBUG_KMEMLEAK_AUTO_SCAN=y
>
> =========================
> Original Syzkaller report
> =========================
>
> BUG: memory leak
> unreferenced object 0xffff8880120ef800 (size 1024):
> comm "syz.0.1478", pid 15130, jiffies 4295203468
> hex dump (first 32 bytes):
> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> backtrace (crc 0):
> kmemleak_alloc_recursive include/linux/kmemleak.h:44 [inline]
> slab_post_alloc_hook mm/slub.c:4575 [inline]
> slab_alloc_node mm/slub.c:4899 [inline]
> __do_kmalloc_node mm/slub.c:5295 [inline]
> __kmalloc_noprof+0x552/0x850 mm/slub.c:5308
> kmalloc_noprof include/linux/slab.h:954 [inline]
> kzalloc_noprof include/linux/slab.h:1188 [inline]
> alloc_rd_atomic_resources drivers/infiniband/sw/rxe/rxe_qp.c:155 [inline]
> rxe_qp_from_attr+0x3f8/0x2150 drivers/infiniband/sw/rxe/rxe_qp.c:714
> rxe_modify_qp+0x1e2/0x530 drivers/infiniband/sw/rxe/rxe_verbs.c:623
> ib_security_modify_qp+0x223/0xfa0 drivers/infiniband/core/security.c:625
> _ib_modify_qp+0x333/0xec0 drivers/infiniband/core/verbs.c:1915
> modify_qp+0x13ca/0x1940 drivers/infiniband/core/uverbs_cmd.c:1932
> ib_uverbs_modify_qp+0xcb/0x120 drivers/infiniband/core/uverbs_cmd.c:1958
> ib_uverbs_write+0xb86/0x1030 drivers/infiniband/core/uverbs_main.c:680
> vfs_write+0x2aa/0x1070 fs/read_write.c:686
> ksys_write+0x1f8/0x250 fs/read_write.c:740
> do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
> do_syscall_64+0x116/0x800 arch/x86/entry/syscall_64.c:94
> entry_SYSCALL_64_after_hwframe+0x77/0x7f
Thanks for the detailed analysis.
From the RDMA usage perspective, concurrent MODIFY_QP operations on the
same QP are not normally expected in real workloads. Typically, after a
QP is created and transitioned to the required state, applications use
it for communication. If a QP attribute or resource needs to be
modified, it is usually done by the owner thread/process in a serialized
manner rather than by multiple threads concurrently modifying the same QP.
However, since the kernel interface does allow such a scenario,
especially under malicious input or fuzzing environments, the driver
should still handle this case safely.
For the fix, I agree that the resource replacement path needs proper
serialization. My preference would be to reuse an existing QP lock if
there is one suitable for protecting QP attribute modifications, rather
than introducing a new `rd_atomic_mutex` specifically for this field.
Adding a new lock may increase locking complexity and could introduce
additional lock ordering concerns.
It may also be worth checking whether other QP attribute modification
paths have similar concurrency assumptions. If the QP modify path is
generally expected to be serialized, protecting the broader QP
modification operation with an existing lock might provide a more
consistent solution.
Zhu Yanjun
>
> ==========
> Root cause
> ==========
>
> modify_qp() obtains the QP through uobj_get_obj_read() and retains the
> UVERBS_LOOKUP_READ access. This is a shared lookup, since UVERBS_LOOKUP_READ
> increments a positive use count and only rejects an object whose count is -1,
> whereas UVERBS_LOOKUP_WRITE is exclusive. Therefore, the two MODIFY_QP commands
> may execute rxe_modify_qp() concurrently. rxe_modify_qp() directly calls
> rxe_qp_from_attr() without a QP-wide lock.
>
> For IB_QP_MAX_DEST_RD_ATOMIC, rxe_qp_from_attr() updates qp->attr.max_dest_rd_atomic,
> frees the current qp->resp.resources pointer and calls alloc_rd_atomic_resources().
> The allocator initializes the responder indices and assigns the result of kzalloc_objs()
> to qp->resp.resources. Neither the resource replacement sequence nor the pointer assignment
> is serialized.
>
> The relevant QP starts with qp->resp.resources == NULL. Let P0 and P1 be the
> two resp_res arrays allocated by the concurrent commands. The following
> race interleaving leaks P1:
>
> CPU0 CPU1
> ==== ====
>
> MODIFY_QP()
> -> rxe_qp_from_attr()
> -> alloc_rd_atomic_resources()
> -> P0 = kzalloc_objs()
> /* preempted after kzalloc_objs() returns P0,
> before the assignment to qp->resp.resources */
>
> MODIFY_QP()
> -> rxe_qp_from_attr()
> -> alloc_rd_atomic_resources()
> -> P1 = kzalloc_objs()
> -> qp->resp.resources = P1
>
> -> qp->resp.resources = P0
> /* overwrites the only reference to P1 */
>
> When the QP is later cleaned up, rxe_qp_do_cleanup() calls free_rd_atomic_resources()
> and can only free the pointer currently stored in qp->resp.resources, namely P0.
> P1 has no remaining reference to it and is reported by kmemleak.
>
> =============
> Suggested fix
> =============
>
> First of all, I wonder is concurrent modify_qp() on the same QP supposed
> to be supported by design? If yes, then the rd_atomic resource replacement
> path needs explicit serialization. We could add a rd_atomic_mutex in
> struct rxe_qp, init it in rxe_qp_init_misc(). Then, the IB_QP_MAX_DEST_RD_ATOMIC
> branch in rxe_qp_from_attr() and rxe_qp_reset() should be protected by this lock.
>
> I am happy to send a patch if this fix is needed and reasonable.
>
> Thanks,
> Peiyang
>
prev parent reply other threads:[~2026-07-30 18:07 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-30 8:40 [BUG] RDMA/rxe: memory leak in rxe_qp_from_attr Peiyang He
2026-07-30 18:07 ` yanjun.zhu [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=a35ece69-60af-4a82-a0cd-da1aeb9c60dc@linux.dev \
--to=yanjun.zhu@linux.dev \
--cc=jgg@ziepe.ca \
--cc=leon@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=peiyang_he@smail.nju.edu.cn \
--cc=syzkaller@googlegroups.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.