From d58671091daf8c325a6f1cd87737d94b5fb51d12 Mon Sep 17 00:00:00 2001 From: Jon Maloy Date: Thu, 23 Nov 2023 11:30:46 -0500 Subject: [PATCH 2/4] net: Update MemReentrancyGuard for NIC RH-Author: Jon Maloy RH-MergeRequest: 331: net: Provide MemReentrancyGuard * to qemu_new_nic() RH-Jira: RHEL-7309 RH-Acked-by: Stefan Hajnoczi RH-Acked-by: Laurent Vivier RH-Acked-by: Jason Wang RH-Commit: [2/2] b116efe725dd838c2cab9bd2240112f3c6c46d6a (redhat/rhel/src/qemu-kvm/jons-qemu-kvm-2) Jira: https://issues.redhat.com/browse/RHEL-7309 CVE: CVE-2023-3019 Upstream: Merged commit 9050f976e447444ea6ee2ba12c9f77e4b0dc54bc Author: Akihiko Odaki Date: Thu Jun 1 12:18:59 2023 +0900 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 Signed-off-by: Jon Maloy --- 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 1457b6c014..11d4564ea1 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -112,6 +112,7 @@ struct NetClientState { 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 669e194c4b..b3008a52b7 100644 --- a/net/net.c +++ b/net/net.c @@ -312,6 +312,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++) { @@ -767,6 +768,7 @@ static ssize_t qemu_deliver_packet_iov(NetClientState *sender, int iovcnt, void *opaque) { + MemReentrancyGuard *owned_reentrancy_guard; NetClientState *nc = opaque; int ret; @@ -779,12 +781,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; } -- 2.41.0