diff options
| author | Akihiko Odaki <akihiko.odaki@daynix.com> | 2023-06-01 12:18:59 +0900 |
|---|---|---|
| committer | Jason Wang <jasowang@redhat.com> | 2023-11-21 15:42:34 +0800 |
| commit | 9050f976e447444ea6ee2ba12c9f77e4b0dc54bc (patch) | |
| tree | f538085c9963ed31cb8f84df51d9b18c8b389d25 /net/net.c | |
| parent | 7d0fefdf81f5973334c344f6b8e1896c309dff66 (diff) | |
| download | focaccia-qemu-9050f976e447444ea6ee2ba12c9f77e4b0dc54bc.tar.gz focaccia-qemu-9050f976e447444ea6ee2ba12c9f77e4b0dc54bc.zip | |
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 <alxndr@bu.edu> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> Acked-by: Alexander Bulekov <alxndr@bu.edu> Signed-off-by: Jason Wang <jasowang@redhat.com>
Diffstat (limited to '')
| -rw-r--r-- | net/net.c | 14 |
1 files changed, 14 insertions, 0 deletions
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; } |