mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: netdev-bot+sashiko@kernel.org
To: lian@is.s.u-tokyo.ac.jp
Cc: ericvh@kernel.org, lucho@ionkov.net, asmadeus@codewreck.org,
	davem@davemloft.net, edumazet@kernel.org, kuba@kernel.org,
	pabeni@redhat.com, linux_oss@crudebyte.com, horms@kernel.org,
	viro@zeniv.linux.org.uk, tomasbortoli@gmail.com,
	chirantan@chromium.org, groug@kaod.org,
	aneesh.kumar@linux.vnet.ibm.com, v9fs@lists.linux.dev,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
	shina@is.s.u-tokyo.ac.jp, stable@vger.kernel.org
Subject: Re: [PATCH 5/5] 9p/virtio: keep zero-copy buffers until the device returns them
Date: Thu, 12 Nov 2026 07:53:13 +0000	[thread overview]
Message-ID: <179446999308.2199510.11222629754827394625@kernel.org> (raw)
In-Reply-To: <20261109105251.2545764-6-lian@is.s.u-tokyo.ac.jp>

Thank you for your contribution! Sashiko AI review found 1 potential
issue(s) to consider.

Critical: 0 · High: 1 · Medium: 0 · Low: 0

If you believe none of the issues are legitimate, please reply to each
issue of Medium severity or higher and explain why the AI is wrong.
If any of them are legitimate and you plan to respin, please let patchwork
know by including "pw-bot: cr" as a separate line at the end of your reply
(one such reply per series is enough).

- [High] The patch adds an unconditional `wait_event_idle(req->wq,
  !smp_load_acquire(&req->zc_pages))` to p9_client_zc_rpc()…

--

9p/virtio: keep zero-copy buffers until the device returns them

This patch fixes a use-after-free. If a fatal signal ends the wait in
p9_virtio_zc_request() while the device still holds the request, a
misbehaving device can later write into zero-copy buffers that have
already been freed. Freeing of the pinned pages moves to req_done() via
a per-request struct p9_zc_pages, and p9_client_zc_rpc() now waits until
the device returns the request.

> diff --git a/net/9p/client.c b/net/9p/client.c
> index 15bb939087165..34be0d2652d4e 100644
> --- a/net/9p/client.c
> +++ b/net/9p/client.c

[ ... ]

> @@ -707,6 +708,8 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type,
>  		 * into rc only while it waits.
>  		 */
>  	}
> +	/* The caller may reuse the payload once the transport releases it */
> +	wait_event_idle(req->wq, !smp_load_acquire(&req->zc_pages));

[Severity: High]

Can this wait leave a killed task stuck forever?

wait_event_idle() sleeps in TASK_IDLE and has no timeout, so SIGKILL
cannot end it. khungtaskd also skips TASK_NOLOAD tasks, so the hang
would never be reported.

The only code that clears req->zc_pages and wakes req->wq is in
req_done(). It runs only after virtqueue_get_buf() returns this exact
request:

