@samitouri / QOSamiQemu / commits / 46099d9900

hw/net/vmxnet3: Do not abort if guest provides bad interrupt numbers

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 Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Signed-off-by: Thomas Huth <thuth@redhat.com> Message-ID: <20260731113352.189066-1-thuth@redhat.com>

Thomas Huth committed Jul 31, 2026 at 13:33 UTC 46099d99005588b25eb07957cd9cdd688c4fc476
1 file changed +26 -8
hw/net/vmxnet3.c
+26 -8
@@ -1336,32 +1336,46 @@ static bool vmxnet3_verify_intx(VMXNET3State *s, int intx)
1336 || intx == pci_get_byte(s->parent_obj.config + PCI_INTERRUPT_PIN) - 1;
1337 }
1338
1339 -static void vmxnet3_validate_interrupt_idx(bool is_msix, int idx)
1339 +static bool vmxnet3_validate_irq_idx(const char *type, bool is_msix, int idx)
1340 {
1341 int max_ints = is_msix ? VMXNET3_MAX_INTRS : VMXNET3_MAX_NMSIX_INTRS;
1342 +
1343 if (idx >= max_ints) {
1343 - hw_error("Bad interrupt index: %d\n", idx);
1344 + qemu_log_mask(LOG_GUEST_ERROR,
1345 + "vmxnet3: Bad %s queue interrupt index: %d\n",
1346 + type, idx);
1347 + return false;
1348 }
1349 +
1350 + return true;
1351 }
1352
1347 -static void vmxnet3_validate_interrupts(VMXNET3State *s)
1353 +static bool vmxnet3_validate_interrupts(VMXNET3State *s)
1354 {
1355 int i;
1356
1357 VMW_CFPRN("Verifying event interrupt index (%d)", s->event_int_idx);
1352 - vmxnet3_validate_interrupt_idx(s->msix_used, s->event_int_idx);
1358 + if (!vmxnet3_validate_irq_idx("event", s->msix_used, s->event_int_idx)) {
1359 + return false;
1360 + }
1361
1362 for (i = 0; i < s->txq_num; i++) {
1363 int idx = s->txq_descr[i].intr_idx;
1364 VMW_CFPRN("Verifying TX queue %d interrupt index (%d)", i, idx);
1357 - vmxnet3_validate_interrupt_idx(s->msix_used, idx);
1365 + if (!vmxnet3_validate_irq_idx("TX", s->msix_used, idx)) {
1366 + return false;
1367 + }
1368 }
1369
1370 for (i = 0; i < s->rxq_num; i++) {
1371 int idx = s->rxq_descr[i].intr_idx;
1372 VMW_CFPRN("Verifying RX queue %d interrupt index (%d)", i, idx);
1363 - vmxnet3_validate_interrupt_idx(s->msix_used, idx);
1373 + if (!vmxnet3_validate_irq_idx("RX", s->msix_used, idx)) {
1374 + return false;
1375 + }
1376 }
1377 +
1378 + return true;
1379 }
1380
1381 static bool vmxnet3_validate_queues(VMXNET3State *s)
@@ -1554,7 +1568,9 @@ static void vmxnet3_activate_device(VMXNET3State *s)
1568 sizeof(s->rxq_descr[i].rxq_stats));
1569 }
1570
1557 - vmxnet3_validate_interrupts(s);
1571 + if (!vmxnet3_validate_interrupts(s)) {
1572 + return;
1573 + }
1574
1575 /* Make sure everything is in place before device activation */
1576 smp_wmb();
@@ -2392,7 +2408,9 @@ static int vmxnet3_post_load(void *opaque, int version_id)
2408 if (!vmxnet3_validate_queues(s)) {
2409 return -1;
2410 }
2395 - vmxnet3_validate_interrupts(s);
2411 + if (!vmxnet3_validate_interrupts(s)) {
2412 + return -1;
2413 + }
2414
2415 return 0;
2416 }