Am 16.09.26 um 22:32 schrieb Eric Farman:
The various indicators pointers allow them to be overwritten, but leak any existing structs that might be there. The adapter indicators path checks that it isn't converting from regular to thin interrupts, but a check in the reverse direction isn't performed. Rather than unwinding the existing allocations to allow additional assignments, just reject these duplicates. Signed-off-by: Eric Farman <[email protected]> --- hw/s390x/virtio-ccw.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index eb6378ea4c..d700db405b 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -565,6 +565,11 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) ret = -EINVAL; break; } + if (dev->indicators) { + /* Do not set without un-setting first */ + ret = -ENOSYS; + break; + } if (sch->thinint_active) { /* Trigger a command reject. */ ret = -ENOSYS; @@ -599,6 +604,11 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) ret = -EINVAL; break; } + if (dev->indicators2) { + /* Do not set without un-setting first */ + ret = -ENOSYS; + break; + } if (!ccw.cda) { ret = -EFAULT; } else { @@ -657,7 +667,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) } if (!ccw.cda) { ret = -EFAULT; - } else if (dev->indicators && !sch->thinint_active) { + } else if (dev->indicators || dev->summary_indicator) { /* Trigger a command reject. */ ret = -ENOSYS; } else {
I think we have to do the full unwind. The Linux driver deregisters indicators by issuing SET_IND with address 0, or SET_IND_ADAPTER with device indicator 0. The virtio drivers reset the device before del_vqs, so the deregistration lands on a clean state and QEMU records an indicator at address 0. A later rebind or module reload does not reset again, so the next SET_IND_ADAPTER and the SET_IND fallback are both rejected and the probe fails. The old condition on SET_IND_ADAPTER existed precisely to let the deregistration through while thinint is active. The fix should release the existing indicator before overwriting, or treat address 0 as deregistration. Releasing before overwriting also handles the find_vqs error path in the guest, which deregisters without a reset in between.
