106 lines
3.5 KiB
Diff
106 lines
3.5 KiB
Diff
From d58671091daf8c325a6f1cd87737d94b5fb51d12 Mon Sep 17 00:00:00 2001
|
|
From: Jon Maloy <jmaloy@redhat.com>
|
|
Date: Thu, 23 Nov 2023 11:30:46 -0500
|
|
Subject: [PATCH 2/4] net: Update MemReentrancyGuard for NIC
|
|
|
|
RH-Author: Jon Maloy <jmaloy@redhat.com>
|
|
RH-MergeRequest: 331: net: Provide MemReentrancyGuard * to qemu_new_nic()
|
|
RH-Jira: RHEL-7309
|
|
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
|
|
RH-Acked-by: Jason Wang <jasowang@redhat.com>
|
|
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 <akihiko.odaki@daynix.com>
|
|
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 <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>
|
|
|
|
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
|
|
---
|
|
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
|
|
|