Skip to content

Commit

Permalink
net: Update MemReentrancyGuard for NIC
Browse files Browse the repository at this point in the history
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>
(cherry picked from commit 9050f97)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
  • Loading branch information
akihikodaki authored and Michael Tokarev committed Nov 29, 2023
1 parent fdebed6 commit 3c0463a
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 0 deletions.
1 change: 1 addition & 0 deletions include/net/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ struct NetClientState {
typedef struct NICState {
NetClientState *ncs;
NICConf *conf;
MemReentrancyGuard *reentrancy_guard;
void *opaque;
bool peer_deleted;
} NICState;
Expand Down
14 changes: 14 additions & 0 deletions net/net.c
Original file line number Diff line number Diff line change
Expand Up @@ -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++) {
Expand Down Expand Up @@ -787,6 +788,7 @@ static ssize_t qemu_deliver_packet_iov(NetClientState *sender,
int iovcnt,
void *opaque)
{
MemReentrancyGuard *owned_reentrancy_guard;
NetClientState *nc = opaque;
int ret;

Expand All @@ -799,12 +801,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;
}
Expand Down

0 comments on commit 3c0463a

Please sign in to comment.