On 9/16/26 4:32 PM, Eric Farman wrote:
> The interrupt subclass is often defined as a uint8, though in practice
> it will be within the range of just 0-7. Ensure that a guest-supplied
> subclass does not extend beyond its expected range, especially when
> used as an array index.
> 
> Signed-off-by: Eric Farman <[email protected]>
> ---
>  hw/s390x/css.c        | 7 ++++++-
>  hw/s390x/virtio-ccw.c | 6 ++++++
>  2 files changed, 12 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/s390x/css.c b/hw/s390x/css.c
> index 76dbca3bb9..9da9128d88 100644
> --- a/hw/s390x/css.c
> +++ b/hw/s390x/css.c
> @@ -654,8 +654,13 @@ void css_adapter_interrupt(CssIoAdapterType type, 
> uint8_t isc)
>      S390FLICState *fs = s390_get_flic();
>      S390FLICStateClass *fsc = s390_get_flic_class(fs);
>      uint32_t io_int_word = (isc << 27) | IO_INT_WORD_AI;
> -    IoAdapter *adapter = channel_subsys.io_adapters[type][isc];

I think this deserve a fixes/cc stable.  This would have been an
out-of-range access before this patch.

The initial support didn't have the concept of MAX_ISC, it showed up in

dde522bbc5 ("s390x: register I/O adapters per ISC during init")

Frankly I think at that point we should have started fencing
registration > MAX_ISC already, but that patch DID locally fence its new
array indexes against MAX_ISC.  It wasn't until

25a08b8ded ("s390x/css: update css_adapter_interrupt")

when the above array index was added without the fence that you are now
adding.  So I think 25a08b8ded is really the culprit.

> +    IoAdapter *adapter;
> +
> +    if (type >= CSS_IO_ADAPTER_TYPE_NUMS || isc > MAX_ISC) {
> +        return;
> +    }
>  
> +    adapter = channel_subsys.io_adapters[type][isc];
>      if (!adapter) {
>          return;
>      }
> diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
> index 30fb2c0681..eb6378ea4c 100644
> --- a/hw/s390x/virtio-ccw.c
> +++ b/hw/s390x/virtio-ccw.c
> @@ -46,6 +46,10 @@ static int virtio_ccw_dev_post_load(void *opaque, int 
> version_id)
>      CcwDevice *ccw_dev = CCW_DEVICE(dev);
>      CCWDeviceClass *ck = CCW_DEVICE_GET_CLASS(ccw_dev);
>  
> +    if (dev->thinint_isc > MAX_ISC) {
> +        return -EINVAL;
> +    }

Is this safe to check before thinint_active?

I guess if we get here before an ISC was ever set it would just be
zero-initialized so it wouldn't erroneously trigger this check.

Assuming your reasoning matches mine:

Reviewed-by: Matthew Rosato <[email protected]>

> +
>      ccw_dev->sch->driver_data = dev;
>      if (ccw_dev->sch->thinint_active) {
>          dev->routes.adapter.adapter_id = css_get_adapter_id(
> @@ -659,6 +663,8 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
>          } else {
>              if (ccw_dstream_read(&sch->cds, thinint)) {
>                  ret = -EFAULT;
> +            } else if (thinint.isc > MAX_ISC) {
> +                ret = -ENOSYS;
>              } else {
>                  thinint.ind_bit = be64_to_cpu(thinint.ind_bit);
>                  thinint.summary_indicator =


Reply via email to