From: sashiko-bot@kernel.org
To: "Eric Farman" <farman@linux.ibm.com>
Cc: "Heiko Carstens" <hca@linux.ibm.com>,
"Vasily Gorbik" <gor@linux.ibm.com>,
linux-s390@vger.kernel.org,
"Alexander Gordeev" <agordeev@linux.ibm.com>,
kvm@vger.kernel.org
Subject: Re: [PATCH v8 10/10] s390/vfio_ccw: implement a crw lock
Date: Tue, 28 Jul 2026 02:01:21 +0000 [thread overview]
Message-ID: <20260728020122.0E8F61F00ADB@smtp.kernel.org> (raw)
In-Reply-To: <20260728013509.1551753-11-farman@linux.ibm.com>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
New issues:
- [High] Missing cancellation of `notoper_work` during device release leads to Use-After-Free.
Pre-existing issues:
- [Critical] Lockless modification of eventfd triggers in `vfio_ccw_mdev_set_irqs` leads to Use-After-Free of `eventfd_ctx` in asynchronous workers.
- [High] Race condition between asynchronous CSS callbacks and mdev removal leads to Use-After-Free of the `private` structure.
--
--- Patch [10]: [PATCH v8 10/10] s390/vfio_ccw: implement a crw lock ---
commit e956337911477e5c5887e514827c14569954a32d
Author: Eric Farman <farman@linux.ibm.com>
s390/vfio_ccw: implement a crw lock
This patch adds a lock to the vfio_ccw driver to manage the list of
asynchronous CRW events. It serializes access to the CRW payload list
to ensure cohesive reads between hardware events and userspace.
> 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);
[Severity: Critical]
This is a pre-existing issue, but I noticed a potential problem with how
crw_trigger is accessed here.
Does private->crw_lock actually protect private->crw_trigger from
concurrent modification?
Looking at vfio_ccw_mdev_set_irqs(), it replaces and frees eventfd contexts
without holding any locks:
drivers/s390/cio/vfio_ccw_ops.c:vfio_ccw_mdev_set_irqs() {
...
if (*ctx)
eventfd_ctx_put(*ctx);
*ctx = efdctx;
}
If the VFIO_DEVICE_SET_IRQS ioctl swaps and frees the eventfd_ctx while
this asynchronous worker is preparing to signal it, won't eventfd_signal()
dereference a freed pointer?
> + spin_unlock_irqrestore(&private->crw_lock, flags);
> }
> [ ... ]
> diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c
> index 1cca3ecdae45b..4a0fe2f8fdb44 100644
> --- a/drivers/s390/cio/vfio_ccw_ops.c
> +++ b/drivers/s390/cio/vfio_ccw_ops.c
> [ ... ]
> @@ -131,6 +132,7 @@ 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;
>
> /*
> * Ensure these work items are fully drained, so none can
> * fire after being released. The notoper_work struct is
> * only meaningful if the device had been opened, which
> * means it would have been cleaned in an earlier close.
> */
> cancel_work_sync(&private->io_work);
> cancel_work_sync(&private->crw_work);
[Severity: High]
The comment above suggests notoper_work is only meaningful if the device
had been opened, but could a race occur here?
If the device was never opened (state is VFIO_CCW_STATE_STANDBY), can an
asynchronous CSS callback still trigger a VFIO_CCW_EVENT_NOT_OPER event
(e.g., if the subchannel is unregistered)?
If this happens and queues notoper_work, and the device is subsequently
released, won't release_dev free the private structure while notoper_work
is still queued?
When the workqueue executes:
drivers/s390/cio/vfio_ccw_drv.c:vfio_ccw_notoper_todo() {
...
mutex_lock(&private->io_mutex);
cp_free(&private->cp);
mutex_unlock(&private->io_mutex);
}
Won't this dereference the freed private pointer? Should we add
cancel_work_sync(&private->notoper_work) here?
[Severity: High]
This is a pre-existing issue, but since we are looking at the lifecycle of
the private structure, is there a race condition with asynchronous CSS
callbacks during mdev removal?
In vfio_ccw_sch_event(), the private pointer is fetched locklessly:
drivers/s390/cio/vfio_ccw_drv.c:vfio_ccw_sch_event() {
struct vfio_ccw_parent *parent = dev_get_drvdata(&sch->dev);
struct vfio_ccw_private *private = dev_get_drvdata(&parent->dev);
unsigned long flags;
...
spin_lock_irqsave(&sch->lock, flags);
}
If vfio_ccw_mdev_remove() runs concurrently, it clears the drvdata
locklessly and drops the device reference:
drivers/s390/cio/vfio_ccw_ops.c:vfio_ccw_mdev_remove() {
vfio_unregister_group_dev(&private->vdev);
dev_set_drvdata(&parent->dev, NULL);
vfio_put_device(&private->vdev);
}
If the CSS callback is preempted after fetching the pointer but before
acquiring sch->lock, and resumes after the removal path completes, won't
it use the freed private structure?
> + 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);
> [ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260728013509.1551753-1-farman@linux.ibm.com?part=10
prev parent reply other threads:[~2026-07-28 2:01 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-28 1:34 [PATCH v8 00/10] s390/vfio_ccw fixes Eric Farman
2026-07-28 1:35 ` [PATCH v8 01/10] s390/vfio_ccw: free all memory if cp_init() fails Eric Farman
2026-07-28 1:51 ` sashiko-bot
2026-07-28 1:35 ` [PATCH v8 02/10] s390/vfio_ccw: limit the number of channel program segments Eric Farman
2026-07-28 1:52 ` sashiko-bot
2026-07-28 1:35 ` [PATCH v8 03/10] s390/vfio_ccw: fix out of bounds check on CCW array Eric Farman
2026-07-28 1:50 ` sashiko-bot
2026-07-28 1:35 ` [PATCH v8 04/10] s390/vfio_ccw: ensure first IDAW remains constant Eric Farman
2026-07-28 1:45 ` sashiko-bot
2026-07-28 1:35 ` [PATCH v8 05/10] s390/vfio_ccw: calculate idal length based on idaw type Eric Farman
2026-07-28 1:49 ` sashiko-bot
2026-07-28 1:35 ` [PATCH v8 06/10] s390/vfio_ccw: ensure index for read/write regions are within range Eric Farman
2026-07-28 1:54 ` sashiko-bot
2026-07-28 1:35 ` [PATCH v8 07/10] s390/vfio_ccw: cancel existing workqueues Eric Farman
2026-07-28 1:53 ` sashiko-bot
2026-07-28 2:07 ` Matthew Rosato
2026-07-28 1:35 ` [PATCH v8 08/10] s390/vfio_ccw: move cp cleanup out of not operational Eric Farman
2026-07-28 1:49 ` sashiko-bot
2026-07-28 2:08 ` Matthew Rosato
2026-07-28 3:23 ` Eric Farman
2026-07-28 1:35 ` [PATCH v8 09/10] s390/vfio_ccw: selectively expand io_mutex Eric Farman
2026-07-28 1:57 ` sashiko-bot
2026-07-28 2:08 ` Matthew Rosato
2026-07-28 1:35 ` [PATCH v8 10/10] s390/vfio_ccw: implement a crw lock Eric Farman
2026-07-28 2:01 ` sashiko-bot [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=20260728020122.0E8F61F00ADB@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.