From: Zhu Yanjun <yanjun.zhu@linux.dev>
To: hello messi <Hello_Messi_10@outlook.com>,
"zyjzyj2000@gmail.com" <zyjzyj2000@gmail.com>,
"yanjun.zhu@linux.dev" <yanjun.zhu@linux.dev>
Cc: "jgg@ziepe.ca" <jgg@ziepe.ca>,
"leon@kernel.org" <leon@kernel.org>,
"linux-rdma@vger.kernel.org" <linux-rdma@vger.kernel.org>
Subject: Re: [PATCH] RDMA/rxe: require ODP MR iova to equal the umem user address
Date: Mon, 12 Oct 2026 21:03:01 -0700 [thread overview]
Message-ID: <55731898-1cc7-4d6b-af6c-18f369aff79c@linux.dev> (raw)
In-Reply-To: <SY7P300MB0292E9E08F0890A2C31CFD96DE972@SY7P300MB0292.AUSP300.PROD.OUTLOOK.COM>
在 2026/10/4 7:07, hello messi 写道:
> Hello,
> I found an out-of-bounds access in the RXE ODP MR path when an ODP
> memory region is registered with an IOVA that differs from the user
> virtual address used to create the underlying |ib_umem_odp|.
> The issue was reproduced on Linux v7.2.8 with Soft-RoCE (|rxe0|).
> *Environment*
Please read the files in
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process
Thanks a lot.
Yanjun Zhu
>
> |Kernel: Linux v7.2.8 RDMA device: Soft-RoCE (rxe0)
> CONFIG_INFINIBAND_ON_DEMAND_PAGING=y CONFIG_RDMA_RXE=m CONFIG_KASAN=y
> CONFIG_KASAN_GENERIC=y CONFIG_KASAN_INLINE=y CONFIG_DEBUG_INFO=y
> CONFIG_DEBUG_INFO_DWARF5=y |
>
> *Root cause*
> |rxe_odp_mr_init_user()| accepts |start| and |iova| independently:
>
> |umem_odp = ib_umem_odp_get(&rxe->ib_dev, start, length, access_flags,
> &rxe_mn_ops); ... mr->ibmr.length = length; mr-
> >ibmr.iova = iova; |
>
> The ODP page list is sized according to the UMEM user address range,
> while RXE calculates the page-list index from the MR IOVA:
>
> |idx = (iova - ib_umem_start(umem_odp)) >> umem_odp->page_shift; |
>
> There is no validation that the resulting index is within |umem_odp-
> >map.pfn_list|.
> |mr_check_range()| does not prevent this because it validates the IOVA
> against |mr->ibmr.iova| and |mr->ibmr.length|, rather than against the
> underlying UMEM user address range.
> *Reproduction*
> A minimal reproducer is attached as |poc.c|.
> The reproducer creates a one-page ODP MR with a deliberately divergent IOVA:
>
> |user VA : 0x55b0f4fb2000 ODP IOVA : 0x55b1f4fb2000 IOVA delta
> : 0x100000000 ODP length : 0x1000 expected idx : 0x100000 |
>
> The resulting index is |0x100000|, while the one-page ODP |pfn_list|
> only contains the entry corresponding to the valid UMEM page.
> The reproducer then submits an RC atomic-write operation using the MR
> rkey and the divergent IOVA, reaching:
>
> |rxe_odp_do_atomic_write() -> rxe_odp_iova_to_index() -> umem_odp-
> >map.pfn_list[index] -> hmm_pfn_to_page() -> kmap_local_page() ->
> smp_store_release() |
>
> The reproducer can be executed by an unprivileged user.
> *KASAN/Oops*
> The reproducer triggers:
>
> |Oops: general protection fault, probably for non-canonical address ...
> KASAN: maybe wild-memory-access ... CPU: 3 UID: 0 PID: 13495 Comm:
> kworker/u514:1 Workqueue: rxe_wq do_work [rdma_rxe] RIP:
> 0010:rxe_odp_do_atomic_write+0x1ba/0x3e0 [rdma_rxe] |
>
> Using |faddr2line|:
>
> |rxe_odp_do_atomic_write+0x1ba/0x3e0: rxe_odp_do_atomic_write at /home/
> kali/linux-7.2.8/drivers/infiniband/sw/rxe/rxe_odp.c:410 |
>
> Line 410 is:
>
> |smp_store_release(&va[page_offset >> 3], value); |
>
> The atomic value supplied by the reproducer was:
>
> |atomic value=0x4141414142424242 |
>
> The same value was present in the kernel register state at the time of
> the fault.
> This demonstrates an out-of-bounds ODP |pfn_list| access in the RXE
> atomic-write path. I have not assumed arbitrary kernel write or code
> execution from this crash; the demonstrated impact is a kernel memory-
> safety violation leading to a kernel fault.
> *Proposed fix*
> The existing ODP index calculation assumes that the MR IOVA and the UMEM
> user address refer to the same address range. The simplest fix is to
> reject an ODP MR when these addresses differ:
>
> |diff --git a/drivers/infiniband/sw/rxe/rxe_odp.c b/drivers/infiniband/
> sw/rxe/rxe_odp.c index ... --- a/drivers/infiniband/sw/rxe/rxe_odp.c +++
> b/drivers/infiniband/sw/rxe/rxe_odp.c @@ -98,6 +98,9 @@ int
> rxe_odp_mr_init_user(struct rxe_dev *rxe, u64 start, u64 length,
> /* Never reach here, for implicit ODP is not implemented. */|
> rxe_odp_do_atomic_op()| } + if (iova != start) +
> return -EINVAL; + umem_odp = ib_umem_odp_get(&rxe->ib_dev,
> start, length, access_flags,
> &rxe_mn_ops); |
>
> This restores the invariant required by the existing ODP index
> calculation and prevents a divergent IOVA from producing an out-of-range
> |pfn_list| index.
> Please consider applying an appropriate fix to current mainline and
> stable kernels as appropriate.
> The reproducer is attached as |poc.c|, and the relevant KASAN/Oops
> output is attached as |kasan-oops.txt|.
> Thanks,
> hellomessi
>
prev parent reply other threads:[~2026-10-13 4:03 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-04 14:07 [PATCH] RDMA/rxe: require ODP MR iova to equal the umem user address hello messi
2026-10-13 2:33 ` Chenguang Zhao
2026-10-13 4:03 ` Zhu Yanjun [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=55731898-1cc7-4d6b-af6c-18f369aff79c@linux.dev \
--to=yanjun.zhu@linux.dev \
--cc=Hello_Messi_10@outlook.com \
--cc=jgg@ziepe.ca \
--cc=leon@kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=zyjzyj2000@gmail.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox