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, linux-s390@vger.kernel.org,
	"Vasily Gorbik" <gor@linux.ibm.com>,
	"Heiko Carstens" <hca@linux.ibm.com>
Subject: Re: [PATCH v2 6/7] s390/vfio_ccw: implement a channel program lock
Date: Mon, 20 Jul 2026 20:39:41 +0000	[thread overview]
Message-ID: <20260720203941.9E7201F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260720201931.976660-7-farman@linux.ibm.com>

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

New issues:
- [High] The newly introduced `cp_lock` spinlock is held while executing operations that acquire sleeping locks, leading to a guaranteed 'scheduling while atomic' kernel BUG.

Pre-existing issues:
- [High] Incomplete locking allows a data race between channel program initialization and `vfio_ccw_dma_unmap()`, leading to a NULL pointer dereference.
- [High] The background work items `crw_work` and `io_work` are not explicitly cancelled before the driver frees the device's private memory.
--

--- Patch [6]: [PATCH v2 6/7] s390/vfio_ccw: implement a channel program lock ---
commit fcac9cc035321189b03cc15ccc7af0d3409a1018
Author: Eric Farman <farman@linux.ibm.com>

s390/vfio_ccw: implement a channel program lock

The channel_program struct is manipulated without a serialization
mechanism to ensure consistent behavior. This patch introduces a spin
lock to guard the entire structure, which can be acquired with or
without the mutex guarding the I/O regions.

> diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
> --- a/drivers/s390/cio/vfio_ccw_cp.c
> +++ b/drivers/s390/cio/vfio_ccw_cp.c
> @@ -810,6 +810,17 @@ void cp_free(struct channel_program *cp)
>  	}
>  }
>  
> +void cp_free(struct channel_program *cp)
> +{
> +	struct vfio_ccw_private *private =
> +		container_of(cp, struct vfio_ccw_private, cp);
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&private->cp_lock, flags);
> +	cp_free_locked(cp);

[Severity: High]
Does holding the cp_lock spinlock here lead to a scheduling while atomic bug?

When cp_free_locked() cascades into the unpinning logic:

cp_free_locked()
  page_array_unpin_free()
    vfio_unpin_pages()
      vfio_iommu_type1_unpin_pages()
        mutex_lock(&iommu->lock);

The IOMMU backend unconditionally acquires a sleeping lock while the
thread is in atomic context from the spin_lock_irqsave(). Can this crash
the kernel when I/O request cleanup executes?

> +	spin_unlock_irqrestore(&private->cp_lock, flags);
> +}
> +

[ ... ]

> diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c
> --- a/drivers/s390/cio/vfio_ccw_ops.c
> +++ b/drivers/s390/cio/vfio_ccw_ops.c
> @@ -36,10 +36,15 @@ static void vfio_ccw_dma_unmap(struct vfio_device *vdev, u64 iova, u64 length)
>  {
>  	struct vfio_ccw_private *private =
>  		container_of(vdev, struct vfio_ccw_private, vdev);
> +	unsigned long flags;
>  
>  	/* Drivers MUST unpin pages in response to an invalidation. */
> -	if (!cp_iova_pinned(&private->cp, iova, length))
> +	spin_lock_irqsave(&private->cp_lock, flags);
> +	if (!cp_iova_pinned(&private->cp, iova, length)) {

[Severity: High]
This is a pre-existing issue, but does adding the lock here expose a NULL
pointer dereference due to incomplete locking elsewhere?

In fsm_io_request(), cp_init() and cp_prefetch() are called without
holding the new cp_lock. cp_init() sets cp->initialized = true. Then
cp_prefetch() calls page_array_alloc(), which does:

page_array_alloc()
  pa->pa_nr = len;
  pa->pa_iova = kzalloc_objs(*pa->pa_iova, len);

If a concurrent unmap enters vfio_ccw_dma_unmap(), acquires cp_lock, and
iterates the channel program because initialized is true, can it
dereference the still-NULL pa->pa_iova array since the initializing
thread hasn't allocated it yet?

> +		spin_unlock_irqrestore(&private->cp_lock, flags);
>  		return;
> +	}
> +	spin_unlock_irqrestore(&private->cp_lock, flags);
>  
>  	vfio_ccw_mdev_reset(private);
>  }

[ ... ]

> @@ -54,6 +59,7 @@ static int vfio_ccw_mdev_init_dev(struct vfio_device *vdev)
>  	INIT_LIST_HEAD(&private->crw);
>  	INIT_WORK(&private->io_work, vfio_ccw_sch_io_todo);
>  	INIT_WORK(&private->crw_work, vfio_ccw_crw_todo);
> +	spin_lock_init(&private->cp_lock);

[Severity: High]
This isn't a bug introduced by this patch, but do these work items leak
and cause a use-after-free on device teardown?

According to the subsystem guidelines, once queue_work() is called,
flush_work() and other workqueue shutdown methods prevent us from leaking
the work struct on shutdown.

If an asynchronous subchannel event fires and queues crw_work, and the
user concurrently removes the mdev device, vfio_ccw_mdev_release_dev()
frees the private structure:

vfio_ccw_mdev_release_dev()
  kfree(private->cp.guest_cp);
  mutex_destroy(&private->io_mutex);

Will the workqueue scheduler eventually execute the pending crw_work and
access the already-freed private structure, since the removal function
drops references without explicitly cancelling background work?

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

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

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-20 20:19 [PATCH v2 0/7] s390/vfio_ccw fixes Eric Farman
2026-07-20 20:19 ` [PATCH v2 1/7] s390/vfio_ccw: free all memory if cp_init() fails Eric Farman
2026-07-20 20:31   ` sashiko-bot
2026-07-20 21:48   ` Farhan Ali
2026-07-21  0:01     ` Eric Farman
2026-07-20 20:19 ` [PATCH v2 2/7] s390/vfio_ccw: limit the number of channel program segments Eric Farman
2026-07-20 20:30   ` sashiko-bot
2026-07-20 20:53     ` Eric Farman
2026-07-20 20:19 ` [PATCH v2 3/7] s390/vfio_ccw: fix out of bounds check on CCW array Eric Farman
2026-07-20 20:38   ` sashiko-bot
2026-07-20 20:19 ` [PATCH v2 4/7] s390/vfio_ccw: ensure first IDAW remains constant Eric Farman
2026-07-20 20:33   ` sashiko-bot
2026-07-20 20:19 ` [PATCH v2 5/7] s390/vfio_ccw: ensure index for read/write regions are within range Eric Farman
2026-07-20 20:40   ` sashiko-bot
2026-07-20 20:19 ` [PATCH v2 6/7] s390/vfio_ccw: implement a channel program lock Eric Farman
2026-07-20 20:39   ` sashiko-bot [this message]
2026-07-20 20:19 ` [PATCH v2 7/7] s390/vfio_ccw: implement a crw lock Eric Farman
2026-07-20 20:47   ` sashiko-bot

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=20260720203941.9E7201F000E9@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.