All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Foo Bar" <muratseker@meta.com>
Cc: virtualization@lists.linux.dev,
	"Michael S. Tsirkin" <mst@redhat.com>,
	"Eugenio Perez" <eperezma@redhat.com>
Subject: Re: [PATCH] virtio_console: add console port to list before hvc_alloc()
Date: Sun, 01 Nov 2026 02:37:33 +0000	[thread overview]
Message-ID: <sashiko-outbox-192252@kernel.org> (raw)
In-Reply-To: <20261101022435.3466820-1-muratseker@meta.com>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Critical] virtio_console: race between __send_to_port() and out_intr() in add_port()
--

commit e1686190742677c49792956e3ec4f167b8b193e9
Author: Murat Seker <muratseker@meta.com>

virtio_console: add console port to list before hvc_alloc()

This commit adds the console port to pdrvdata.consoles before calling
hvc_alloc() in init_port_console() so that put_chars() can find the port
when register_console() replays the kernel log buffer. If hvc_alloc()
fails, the port is removed from pdrvdata.consoles before freeing the
vtermno.

> diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
> index 019bcae81af5c..a31fdac658913 100644
> --- a/drivers/char/virtio_console.c
> +++ b/drivers/char/virtio_console.c
> @@ -1280,18 +1280,28 @@ static int init_port_console(struct port *port)
>  		return ret;
>  
>  	port->cons.vtermno = ret;
> +
> +	/*
> +	 * hvc_alloc() may register the console, which replays the log buffer
> +	 * through put_chars().  put_chars() finds the port on this list, so
> +	 * add it first or the replayed messages are dropped.
> +	 */
> +	spin_lock_irq(&pdrvdata_lock);
> +	list_add_tail(&port->cons.list, &pdrvdata.consoles);
> +	spin_unlock_irq(&pdrvdata_lock);
> +
>  	port->cons.hvc = hvc_alloc(port->cons.vtermno, 0, &hv_ops, PAGE_SIZE);

[Severity: Critical]
When probing a non-multiport device with a preferred hvc console, can this
cause a race between __send_to_port() and out_intr() on port->out_vq?

In virtcons_probe(), init_vqs() sets out_intr() as the callback for
portdev->out_vqs[0] and virtio_device_ready() enables virtqueue interrupts
before add_port() is called.

In add_port(), when !use_multiport(port->portdev) is true,
init_port_console() is called before the port is added to
port->portdev->ports:

drivers/char/virtio_console.c:add_port() {
	...
	else if (!use_multiport(port->portdev)) {
		/*
		 * If we're not using multiport support,
		 * this has to be a console port.
		 */
		err = init_port_console(port);
		if (err)
			goto free_inbufs;
	}

	spin_lock_irq(&portdev->ports_lock);
	list_add_tail(&port->list, &port->portdev->ports);
	spin_unlock_irq(&portdev->ports_lock);
	...
}

Because port->cons.list is now in pdrvdata.consoles during hvc_alloc(),
hvc_alloc() -> hvc_check_console() -> register_console() synchronously
replays the kernel log buffer through hvc_console_print() -> put_chars() ->
__send_to_port() while port is still not in portdev->ports.

__send_to_port() acquires port->outvq_lock with spin_lock_irqsave(), queues
the buffer on out_vq, kicks the host, and spins waiting for completion:

drivers/char/virtio_console.c:__send_to_port() {
	...
	/* Tell Host to go! */
	virtqueue_kick(out_vq);

	if (!in_blocking) {
		...
		while (!(buf = virtqueue_get_buf(out_vq, &len))
			&& !virtqueue_is_broken(out_vq))
			cpu_relax();
	}
	...
}

If the host completes the buffer and raises an interrupt on another CPU
before add_port() adds the port to portdev->ports, out_intr() runs and
find_port_by_vq() returns NULL:

drivers/char/virtio_console.c:out_intr() {
	struct port *port;

	port = find_port_by_vq(vq->vdev->priv, vq);
	if (!port) {
		flush_bufs(vq, false);
		return;
	}
	...
}

Wouldn't flush_bufs() then call virtqueue_get_buf() and free_buf() on
out_vq without holding port->outvq_lock, corrupting the virtqueue ring
concurrently with __send_to_port() and stealing the completed buffer so
that __send_to_port() spins forever with interrupts disabled?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261101022435.3466820-1-muratseker@meta.com?part=1

  reply	other threads:[~2026-11-01  2:37 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-01  2:24 [PATCH] virtio_console: add console port to list before hvc_alloc() Foo Bar
2026-11-01  2:37 ` sashiko-bot [this message]
2026-11-01  2:59 ` Murat Seker

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=sashiko-outbox-192252@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=eperezma@redhat.com \
    --cc=mst@redhat.com \
    --cc=muratseker@meta.com \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=virtualization@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 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.