From: sashiko-bot@kernel.org
To: "Jason Gunthorpe" <jgg@nvidia.com>
Cc: linux-hyperv@vger.kernel.org
Subject: Re: [PATCH v3 02/10] IB/rdmavt: Don't abuse udata and ib_respond_udata()
Date: Wed, 13 May 2026 03:12:36 +0000 [thread overview]
Message-ID: <20260513031237.4280DC2BCB0@smtp.kernel.org> (raw)
In-Reply-To: <2-v3-4effdebad75a+e1-rdma_udata_rep_jgg@nvidia.com>
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [Critical] TOCTOU heap buffer overflow due to unvalidated `num_sge` from user-shared memory.
- [High] Memory leak of the kernel queue structure (`srq->rq.kwq`) on user-backed SRQ modifications.
- [High] Locking imbalance and freeing memory while locked.
- [High] Inconsistent state and Use-After-Free on error path.
- [Low] Uninitialized variable compiler warning for `offset_addr`.
--
commit dac7699d9e58c179b3a8859ac64da79e5fd21f46
Author: Jason Gunthorpe <jgg@ziepe.ca>
Subject: IB/rdmavt: Don't abuse udata and ib_respond_udata()
This commit modifies rvt_modify_srq to use copy_to_user directly instead
of ib_copy_to_udata for returning the offset address.
> diff --git a/drivers/infiniband/sw/rdmavt/srq.c b/drivers/infiniband/sw/rdmavt/srq.c
> index fe125bf85b272..d022aa56c5bfd 100644
> --- a/drivers/infiniband/sw/rdmavt/srq.c
> +++ b/drivers/infiniband/sw/rdmavt/srq.c
> @@ -128,6 +128,7 @@ int rvt_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
> struct rvt_srq *srq = ibsrq_to_rvtsrq(ibsrq);
> struct rvt_dev_info *dev = ib_to_rvt(ibsrq->device);
> struct rvt_rq tmp_rq = {};
> + __u64 offset_addr;
> int ret = 0;
>
> if (attr_mask & IB_SRQ_MAX_WR) {
Could hoisting offset_addr lead to a compiler warning for being potentially
uninitialized?
The compiler might assume udata->inlen could change concurrently across the
spin_lock_irq() and spin_unlock_irq() calls. If the first check fails
but the second one passes:
if (udata && udata->inlen >= sizeof(__u64))
Does this allow offset_addr to be used without initialization?
[ ... ]
> @@ -149,19 +150,17 @@ int rvt_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
> return -ENOMEM;
> /* Check that we can write the offset to mmap. */
> if (udata && udata->inlen >= sizeof(__u64)) {
> - __u64 offset_addr;
> __u64 offset = 0;
>
> ret = ib_copy_from_udata(&offset_addr, udata,
> sizeof(offset_addr));
> if (ret)
> goto bail_free;
> - udata->outbuf = (void __user *)
> - (unsigned long)offset_addr;
> - ret = ib_copy_to_udata(udata, &offset,
> - sizeof(offset));
> - if (ret)
> + if (copy_to_user(u64_to_user_ptr(offset_addr), &offset,
> + sizeof(offset))) {
> + ret = -EFAULT;
> goto bail_free;
> + }
> }
>
> spin_lock_irq(&srq->rq.kwq->c_lock);
Can this code leak the kernel queue structure?
When resizing a user-backed SRQ, the code fetches elements from the old
user-mapped queue. In the udata path, okwq is left as NULL:
if (udata) {
owq = srq->rq.wq;
head = RDMA_READ_UAPI_ATOMIC(owq->head);
tail = RDMA_READ_UAPI_ATOMIC(owq->tail);
} else {
okwq = srq->rq.kwq;
...
When it later calls kvfree(okwq), it seems nothing is freed, which could
permanently leak the old kwq structure.
Is there a lock imbalance here when the queue is replaced?
The original queue is locked with:
spin_lock_irq(&srq->rq.kwq->c_lock);
But then the queue pointer is replaced:
srq->rq.kwq = tmp_rq.kwq;
When the lock is released:
spin_unlock_irq(&srq->rq.kwq->c_lock);
Does this unlock the new queue instead of the old one, and then free the old
queue via kvfree(okwq) while its lock is still held?
Can the loop migrating WQEs overflow the destination buffer?
The number of scatter-gather elements is read directly from user-shared
memory:
wqe = rvt_get_rwqe_ptr(&srq->rq, tail);
p->wr_id = wqe->wr_id;
p->num_sge = wqe->num_sge;
for (i = 0; i < wqe->num_sge; i++)
p->sg_list[i] = wqe->sg_list[i];
If a userspace program concurrently modifies num_sge to a large value, could
this loop exceed the bounds of tmp_rq.kwq->curr_wq, since the destination
size was calculated based on srq->rq.max_sge?
[ ... ]
> @@ -236,10 +235,10 @@ int rvt_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
> * See rvt_mmap() for details.
> */
> if (udata && udata->inlen >= sizeof(__u64)) {
> - ret = ib_copy_to_udata(udata, &ip->offset,
> - sizeof(ip->offset));
> - if (ret)
> - return ret;
> + if (copy_to_user(u64_to_user_ptr(offset_addr),
> + &ip->offset,
> + sizeof(ip->offset)))
> + return -EFAULT;
> }
>
Does returning -EFAULT here leave the kernel and userspace in an inconsistent
state?
At this point, the kernel has already applied the SRQ size change, replaced
the queue, and permanently freed the old memory:
vfree(owq);
kvfree(okwq);
If copy_to_user fails and returns -EFAULT, userspace might interpret this as
a failed resize and continue using its existing memory mapping of the old
queue. Could this lead to a use-after-free since the pages have already
been freed?
--
Sashiko AI review · https://sashiko.dev/#/patchset/0-v3-4effdebad75a+e1-rdma_udata_rep_jgg@nvidia.com?part=2
next prev parent reply other threads:[~2026-05-13 3:12 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-12 0:09 [PATCH v3 00/10] Convert all drivers to the new udata response flow Jason Gunthorpe
2026-05-12 0:09 ` [PATCH v3 01/10] RDMA: Use ib_is_udata_in_empty() for places calling ib_is_udata_cleared() Jason Gunthorpe
2026-05-12 0:09 ` [PATCH v3 02/10] IB/rdmavt: Don't abuse udata and ib_respond_udata() Jason Gunthorpe
2026-05-13 3:12 ` sashiko-bot [this message]
2026-05-13 11:38 ` Jason Gunthorpe
2026-05-13 13:45 ` Dennis Dalessandro
2026-05-12 0:09 ` [PATCH v3 03/10] RDMA: Convert drivers using min to ib_respond_udata() Jason Gunthorpe
2026-05-12 0:09 ` [PATCH v3 04/10] RDMA: Convert drivers using sizeof() " Jason Gunthorpe
2026-05-12 0:09 ` [PATCH v3 05/10] RDMA/cxgb4: Convert " Jason Gunthorpe
2026-05-12 0:09 ` [PATCH v3 06/10] RDMA/qedr: Replace qedr_ib_copy_to_udata() with ib_respond_udata() Jason Gunthorpe
2026-05-13 19:07 ` sashiko-bot
2026-05-12 0:09 ` [PATCH v3 07/10] RDMA/mlx: Replace response_len " Jason Gunthorpe
2026-05-12 0:09 ` [PATCH v3 08/10] RDMA: Use proper driver data response structs instead of open coding Jason Gunthorpe
2026-05-12 0:09 ` [PATCH v3 09/10] RDMA: Add missed = {} initialization to uresp structs Jason Gunthorpe
2026-05-12 0:09 ` [PATCH v3 10/10] RDMA: Replace memset with = {} pattern for ib_respond_udata() Jason Gunthorpe
2026-05-13 20:59 ` sashiko-bot
2026-05-13 23:23 ` Jason Gunthorpe
2026-05-14 8:22 ` [PATCH v3 00/10] Convert all drivers to the new udata response flow Leon Romanovsky
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=20260513031237.4280DC2BCB0@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=jgg@nvidia.com \
--cc=linux-hyperv@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/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