All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Eric Farman" <farman@linux.ibm.com>
Cc: "Alexander Gordeev" <agordeev@linux.ibm.com>,
	kvm@vger.kernel.org, "Heiko Carstens" <hca@linux.ibm.com>,
	"Vasily Gorbik" <gor@linux.ibm.com>,
	linux-s390@vger.kernel.org
Subject: Re: [PATCH v7 10/10] s390/vfio_ccw: implement a crw lock
Date: Mon, 27 Jul 2026 20:07:21 +0000	[thread overview]
Message-ID: <20260727200721.D818D1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260727192230.2715207-11-farman@linux.ibm.com>

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

Pre-existing issues:
- [High] Concurrent VFIO_DEVICE_SET_IRQS ioctl can cause a Use-After-Free of eventfd_ctx in vfio_ccw_crw_region_read() and vfio_ccw_crw_todo().
- [High] Race condition between asynchronous channel path events and device removal leads to Use-After-Free of the `private` struct.
- [High] The `crw` list is emptied before `cancel_work_sync()` is called, which can lead to memory leaks of dynamically allocated `crw` objects.
--

--- Patch [10]: [PATCH v7 10/10] s390/vfio_ccw: implement a crw lock ---
commit 32947477038816f52fb49c7c2eb829ec1255cb5d
Author: Eric Farman <farman@linux.ibm.com>

s390/vfio_ccw: implement a crw lock

Unlike the channel_program struct, which covers synchronous I/O
submissions and asynchronous interrupts, the CRW region relies
exclusively on asynchronous events coming from hardware.

Implement a lock to manage the list of those payloads, to ensure
they are read cohesively.

Fixes: 3f02cb2fd9d2 ("vfio-ccw: Wire up the CRW irq and CRW region")
Cc: stable@vger.kernel.org
Cc: Farhan Ali <alifm@linux.ibm.com>

> diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c
> index 757ff5b2556e3..ab6b518cc353f 100644
> --- a/drivers/s390/cio/vfio_ccw_drv.c
> +++ b/drivers/s390/cio/vfio_ccw_drv.c
> @@ -118,11 +118,14 @@ void vfio_ccw_sch_io_todo(struct work_struct *work)
>  void vfio_ccw_crw_todo(struct work_struct *work)
>  {
>  	struct vfio_ccw_private *private;
> +	unsigned long flags;
>  
>  	private = container_of(work, struct vfio_ccw_private, crw_work);
>  
> +	spin_lock_irqsave(&private->crw_lock, flags);
>  	if (!list_empty(&private->crw) && private->crw_trigger)
>  		eventfd_signal(private->crw_trigger);
> +	spin_unlock_irqrestore(&private->crw_lock, flags);
>  }

[Severity: High]
This isn't a bug introduced by this patch, but can a concurrent
VFIO_DEVICE_SET_IRQS ioctl cause a use-after-free of the eventfd_ctx?

If an unprivileged userspace process calls the VFIO_DEVICE_SET_IRQS ioctl,
vfio_ccw_mdev_set_irqs() releases the eventfd_ctx without acquiring crw_lock
or other serializing locks:

	if (*ctx)
		eventfd_ctx_put(*ctx);
	*ctx = efdctx;

Since private->crw_trigger is read under crw_lock here, but not held by
the writer, could the context be freed before or during eventfd_signal()?

