From 7d0fefdf81f5973334c344f6b8e1896c309dff66 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Thu, 1 Jun 2023 12:18:58 +0900 Subject: [PATCH 1/3] net: Provide MemReentrancyGuard * to qemu_new_nic() Recently MemReentrancyGuard was added to DeviceState to record that the device is engaging in I/O. The network device backend needs to update it when delivering a packet to a device. In preparation for such a change, add MemReentrancyGuard * as a parameter of qemu_new_nic(). Signed-off-by: Akihiko Odaki Reviewed-by: Alexander Bulekov Signed-off-by: Jason Wang --- hw/net/allwinner-sun8i-emac.c | 3 ++- hw/net/allwinner_emac.c | 3 ++- hw/net/cadence_gem.c | 3 ++- hw/net/dp8393x.c | 3 ++- hw/net/e1000.c | 3 ++- hw/net/e1000e.c | 2 +- hw/net/eepro100.c | 4 +++- hw/net/etraxfs_eth.c | 3 ++- hw/net/fsl_etsec/etsec.c | 3 ++- hw/net/ftgmac100.c | 3 ++- hw/net/i82596.c | 2 +- hw/net/igb.c | 2 +- hw/net/imx_fec.c | 2 +- hw/net/lan9118.c | 3 ++- hw/net/mcf_fec.c | 3 ++- hw/net/mipsnet.c | 3 ++- hw/net/msf2-emac.c | 3 ++- hw/net/mv88w8618_eth.c | 3 ++- hw/net/ne2000-isa.c | 3 ++- hw/net/ne2000-pci.c | 3 ++- hw/net/npcm7xx_emc.c | 3 ++- hw/net/opencores_eth.c | 3 ++- hw/net/pcnet.c | 3 ++- hw/net/rocker/rocker_fp.c | 4 ++-- hw/net/rtl8139.c | 3 ++- hw/net/smc91c111.c | 3 ++- hw/net/spapr_llan.c | 3 ++- hw/net/stellaris_enet.c | 3 ++- hw/net/sungem.c | 2 +- hw/net/sunhme.c | 3 ++- hw/net/tulip.c | 3 ++- hw/net/virtio-net.c | 6 ++++-- hw/net/vmxnet3.c | 2 +- hw/net/xen_nic.c | 3 ++- hw/net/xgmac.c | 3 ++- hw/net/xilinx_axienet.c | 3 ++- hw/net/xilinx_ethlite.c | 3 ++- hw/usb/dev-network.c | 3 ++- include/net/net.h | 1 + net/net.c | 1 + 40 files changed, 75 insertions(+), 40 deletions(-) diff --git a/hw/net/allwinner-sun8i-emac.c b/hw/net/allwinner-sun8i-emac.c index fac4405f45..cc350d40e5 100644 --- a/hw/net/allwinner-sun8i-emac.c +++ b/hw/net/allwinner-sun8i-emac.c @@ -824,7 +824,8 @@ static void allwinner_sun8i_emac_realize(DeviceState *dev, Error **errp) qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_allwinner_sun8i_emac_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); } diff --git a/hw/net/allwinner_emac.c b/hw/net/allwinner_emac.c index 372e5b66da..e10965de14 100644 --- a/hw/net/allwinner_emac.c +++ b/hw/net/allwinner_emac.c @@ -453,7 +453,8 @@ static void aw_emac_realize(DeviceState *dev, Error **errp) qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_aw_emac_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); fifo8_create(&s->rx_fifo, RX_FIFO_SIZE); diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index 19adbc0e19..296bba238e 100644 --- a/hw/net/cadence_gem.c +++ b/hw/net/cadence_gem.c @@ -1743,7 +1743,8 @@ static void gem_realize(DeviceState *dev, Error **errp) qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_gem_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); if (s->jumbo_max_len > MAX_FRAME_SIZE) { error_setg(errp, "jumbo-max-len is greater than %d", diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c index c6f5fb7dce..b16b18b3c3 100644 --- a/hw/net/dp8393x.c +++ b/hw/net/dp8393x.c @@ -913,7 +913,8 @@ static void dp8393x_realize(DeviceState *dev, Error **errp) "dp8393x-regs", SONIC_REG_COUNT << s->it_shift); s->nic = qemu_new_nic(&net_dp83932_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); s->watchdog = timer_new_ns(QEMU_CLOCK_VIRTUAL, dp8393x_watchdog, s); diff --git a/hw/net/e1000.c b/hw/net/e1000.c index 548bcabcbb..8ffe1077f1 100644 --- a/hw/net/e1000.c +++ b/hw/net/e1000.c @@ -1666,7 +1666,8 @@ static void pci_e1000_realize(PCIDevice *pci_dev, Error **errp) macaddr); d->nic = qemu_new_nic(&net_e1000_info, &d->conf, - object_get_typename(OBJECT(d)), dev->id, d); + object_get_typename(OBJECT(d)), dev->id, + &dev->mem_reentrancy_guard, d); qemu_format_nic_info_str(qemu_get_queue(d->nic), macaddr); diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c index c3848797b8..e41a6c1038 100644 --- a/hw/net/e1000e.c +++ b/hw/net/e1000e.c @@ -320,7 +320,7 @@ e1000e_init_net_peer(E1000EState *s, PCIDevice *pci_dev, uint8_t *macaddr) int i; s->nic = qemu_new_nic(&net_e1000e_info, &s->conf, - object_get_typename(OBJECT(s)), dev->id, s); + object_get_typename(OBJECT(s)), dev->id, &dev->mem_reentrancy_guard, s); s->core.max_queue_num = s->conf.peers.queues ? s->conf.peers.queues - 1 : 0; diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c index 94ce9e18ff..69e1c4bb89 100644 --- a/hw/net/eepro100.c +++ b/hw/net/eepro100.c @@ -1874,7 +1874,9 @@ static void e100_nic_realize(PCIDevice *pci_dev, Error **errp) nic_reset(s); s->nic = qemu_new_nic(&net_eepro100_info, &s->conf, - object_get_typename(OBJECT(pci_dev)), pci_dev->qdev.id, s); + object_get_typename(OBJECT(pci_dev)), + pci_dev->qdev.id, + &pci_dev->qdev.mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); TRACE(OTHER, logout("%s\n", qemu_get_queue(s->nic)->info_str)); diff --git a/hw/net/etraxfs_eth.c b/hw/net/etraxfs_eth.c index 1b82aec794..ba57a978d1 100644 --- a/hw/net/etraxfs_eth.c +++ b/hw/net/etraxfs_eth.c @@ -618,7 +618,8 @@ static void etraxfs_eth_realize(DeviceState *dev, Error **errp) qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_etraxfs_info, &s->conf, - object_get_typename(OBJECT(s)), dev->id, s); + object_get_typename(OBJECT(s)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); s->phy.read = tdk_read; diff --git a/hw/net/fsl_etsec/etsec.c b/hw/net/fsl_etsec/etsec.c index 798ea33d08..00315f305d 100644 --- a/hw/net/fsl_etsec/etsec.c +++ b/hw/net/fsl_etsec/etsec.c @@ -391,7 +391,8 @@ static void etsec_realize(DeviceState *dev, Error **errp) eTSEC *etsec = ETSEC_COMMON(dev); etsec->nic = qemu_new_nic(&net_etsec_info, &etsec->conf, - object_get_typename(OBJECT(dev)), dev->id, etsec); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, etsec); qemu_format_nic_info_str(qemu_get_queue(etsec->nic), etsec->conf.macaddr.a); etsec->ptimer = ptimer_init(etsec_timer_hit, etsec, PTIMER_POLICY_LEGACY); diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c index 702b001be2..78e594afa4 100644 --- a/hw/net/ftgmac100.c +++ b/hw/net/ftgmac100.c @@ -1110,7 +1110,8 @@ static void ftgmac100_realize(DeviceState *dev, Error **errp) qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_ftgmac100_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); } diff --git a/hw/net/i82596.c b/hw/net/i82596.c index 6defa9d3a1..a907f0df8c 100644 --- a/hw/net/i82596.c +++ b/hw/net/i82596.c @@ -726,7 +726,7 @@ void i82596_common_init(DeviceState *dev, I82596State *s, NetClientInfo *info) qemu_macaddr_default_if_unset(&s->conf.macaddr); } s->nic = qemu_new_nic(info, &s->conf, object_get_typename(OBJECT(dev)), - dev->id, s); + dev->id, &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); if (USE_TIMER) { diff --git a/hw/net/igb.c b/hw/net/igb.c index dfb722b695..8089acfea4 100644 --- a/hw/net/igb.c +++ b/hw/net/igb.c @@ -325,7 +325,7 @@ igb_init_net_peer(IGBState *s, PCIDevice *pci_dev, uint8_t *macaddr) int i; s->nic = qemu_new_nic(&net_igb_info, &s->conf, - object_get_typename(OBJECT(s)), dev->id, s); + object_get_typename(OBJECT(s)), dev->id, &dev->mem_reentrancy_guard, s); s->core.max_queue_num = s->conf.peers.queues ? s->conf.peers.queues - 1 : 0; diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c index 5d1f1f104c..6881e3e4f0 100644 --- a/hw/net/imx_fec.c +++ b/hw/net/imx_fec.c @@ -1334,7 +1334,7 @@ static void imx_eth_realize(DeviceState *dev, Error **errp) s->nic = qemu_new_nic(&imx_eth_net_info, &s->conf, object_get_typename(OBJECT(dev)), - dev->id, s); + dev->id, &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); } diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c index e5c4af182d..cf7b8c897a 100644 --- a/hw/net/lan9118.c +++ b/hw/net/lan9118.c @@ -1361,7 +1361,8 @@ static void lan9118_realize(DeviceState *dev, Error **errp) qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_lan9118_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); s->eeprom[0] = 0xa5; for (i = 0; i < 6; i++) { diff --git a/hw/net/mcf_fec.c b/hw/net/mcf_fec.c index ec3ddf520a..e6902716bd 100644 --- a/hw/net/mcf_fec.c +++ b/hw/net/mcf_fec.c @@ -643,7 +643,8 @@ static void mcf_fec_realize(DeviceState *dev, Error **errp) mcf_fec_state *s = MCF_FEC_NET(dev); s->nic = qemu_new_nic(&net_mcf_fec_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); } diff --git a/hw/net/mipsnet.c b/hw/net/mipsnet.c index 2ade72dea0..8e925de867 100644 --- a/hw/net/mipsnet.c +++ b/hw/net/mipsnet.c @@ -255,7 +255,8 @@ static void mipsnet_realize(DeviceState *dev, Error **errp) sysbus_init_irq(sbd, &s->irq); s->nic = qemu_new_nic(&net_mipsnet_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); } diff --git a/hw/net/msf2-emac.c b/hw/net/msf2-emac.c index db3a04deb1..145a5e46ab 100644 --- a/hw/net/msf2-emac.c +++ b/hw/net/msf2-emac.c @@ -530,7 +530,8 @@ static void msf2_emac_realize(DeviceState *dev, Error **errp) qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_msf2_emac_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); } diff --git a/hw/net/mv88w8618_eth.c b/hw/net/mv88w8618_eth.c index ef30b0d4a6..2185f1131a 100644 --- a/hw/net/mv88w8618_eth.c +++ b/hw/net/mv88w8618_eth.c @@ -350,7 +350,8 @@ static void mv88w8618_eth_realize(DeviceState *dev, Error **errp) address_space_init(&s->dma_as, s->dma_mr, "emac-dma"); s->nic = qemu_new_nic(&net_mv88w8618_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); } static const VMStateDescription mv88w8618_eth_vmsd = { diff --git a/hw/net/ne2000-isa.c b/hw/net/ne2000-isa.c index 6ced6775ff..a79f7fad1f 100644 --- a/hw/net/ne2000-isa.c +++ b/hw/net/ne2000-isa.c @@ -74,7 +74,8 @@ static void isa_ne2000_realizefn(DeviceState *dev, Error **errp) ne2000_reset(s); s->nic = qemu_new_nic(&net_ne2000_isa_info, &s->c, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->c.macaddr.a); } diff --git a/hw/net/ne2000-pci.c b/hw/net/ne2000-pci.c index edc6689d33..fee93c6ec0 100644 --- a/hw/net/ne2000-pci.c +++ b/hw/net/ne2000-pci.c @@ -71,7 +71,8 @@ static void pci_ne2000_realize(PCIDevice *pci_dev, Error **errp) s->nic = qemu_new_nic(&net_ne2000_info, &s->c, object_get_typename(OBJECT(pci_dev)), - pci_dev->qdev.id, s); + pci_dev->qdev.id, + &pci_dev->qdev.mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->c.macaddr.a); } diff --git a/hw/net/npcm7xx_emc.c b/hw/net/npcm7xx_emc.c index 8156f701b0..1d4e8f59f3 100644 --- a/hw/net/npcm7xx_emc.c +++ b/hw/net/npcm7xx_emc.c @@ -821,7 +821,8 @@ static void npcm7xx_emc_realize(DeviceState *dev, Error **errp) qemu_macaddr_default_if_unset(&emc->conf.macaddr); emc->nic = qemu_new_nic(&net_npcm7xx_emc_info, &emc->conf, - object_get_typename(OBJECT(dev)), dev->id, emc); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, emc); qemu_format_nic_info_str(qemu_get_queue(emc->nic), emc->conf.macaddr.a); } diff --git a/hw/net/opencores_eth.c b/hw/net/opencores_eth.c index 0b3dc3146e..f96d6ea2cc 100644 --- a/hw/net/opencores_eth.c +++ b/hw/net/opencores_eth.c @@ -732,7 +732,8 @@ static void sysbus_open_eth_realize(DeviceState *dev, Error **errp) sysbus_init_irq(sbd, &s->irq); s->nic = qemu_new_nic(&net_open_eth_info, &s->conf, - object_get_typename(OBJECT(s)), dev->id, s); + object_get_typename(OBJECT(s)), dev->id, + &dev->mem_reentrancy_guard, s); } static void qdev_open_eth_reset(DeviceState *dev) diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c index 02828ae716..a7e123e60d 100644 --- a/hw/net/pcnet.c +++ b/hw/net/pcnet.c @@ -1709,7 +1709,8 @@ void pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info) s->poll_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pcnet_poll_timer, s); qemu_macaddr_default_if_unset(&s->conf.macaddr); - s->nic = qemu_new_nic(info, &s->conf, object_get_typename(OBJECT(dev)), dev->id, s); + s->nic = qemu_new_nic(info, &s->conf, object_get_typename(OBJECT(dev)), + dev->id, &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); /* Initialize the PROM */ diff --git a/hw/net/rocker/rocker_fp.c b/hw/net/rocker/rocker_fp.c index 9afd0c5e3f..cb87ff752a 100644 --- a/hw/net/rocker/rocker_fp.c +++ b/hw/net/rocker/rocker_fp.c @@ -241,8 +241,8 @@ FpPort *fp_port_alloc(Rocker *r, char *sw_name, port->conf.bootindex = -1; port->conf.peers = *peers; - port->nic = qemu_new_nic(&fp_port_info, &port->conf, - sw_name, NULL, port); + port->nic = qemu_new_nic(&fp_port_info, &port->conf, sw_name, NULL, + &DEVICE(r)->mem_reentrancy_guard, port); qemu_format_nic_info_str(qemu_get_queue(port->nic), port->conf.macaddr.a); diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c index 4525fda383..4af8c66266 100644 --- a/hw/net/rtl8139.c +++ b/hw/net/rtl8139.c @@ -3388,7 +3388,8 @@ static void pci_rtl8139_realize(PCIDevice *dev, Error **errp) s->eeprom.contents[9] = s->conf.macaddr.a[4] | s->conf.macaddr.a[5] << 8; s->nic = qemu_new_nic(&net_rtl8139_info, &s->conf, - object_get_typename(OBJECT(dev)), d->id, s); + object_get_typename(OBJECT(dev)), d->id, + &d->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); s->cplus_txbuffer = NULL; diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c index ddbceda967..876a78456a 100644 --- a/hw/net/smc91c111.c +++ b/hw/net/smc91c111.c @@ -783,7 +783,8 @@ static void smc91c111_realize(DeviceState *dev, Error **errp) sysbus_init_irq(sbd, &s->irq); qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_smc91c111_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); /* ??? Save/restore. */ } diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c index a6876a936d..475d5f3a34 100644 --- a/hw/net/spapr_llan.c +++ b/hw/net/spapr_llan.c @@ -325,7 +325,8 @@ static void spapr_vlan_realize(SpaprVioDevice *sdev, Error **errp) memcpy(&dev->perm_mac.a, &dev->nicconf.macaddr.a, sizeof(dev->perm_mac.a)); dev->nic = qemu_new_nic(&net_spapr_vlan_info, &dev->nicconf, - object_get_typename(OBJECT(sdev)), sdev->qdev.id, dev); + object_get_typename(OBJECT(sdev)), sdev->qdev.id, + &sdev->qdev.mem_reentrancy_guard, dev); qemu_format_nic_info_str(qemu_get_queue(dev->nic), dev->nicconf.macaddr.a); dev->rxp_timer = timer_new_us(QEMU_CLOCK_VIRTUAL, spapr_vlan_flush_rx_queue, diff --git a/hw/net/stellaris_enet.c b/hw/net/stellaris_enet.c index 8dd60783d8..6768a6912f 100644 --- a/hw/net/stellaris_enet.c +++ b/hw/net/stellaris_enet.c @@ -492,7 +492,8 @@ static void stellaris_enet_realize(DeviceState *dev, Error **errp) qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_stellaris_enet_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); } diff --git a/hw/net/sungem.c b/hw/net/sungem.c index c2e2c90668..013cfc2736 100644 --- a/hw/net/sungem.c +++ b/hw/net/sungem.c @@ -1399,7 +1399,7 @@ static void sungem_realize(PCIDevice *pci_dev, Error **errp) qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_sungem_info, &s->conf, object_get_typename(OBJECT(dev)), - dev->id, s); + dev->id, &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); } diff --git a/hw/net/sunhme.c b/hw/net/sunhme.c index 64d4ea5850..ddc83a64bd 100644 --- a/hw/net/sunhme.c +++ b/hw/net/sunhme.c @@ -881,7 +881,8 @@ static void sunhme_realize(PCIDevice *pci_dev, Error **errp) qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_sunhme_info, &s->conf, - object_get_typename(OBJECT(d)), d->id, s); + object_get_typename(OBJECT(d)), d->id, + &d->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); } diff --git a/hw/net/tulip.c b/hw/net/tulip.c index 11d866e431..962086aae4 100644 --- a/hw/net/tulip.c +++ b/hw/net/tulip.c @@ -983,7 +983,8 @@ static void pci_tulip_realize(PCIDevice *pci_dev, Error **errp) s->nic = qemu_new_nic(&net_tulip_info, &s->c, object_get_typename(OBJECT(pci_dev)), - pci_dev->qdev.id, s); + pci_dev->qdev.id, + &pci_dev->qdev.mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->c.macaddr.a); } diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index b85c7946a7..80c56f0cfc 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -3714,10 +3714,12 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp) * Happen when virtio_net_set_netclient_name has been called. */ n->nic = qemu_new_nic(&net_virtio_info, &n->nic_conf, - n->netclient_type, n->netclient_name, n); + n->netclient_type, n->netclient_name, + &dev->mem_reentrancy_guard, n); } else { n->nic = qemu_new_nic(&net_virtio_info, &n->nic_conf, - object_get_typename(OBJECT(dev)), dev->id, n); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, n); } for (i = 0; i < n->max_queue_pairs; i++) { diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c index 1b48d7743e..6fb4102d03 100644 --- a/hw/net/vmxnet3.c +++ b/hw/net/vmxnet3.c @@ -2078,7 +2078,7 @@ static void vmxnet3_net_init(VMXNET3State *s) s->nic = qemu_new_nic(&net_vmxnet3_info, &s->conf, object_get_typename(OBJECT(s)), - d->id, s); + d->id, &d->mem_reentrancy_guard, s); s->peer_has_vhdr = vmxnet3_peer_has_vnet_hdr(s); s->tx_sop = true; diff --git a/hw/net/xen_nic.c b/hw/net/xen_nic.c index af4ba3f1e6..1e2b3baeb1 100644 --- a/hw/net/xen_nic.c +++ b/hw/net/xen_nic.c @@ -325,7 +325,8 @@ static void xen_netdev_realize(XenDevice *xendev, Error **errp) netdev->nic = qemu_new_nic(&net_xen_info, &netdev->conf, object_get_typename(OBJECT(xendev)), - DEVICE(xendev)->id, netdev); + DEVICE(xendev)->id, + &xendev->qdev.mem_reentrancy_guard, netdev); nc = qemu_get_queue(netdev->nic); qemu_format_nic_info_str(nc, netdev->conf.macaddr.a); diff --git a/hw/net/xgmac.c b/hw/net/xgmac.c index 0ab6ae91aa..1f4f277d84 100644 --- a/hw/net/xgmac.c +++ b/hw/net/xgmac.c @@ -402,7 +402,8 @@ static void xgmac_enet_realize(DeviceState *dev, Error **errp) qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_xgmac_enet_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); s->regs[XGMAC_ADDR_HIGH(0)] = (s->conf.macaddr.a[5] << 8) | diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c index 5b19a01eaa..7d1fd37b4a 100644 --- a/hw/net/xilinx_axienet.c +++ b/hw/net/xilinx_axienet.c @@ -967,7 +967,8 @@ static void xilinx_enet_realize(DeviceState *dev, Error **errp) qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_xilinx_enet_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); tdk_init(&s->TEMAC.phy); diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c index 89f4f3b254..989afaf037 100644 --- a/hw/net/xilinx_ethlite.c +++ b/hw/net/xilinx_ethlite.c @@ -235,7 +235,8 @@ static void xilinx_ethlite_realize(DeviceState *dev, Error **errp) qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_xilinx_ethlite_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); } diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index 5fff487ee5..2c33e36cad 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -1386,7 +1386,8 @@ static void usb_net_realize(USBDevice *dev, Error **errp) qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_usbnet_info, &s->conf, - object_get_typename(OBJECT(s)), s->dev.qdev.id, s); + object_get_typename(OBJECT(s)), s->dev.qdev.id, + &s->dev.qdev.mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); snprintf(s->usbstring_mac, sizeof(s->usbstring_mac), "%02x%02x%02x%02x%02x%02x", diff --git a/include/net/net.h b/include/net/net.h index 2fb1c9181c..24deea2dbd 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -159,6 +159,7 @@ NICState *qemu_new_nic(NetClientInfo *info, NICConf *conf, const char *model, const char *name, + MemReentrancyGuard *reentrancy_guard, void *opaque); void qemu_del_nic(NICState *nic); NetClientState *qemu_get_subqueue(NICState *nic, int queue_index); diff --git a/net/net.c b/net/net.c index 8e67a20abc..aaf0c2bb81 100644 --- a/net/net.c +++ b/net/net.c @@ -319,6 +319,7 @@ NICState *qemu_new_nic(NetClientInfo *info, NICConf *conf, const char *model, const char *name, + MemReentrancyGuard *reentrancy_guard, void *opaque) { NetClientState **peers = conf->peers.ncs; From 9050f976e447444ea6ee2ba12c9f77e4b0dc54bc Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Thu, 1 Jun 2023 12:18:59 +0900 Subject: [PATCH 2/3] net: Update MemReentrancyGuard for NIC Recently MemReentrancyGuard was added to DeviceState to record that the device is engaging in I/O. The network device backend needs to update it when delivering a packet to a device. This implementation follows what bottom half does, but it does not add a tracepoint for the case that the network device backend started delivering a packet to a device which is already engaging in I/O. This is because such reentrancy frequently happens for qemu_flush_queued_packets() and is insignificant. Fixes: CVE-2023-3019 Reported-by: Alexander Bulekov Signed-off-by: Akihiko Odaki Acked-by: Alexander Bulekov Signed-off-by: Jason Wang --- include/net/net.h | 1 + net/net.c | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/include/net/net.h b/include/net/net.h index 24deea2dbd..ffbd2c8d56 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -126,6 +126,7 @@ typedef QTAILQ_HEAD(NetClientStateList, NetClientState) NetClientStateList; typedef struct NICState { NetClientState *ncs; NICConf *conf; + MemReentrancyGuard *reentrancy_guard; void *opaque; bool peer_deleted; } NICState; diff --git a/net/net.c b/net/net.c index aaf0c2bb81..4d1ff7ae47 100644 --- a/net/net.c +++ b/net/net.c @@ -332,6 +332,7 @@ NICState *qemu_new_nic(NetClientInfo *info, nic = g_malloc0(info->size + sizeof(NetClientState) * queues); nic->ncs = (void *)nic + info->size; nic->conf = conf; + nic->reentrancy_guard = reentrancy_guard, nic->opaque = opaque; for (i = 0; i < queues; i++) { @@ -814,6 +815,7 @@ static ssize_t qemu_deliver_packet_iov(NetClientState *sender, int iovcnt, void *opaque) { + MemReentrancyGuard *owned_reentrancy_guard; NetClientState *nc = opaque; int ret; @@ -826,12 +828,24 @@ static ssize_t qemu_deliver_packet_iov(NetClientState *sender, return 0; } + if (nc->info->type != NET_CLIENT_DRIVER_NIC || + qemu_get_nic(nc)->reentrancy_guard->engaged_in_io) { + owned_reentrancy_guard = NULL; + } else { + owned_reentrancy_guard = qemu_get_nic(nc)->reentrancy_guard; + owned_reentrancy_guard->engaged_in_io = true; + } + if (nc->info->receive_iov && !(flags & QEMU_NET_PACKET_FLAG_RAW)) { ret = nc->info->receive_iov(nc, iov, iovcnt); } else { ret = nc_sendv_compat(nc, iov, iovcnt, flags); } + if (owned_reentrancy_guard) { + owned_reentrancy_guard->engaged_in_io = false; + } + if (ret == 0) { nc->receive_disabled = 1; } From 84f85eb95f14add02efd5e69f2ff7783d79b24f7 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 15 Nov 2023 17:24:35 +0000 Subject: [PATCH 3/3] net: do not delete nics in net_cleanup() In net_cleanup() we only need to delete the netdevs, as those may have state which outlives Qemu when it exits, and thus may actually need to be cleaned up on exit. The nics, on the other hand, are owned by the device which created them. Most devices don't bother to clean up on exit because they don't have any state which will outlive Qemu... but XenBus devices do need to clean up their nodes in XenStore, and do have an exit handler to delete them. When the XenBus exit handler destroys the xen-net-device, it attempts to delete its nic after net_cleanup() had already done so. And crashes. Fix this by only deleting netdevs as we walk the list. As the comment notes, we can't use QTAILQ_FOREACH_SAFE() as each deletion may remove *multiple* entries, including the "safely" saved 'next' pointer. But we can store the *previous* entry, since nics are safe. Signed-off-by: David Woodhouse Reviewed-by: Paul Durrant Signed-off-by: Jason Wang --- net/net.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/net/net.c b/net/net.c index 4d1ff7ae47..0520bc1681 100644 --- a/net/net.c +++ b/net/net.c @@ -1514,18 +1514,34 @@ static void net_vm_change_state_handler(void *opaque, bool running, void net_cleanup(void) { - NetClientState *nc; + NetClientState *nc, **p = &QTAILQ_FIRST(&net_clients); /*cleanup colo compare module for COLO*/ colo_compare_cleanup(); - /* We may del multiple entries during qemu_del_net_client(), - * so QTAILQ_FOREACH_SAFE() is also not safe here. + /* + * Walk the net_clients list and remove the netdevs but *not* any + * NET_CLIENT_DRIVER_NIC entries. The latter are owned by the device + * model which created them, and in some cases (e.g. xen-net-device) + * the device itself may do cleanup at exit and will be upset if we + * just delete its NIC from underneath it. + * + * Since qemu_del_net_client() may delete multiple entries, using + * QTAILQ_FOREACH_SAFE() is not safe here. The only safe pointer + * to keep as a bookmark is a NET_CLIENT_DRIVER_NIC entry, so keep + * 'p' pointing to either the head of the list, or the 'next' field + * of the latest NET_CLIENT_DRIVER_NIC, and operate on *p as we walk + * the list. + * + * The 'nc' variable isn't part of the list traversal; it's purely + * for convenience as too much '(*p)->' has a tendency to make the + * readers' eyes bleed. */ - while (!QTAILQ_EMPTY(&net_clients)) { - nc = QTAILQ_FIRST(&net_clients); + while (*p) { + nc = *p; if (nc->info->type == NET_CLIENT_DRIVER_NIC) { - qemu_del_nic(qemu_get_nic(nc)); + /* Skip NET_CLIENT_DRIVER_NIC entries */ + p = &QTAILQ_NEXT(nc, next); } else { qemu_del_net_client(nc); }