All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "João Peixoto" <jpeixoto@osyx.tech>
Cc: devicetree@vger.kernel.org, robh@kernel.org, conor+dt@kernel.org
Subject: Re: [PATCH v6 2/3] virt: bao: add I/O dispatcher driver
Date: Fri, 13 Nov 2026 17:27:20 +0000	[thread overview]
Message-ID: <sashiko-outbox-213306@kernel.org> (raw)
In-Reply-To: <4e725d9d94cfd425ac0ff4352b21f7bf7b7a1296.1794589639.git.jpeixoto@osyx.tech>

Thank you for your contribution! Sashiko AI review found 1 potential
issue to consider:
- [Medium] virt: bao: race in bao_irqfd_queue_shutdown() causes UAF on
  teardown
--

commit a54931ee06339bcb9128b2ac3b46c8d5cb3569c1
Author: João Peixoto <jpeixoto@osyx.tech>

virt: bao: add I/O dispatcher driver

This commit adds the Bao hypervisor I/O dispatcher driver, exposing
/dev/bao and per-DM file descriptors to bridge Remote I/O requests,
shared memory, ioeventfds, and irqfds between frontend guests and
userspace VirtIO device models.

> diff --git a/drivers/virt/bao/io-dispatcher/irqfd.c b/drivers/virt/bao/io-dispatcher/irqfd.c
> new file mode 100644
> index 0000000000000..8d01bef4e7abd
> --- /dev/null
> +++ b/drivers/virt/bao/io-dispatcher/irqfd.c
> @@ -0,0 +1,330 @@

[ ... ]

> +/* Queue the cleanup work at most once. Safe from atomic context. */
> +static void bao_irqfd_queue_shutdown(struct irqfd *irqfd)
> +{
> +	if (!test_and_set_bit(BAO_IRQFD_SHUTDOWN, &irqfd->flags))
> +		queue_work(irqfd->dm->irqfd_server, &irqfd->shutdown);
> +}

[ ... ]

> +static int bao_irqfd_wakeup(wait_queue_entry_t *wait, unsigned int mode,
> +			    int sync, void *key)
> +{
> +	struct irqfd *irqfd = container_of(wait, struct irqfd, wait);
> +	__poll_t flags = key_to_poll(key);
> +	u64 cnt;
> +
> +	if (flags & EPOLLIN) {
> +		eventfd_ctx_do_read(irqfd->eventfd, &cnt);
> +		bao_irqfd_inject(irqfd->dm->info.id);
> +	}
> +
> +	if (flags & EPOLLHUP)
> +		/* Defer teardown to the cleanup work; can't sleep here. */
> +		bao_irqfd_queue_shutdown(irqfd);
> +
> +	return 0;
> +}

[ ... ]

> +void bao_irqfd_server_destroy(struct bao_dm *dm)
> +{
> +	struct irqfd *irqfd;
> +	struct irqfd *next;
> +
> +	if (WARN_ON_ONCE(!dm))
> +		return;
> +
> +	mutex_lock(&dm->irqfds_lock);
> +	list_for_each_entry_safe(irqfd, next, &dm->irqfds, list) {
> +		list_del_init(&irqfd->list);
> +		dm->nr_irqfds--;
> +		bao_irqfd_queue_shutdown(irqfd);
> +	}
> +	mutex_unlock(&dm->irqfds_lock);
> +
> +	/* Drain all cleanup work before tearing the workqueue down. */
> +	if (dm->irqfd_server) {
> +		flush_workqueue(dm->irqfd_server);
> +		destroy_workqueue(dm->irqfd_server);
> +	}
> +}

[Severity: Medium]
Can bao_irqfd_queue_shutdown() race with bao_irqfd_server_destroy() and
cause a use-after-free of dm and dm->irqfd_server?

bao_irqfd_wakeup() runs on EPOLLHUP without holding dm->irqfds_lock.  Once
it sets BAO_IRQFD_SHUTDOWN in bao_irqfd_queue_shutdown(), a concurrent
teardown caller sees the bit already set and moves on to flush and destroy
dm->irqfd_server before the work item is actually queued:

CPU0                                  CPU1
eventfd_release()                     bao_dm_release()
  wake_up_poll(..., EPOLLHUP)           bao_dm_destroy()
    bao_irqfd_wakeup()                    bao_irqfd_server_destroy()
      bao_irqfd_queue_shutdown()            mutex_lock(&dm->irqfds_lock)
        test_and_set_bit(...) -> 0          bao_irqfd_queue_shutdown()
                                              test_and_set_bit(...) -> 1
                                            mutex_unlock(&dm->irqfds_lock)
                                            flush_workqueue(dm->irqfd_server)
                                            destroy_workqueue(dm->irqfd_server)
                                          kfree(dm)
        queue_work(irqfd->dm->irqfd_server, ...)
          <-- use-after-free

The same race with bao_irqfd_deassign() lets flush_workqueue() return
before irqfd->shutdown has been queued and run.

Since queue_work() already ignores a work_struct that is currently
pending, bao_irqfd_queue_shutdown() can call queue_work() unconditionally
without BAO_IRQFD_SHUTDOWN so that both paths guarantee the work is queued
before returning.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1794589639.git.jpeixoto@osyx.tech?part=2

  reply	other threads:[~2026-11-13 17:27 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-13 17:12 [PATCH v6 0/3] virt: bao: add Bao hypervisor IPC and I/O dispatcher drivers João Peixoto
2026-11-13 17:12 ` João Peixoto
2026-11-13 17:12 ` [PATCH v6 1/3] virt: bao: add IPC shared-memory driver João Peixoto
2026-11-13 17:12   ` João Peixoto
2026-11-13 17:12 ` [PATCH v6 2/3] virt: bao: add I/O dispatcher driver João Peixoto
2026-11-13 17:12   ` João Peixoto
2026-11-13 17:27   ` sashiko-bot [this message]
2026-11-13 17:12 ` [PATCH v6 3/3] MAINTAINERS: add Bao hypervisor entry João Peixoto
2026-11-13 17:12   ` João Peixoto

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-213306@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=jpeixoto@osyx.tech \
    --cc=robh@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 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.