net/9p/trans_virtio.c:req_done() {
    ...
	while ((req = virtqueue_get_buf(chan->vq, &len)) != NULL) {
		...
		if (req->zc_pages) {
			if (req->zc_pages->held)
				p9_zc_release(req->zc_pages);
			smp_store_release(&req->zc_pages, NULL);
			wake_up(&req->wq);
		}
    ...
}

On a fatal signal, p9_virtio_zc_request() hands the pages to req_done()
and returns with req->zc_pages still set:

		held = req->zc_pages;
		if (held)
			zc->held = true;
		spin_unlock_irqrestore(&chan->lock, flags);
		if (held)
			return err;

p9_client_zc_rpc() sends a TFLUSH only when c->status == Connected.
There are two cases where no flush is sent but the new wait still runs:

  - after umount -f, via
    v9fs_session_begin_cancel()->p9_client_begin_disconnect()
  - after an earlier -EIO has set Disconnected

If a flush is sent, p9_client_rpc(TFLUSH) can itself return early on the
fatal signal. In every case the wait above runs.

If the device never returns the original descriptor, nothing else clears
zc_pages. That can happen in several ways:

  - virtqueue_kick() fails and sets vq->broken. Its return value is
    ignored right after req->zc_pages = zc in p9_virtio_zc_request().
  - surprise PCI removal. virtio_pci_remove() calls
    virtio_break_device(), and vring_interrupt() then stops calling the
    callback.
  - a hung backend, or a device that answers the TFLUSH but keeps the
    original descriptor. This is the misbehaving-device case the commit
    message describes.

Before this patch, a killed task always left this path.

Once stuck, the task keeps any VFS locks its caller holds and cannot
finish exiting or coredumping. Its pinned pages stay counted in
vp_pinned, which throttles p9_get_mapped_pages() on other mounts. It
also keeps the mount busy, so p9_virtio_close() never runs and
chan->inuse stays true. p9_virtio_remove() then loops here and never
reaches virtio_reset_device()/del_vqs():

	while (chan->inuse) {
		mutex_unlock(&virtio_9p_lock);
		msleep(250);

That is a circular wait. Remove waits for umount, umount waits for the
task, and the task waits for a req_done() that never runs for this
request.

For pinned user pages (need_drop == 1), the zc->held hand-off already
keeps the pages alive until req_done(), so the unconditional wait seems
to be needed only for kvec buffers. Could the wait be limited to that
case, or bounded or made killable? Alternatively, could the transport
clear zc_pages and wake waiters when the vq is broken or torn down?

The commit message also does not mention that killed tasks can now
block on the device with no time limit. Should it?

>  recalc_sigpending:
>  	if (sigpending) {
>  		spin_lock_irqsave(&current->sighand->siglock, flags);

[ ... ]

-- 
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261109105251.2545764-1-lian%40is.s.u-tokyo.ac.jp

      reply	other threads:[~2026-11-12  7:53 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-09 10:52 [PATCH 0/5] 9p: bound zero-copy error replies and keep flushed requests " Lianjie Wang
2026-11-09 10:52 ` [PATCH 1/5] 9p/virtio: clamp the reply size of a zero-copy request Lianjie Wang
2026-11-12  7:53   ` netdev-bot+sashiko
2026-11-09 10:52 ` [PATCH 2/5] 9p: ignore a zero-copy reply that arrives after a fatal signal Lianjie Wang
2026-11-12  7:53   ` netdev-bot+sashiko
2026-11-09 10:52 ` [PATCH 3/5] 9p/virtio: keep a request until the device returns it Lianjie Wang
2026-11-12  7:53   ` netdev-bot+sashiko
2026-11-09 10:52 ` [PATCH 4/5] 9p: take the tag of a flushed request from the request Lianjie Wang
2026-11-09 10:52 ` [PATCH 5/5] 9p/virtio: keep zero-copy buffers until the device returns them Lianjie Wang
2026-11-12  7:53   ` netdev-bot+sashiko [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=179446999308.2199510.11222629754827394625@kernel.org \
    --to=netdev-bot+sashiko@kernel.org \
    --cc=aneesh.kumar@linux.vnet.ibm.com \
    --cc=asmadeus@codewreck.org \
    --cc=chirantan@chromium.org \
    --cc=davem@davemloft.net \
    --cc=edumazet@kernel.org \
    --cc=ericvh@kernel.org \
    --cc=groug@kaod.org \
    --cc=horms@kernel.org \
    --cc=kuba@kernel.org \
    --cc=lian@is.s.u-tokyo.ac.jp \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux_oss@crudebyte.com \
    --cc=lucho@ionkov.net \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=shina@is.s.u-tokyo.ac.jp \
    --cc=stable@vger.kernel.org \
    --cc=tomasbortoli@gmail.com \
    --cc=v9fs@lists.linux.dev \
    --cc=viro@zeniv.linux.org.uk \
    /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

all inboxes | Powered by JetHome®