Re: [PATCH v3 5/8] s390/vfio_ccw: calculate idal length based on idaw type

From: Matthew Rosato

Date: Fri Jul 24 2026 - 13:40:33 EST


On 7/23/26 1:47 PM, Eric Farman wrote:
> Sashiko pointed out that get_guest_idal() unconditionally calculates
> the length of the IDAL presuming everything is a Format-2 IDAW.
>
> The output of vfio-ccw is always Format-2, but the input can be either
> Format-1 (31-bit addresses) or Format-2 (64-bit addresses). As a result,
> the size of the guest IDAL may be incorrect and should be trimmed down.
>
> Reported-by: sashiko-bot <sashiko-bot@xxxxxxxxxx>
> Link: https://lore.kernel.org/r/20260720203400.7328E1F000E9@xxxxxxxxxxxxxxx/
> Fixes: 1b676fe3d9d3 ("vfio/ccw: handle a guest Format-1 IDAL")
> Cc: stable@xxxxxxxxxxxxxxx
> Signed-off-by: Eric Farman <farman@xxxxxxxxxxxxx>

Reviewed-by: Matthew Rosato <mjrosato@xxxxxxxxxxxxx>

> ---
> drivers/s390/cio/vfio_ccw_cp.c | 5 +++--
> 1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
> index 06b6bc6142a0..b4a041d35bba 100644
> --- a/drivers/s390/cio/vfio_ccw_cp.c
> +++ b/drivers/s390/cio/vfio_ccw_cp.c
> @@ -233,6 +233,7 @@ static void convert_ccw0_to_ccw1(struct ccw1 *source, unsigned long len)
> }
>
> #define idal_is_2k(_cp) (!(_cp)->orb.cmd.c64 || (_cp)->orb.cmd.i2k)
> +#define get_idaw_size(_cp) ((_cp)->orb.cmd.c64 ? sizeof(u64) : sizeof(u32))
>
> /*
> * Helpers to operate ccwchain.
> @@ -534,7 +535,7 @@ static dma64_t *get_guest_idal(struct ccw1 *ccw, struct channel_program *cp, int
> dma64_t *idaws;
> dma32_t *idaws_f1;
> u64 first_idaw;
> - int idal_len = idaw_nr * sizeof(*idaws);
> + int idal_len = idaw_nr * get_idaw_size(cp);
> int idaw_size = idal_is_2k(cp) ? PAGE_SIZE / 2 : PAGE_SIZE;
> int idaw_mask = ~(idaw_size - 1);
> int i, ret;
> @@ -602,7 +603,7 @@ static int ccw_count_idaws(struct ccw1 *ccw,
> struct vfio_device *vdev =
> &container_of(cp, struct vfio_ccw_private, cp)->vdev;
> u64 iova;
> - int size = cp->orb.cmd.c64 ? sizeof(u64) : sizeof(u32);
> + int size = get_idaw_size(cp);
> int ret;
> int bytes = 1;
>