> @@ -286,6 +289,7 @@ static void vfio_ccw_queue_crw(struct vfio_ccw_private *private,
>  			       unsigned int rsid)
>  {
>  	struct vfio_ccw_crw *crw;
> +	unsigned long flags;
>  
>  	/*
>  	 * If unable to allocate a CRW, just drop the event and
> @@ -303,7 +307,9 @@ static void vfio_ccw_queue_crw(struct vfio_ccw_private *private,
>  	crw->crw.erc = erc;
>  	crw->crw.rsid = rsid;
>  
> +	spin_lock_irqsave(&private->crw_lock, flags);
>  	list_add_tail(&crw->next, &private->crw);
> +	spin_unlock_irqrestore(&private->crw_lock, flags);
>  	queue_work(vfio_ccw_work_q, &private->crw_work);
>  }

[Severity: High]
This is a pre-existing issue, but is there a race condition between asynchronous
channel path events and device removal that could lead to a use-after-free of
the private struct?

A hardware event can trigger vfio_ccw_chp_event() which fetches the private
pointer locklessly:

	struct vfio_ccw_private *private = dev_get_drvdata(&parent->dev);
	...
	vfio_ccw_queue_crw(private, CRW_RSC_CPATH, ...);

Concurrently, if userspace writes to the mdev 'remove' sysfs attribute,
vfio_ccw_mdev_remove() clears the driver data and releases the device reference:

	dev_set_drvdata(&parent->dev, NULL);
	vfio_put_device(&private->vdev);

Could the private structure be freed while we are still executing here or in
queue_work()?

> diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c
> index 8ec6b175d9914..9cbb277b83fb2 100644
> --- a/drivers/s390/cio/vfio_ccw_ops.c
> +++ b/drivers/s390/cio/vfio_ccw_ops.c

[ ... ]

> @@ -131,11 +132,14 @@ static void vfio_ccw_mdev_release_dev(struct vfio_device *vdev)
>  	struct vfio_ccw_private *private =
>  		container_of(vdev, struct vfio_ccw_private, vdev);
>  	struct vfio_ccw_crw *crw, *temp;
> +	unsigned long flags;
>  
> +	spin_lock_irqsave(&private->crw_lock, flags);
>  	list_for_each_entry_safe(crw, temp, &private->crw, next) {
>  		list_del(&crw->next);
>  		kfree(crw);
>  	}
> +	spin_unlock_irqrestore(&private->crw_lock, flags);
>  
>  	/* Should be empty, but just in case */
>  	cancel_work_sync(&private->io_work);

[Severity: High]
This isn't a bug introduced by this patch, but does emptying the crw list before
calling cancel_work_sync() violate the subsystem rule that background tasks must
be explicitly stopped before the queues they operate on are destroyed?

If a concurrent hardware event (like vfio_ccw_chp_event) allocates a crw and
calls queue_work() before or during the cancellation, could the newly allocated
crw be left on the list and leaked?

Additionally, if queue_work() executes after cancel_work_sync() finishes, could
the work execute on a freed private pointer?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260727192230.2715207-1-farman@linux.ibm.com?part=10

  reply	other threads:[~2026-07-27 20:07 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-27 19:22 [PATCH v7 00/10] s390/vfio_ccw fixes Eric Farman
2026-07-27 19:22 ` [PATCH v7 01/10] s390/vfio_ccw: free all memory if cp_init() fails Eric Farman
2026-07-27 19:58   ` sashiko-bot
2026-07-27 19:22 ` [PATCH v7 02/10] s390/vfio_ccw: limit the number of channel program segments Eric Farman
2026-07-27 19:52   ` sashiko-bot
2026-07-27 19:22 ` [PATCH v7 03/10] s390/vfio_ccw: fix out of bounds check on CCW array Eric Farman
2026-07-27 19:53   ` sashiko-bot
2026-07-27 19:22 ` [PATCH v7 04/10] s390/vfio_ccw: ensure first IDAW remains constant Eric Farman
2026-07-27 19:59   ` sashiko-bot
2026-07-27 19:22 ` [PATCH v7 05/10] s390/vfio_ccw: calculate idal length based on idaw type Eric Farman
2026-07-27 19:54   ` sashiko-bot
2026-07-27 19:22 ` [PATCH v7 06/10] s390/vfio_ccw: ensure index for read/write regions are within range Eric Farman
2026-07-27 20:03   ` sashiko-bot
2026-07-27 19:22 ` [PATCH v7 07/10] s390/vfio_ccw: cancel existing workqueues Eric Farman
2026-07-27 20:02   ` sashiko-bot
2026-07-27 21:54   ` Matthew Rosato
2026-07-27 19:22 ` [PATCH v7 08/10] s390/vfio_ccw: move cp cleanup out of not operational Eric Farman
2026-07-27 20:04   ` sashiko-bot
2026-07-27 21:54   ` Matthew Rosato
2026-07-27 19:22 ` [PATCH v7 09/10] s390/vfio_ccw: selectively expand io_mutex Eric Farman
2026-07-27 20:12   ` sashiko-bot
2026-07-27 19:22 ` [PATCH v7 10/10] s390/vfio_ccw: implement a crw lock Eric Farman
2026-07-27 20:07   ` sashiko-bot [this message]
2026-07-27 21:35   ` Farhan Ali

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=20260727200721.D818D1F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=agordeev@linux.ibm.com \
    --cc=farman@linux.ibm.com \
    --cc=gor@linux.ibm.com \
    --cc=hca@linux.ibm.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-s390@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 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.