Re: [PATCH] hw/net/vmxnet3: Do not abort if guest provides bad interrupt numbers

Thomas Huth <[email protected]> Fri, 31 Jul 2026 13:16:24 +0200
Newsgroups org.nongnu.qemu-trivial,org.nongnu.qemu-devel
Message-ID <[email protected]>
On 31/07/2026 08.03, Philippe Mathieu-Daudé wrote:
> Hi Thomas,
> 
> On 30/7/26 16:39, Thomas Huth wrote:
>> From: Thomas Huth <[email protected]>
>>
>> vmxnet3_validate_interrupts() currently aborts via hw_error() if
>> the guest provided bad interrupt numbers. This should not happen,
>> QEMU should rather refuse to activate the device in this case instead.
>> Thus propagate the error to the callers to handle it more gracefully
>> there.
>>
>> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/539
>> Signed-off-by: Thomas Huth <[email protected]>
>> ---
>>   hw/net/vmxnet3.c | 35 +++++++++++++++++++++++++++--------
>>   1 file changed, 27 insertions(+), 8 deletions(-)
>>
>> diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
>> index 8569484b2f2..1c5d1d740cc 100644
>> --- a/hw/net/vmxnet3.c
>> +++ b/hw/net/vmxnet3.c
>> @@ -1336,32 +1336,46 @@ static bool vmxnet3_verify_intx(VMXNET3State *s, 
>> int intx)
>>           || intx == pci_get_byte(s->parent_obj.config + 
>> PCI_INTERRUPT_PIN) - 1;
>>   }
>> -static void vmxnet3_validate_interrupt_idx(bool is_msix, int idx)
>> +static bool vmxnet3_validate_irq_idx(const char *type, bool is_msix, int 
>> idx)
>>   {
>>       int max_ints = is_msix ? VMXNET3_MAX_INTRS : VMXNET3_MAX_NMSIX_INTRS;
>> +
>>       if (idx >= max_ints) {
>> -        hw_error("Bad interrupt index: %d\n", idx);
>> +        qemu_log_mask(LOG_GUEST_ERROR,
>> +                      "vmxnet3: Bad %s queue interrupt index: %d\n",
>> +                      type, idx);
>> +        return false;
>>       }
>> +
>> +    return true;
>>   }
>> -static void vmxnet3_validate_interrupts(VMXNET3State *s)
>> +static bool vmxnet3_validate_interrupts(VMXNET3State *s)
>>   {
>>       int i;
>>       VMW_CFPRN("Verifying event interrupt index (%d)", s->event_int_idx);
>> -    vmxnet3_validate_interrupt_idx(s->msix_used, s->event_int_idx);
>> +    if (!vmxnet3_validate_irq_idx("event", s->msix_used, s- 
>> >event_int_idx)) {
>> +        return false;
>> +    }
>>       for (i = 0; i < s->txq_num; i++) {
>>           int idx = s->txq_descr[i].intr_idx;
>>           VMW_CFPRN("Verifying TX queue %d interrupt index (%d)", i, idx);
>> -        vmxnet3_validate_interrupt_idx(s->msix_used, idx);
>> +        if (!vmxnet3_validate_irq_idx("TX", s->msix_used, idx)) {
>> +            return false;
>> +        }
>>       }
>>       for (i = 0; i < s->rxq_num; i++) {
>>           int idx = s->rxq_descr[i].intr_idx;
>>           VMW_CFPRN("Verifying RX queue %d interrupt index (%d)", i, idx);
>> -        vmxnet3_validate_interrupt_idx(s->msix_used, idx);
>> +        if (!vmxnet3_validate_irq_idx("RX", s->msix_used, idx)) {
>> +            return false;
>> +        }
>>       }
>> +
>> +    return true;
>>   }
>>   static bool vmxnet3_validate_queues(VMXNET3State *s)
>> @@ -1554,7 +1568,10 @@ static void vmxnet3_activate_device(VMXNET3State *s)
>>                  sizeof(s->rxq_descr[i].rxq_stats));
>>       }
>> -    vmxnet3_validate_interrupts(s);
>> +    if (!vmxnet3_validate_interrupts(s)) {
>> +        vmxnet3_reset(s);
>> +        return;
> 
> We definitively want to return here to not set s->device_active,
> but calling vmxnet3_reset() in the middle of a command handler is
> surprising. Maybe call it in the caller?
I've added it here as precautionary measure, but looking at the code flow 
again, it's likely not really necessary here: vmxnet3_deactivate_device() 
does not do anything at all since device_active has not been set yet. And 
all the other early returns in vmxnet3_activate_device() also don't do this.

So let's simply drop that vmxnet3_reset() from the patch. I'll send a v2...

  Thomas