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>,
	"Vasily Gorbik" <gor@linux.ibm.com>,
	"Heiko Carstens" <hca@linux.ibm.com>,
	linux-s390@vger.kernel.org, kvm@vger.kernel.org
Subject: Re: [PATCH v2 4/7] s390/vfio_ccw: ensure first IDAW remains constant
Date: Mon, 20 Jul 2026 20:33:59 +0000	[thread overview]
Message-ID: <20260720203400.7328E1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260720201931.976660-5-farman@linux.ibm.com>

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

Pre-existing issues:
- [Critical] This problem wasn't introduced by this patch, but concurrent execution of a device reset or DMA unmap with an active I/O request leads to a critical use-after-free and data corruption of the channel program structures.
- [High] This problem wasn't introduced by this patch, but the IDAL read length calculation in `get_guest_idal()` for Format-1 IDAWs incorrectly calculates the length as if they were 64-bit IDAWs, leading to an out-of-bounds read from guest memory.
--

--- Patch [4]: [PATCH v2 4/7] s390/vfio_ccw: ensure first IDAW remains constant ---
commit d9b51975a2a2546c96fb0396ccf078c5c296fe37
Author: Eric Farman <farman@linux.ibm.com>

s390/vfio_ccw: ensure first IDAW remains constant

This patch ensures the first IDAW in a list remains constant by verifying
its address between reads, and returning an error if a mismatch is found.
This helps maintain a consistent set of IDAWs for I/O operations.

> diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
> index ce61858c82eb6..c6f0264fb5d33 100644
> --- a/drivers/s390/cio/vfio_ccw_cp.c
> +++ b/drivers/s390/cio/vfio_ccw_cp.c
> @@ -533,6 +533,7 @@ static dma64_t *get_guest_idal(struct ccw1 *ccw, struct channel_program *cp, int
>  		&container_of(cp, struct vfio_ccw_private, cp)->vdev;
>  	dma64_t *idaws;
>  	dma32_t *idaws_f1;
> +	u64 first_idaw;
>  	int idal_len = idaw_nr * sizeof(*idaws);
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

[Severity: High]
This is a pre-existing issue, but the IDAL read length calculation in
get_guest_idal() for Format-1 IDAWs incorrectly calculates the length as if
they were 64-bit IDAWs, leading to an out-of-bounds read from guest memory.

Because Format-1 IDAWs are actually 32 bits (4 bytes) long, this instructs
vfio_dma_rw() to read exactly twice the valid IDAL size.

If the IDAL resides near the boundary of the guest's mapped IOMMU DMA region,
this over-read spans into an unmapped area, causing vfio_dma_rw() to reject
the read and fail the legitimate channel program.

Does this code need to calculate the length based on the actual IDAW size
instead of the host's 8-byte target struct dma64_t?

>  	int idaw_size = idal_is_2k(cp) ? PAGE_SIZE / 2 : PAGE_SIZE;
>  	int idaw_mask = ~(idaw_size - 1);

[ ... ]

Additionally, there is another regression present in the state machine:

[Severity: Critical]
This is a pre-existing issue, but concurrent execution of a device reset or
DMA unmap with an active I/O request leads to a use-after-free and data
corruption of the channel program structures.

If an unprivileged guest triggers an I/O operation, invoking
vfio_ccw_mdev_write_io_region() in the host, this function takes
private->io_mutex and pushes VFIO_CCW_EVENT_IO_REQ to the state machine,
invoking fsm_io_request().

Here, private->state is set to VFIO_CCW_STATE_CP_PROCESSING, and
cp_init()/cp_prefetch() are called without holding any locks:

drivers/s390/cio/vfio_ccw_fsm.c:fsm_io_request()
    private->state = VFIO_CCW_STATE_CP_PROCESSING;
    //...
    io_region->ret_code = cp_init(&private->cp, orb);
    //...
    io_region->ret_code = cp_prefetch(&private->cp);

Concurrently, if the guest alters its IOMMU mappings, it triggers
vfio_ccw_dma_unmap() on the host. This callback checks cp_iova_pinned() without
holding any locks and then executes vfio_ccw_mdev_reset(), which pushes
VFIO_CCW_EVENT_CLOSE to the state machine without acquiring private->io_mutex:

drivers/s390/cio/vfio_ccw_ops.c:vfio_ccw_mdev_reset()
    vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_CLOSE);

Since the state is currently CP_PROCESSING, this routes to fsm_close(), which
unconditionally frees the structures concurrently with the active initialization
routine:

drivers/s390/cio/vfio_ccw_fsm.c:fsm_close()
    cp_free(&private->cp);

Can this sequence actually occur and cause cp_free() to free the ccwchain
memory while cp_prefetch() is actively modifying it? Should these events be
serialized to prevent this?

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

  reply	other threads:[~2026-07-20 20:34 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 [this message]
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
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=20260720203400.7328E1F000E9@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.