From cca66d3e5f7bc1d88d79a7653ae244ba31566ee8 Mon Sep 17 00:00:00 2001 From: Ani Sinha Date: Mon, 19 Jun 2023 12:22:09 +0530 Subject: [PATCH 2/2] vhost-vdpa: do not cleanup the vdpa/vhost-net structures if peer nic is present RH-Author: Ani Sinha RH-MergeRequest: 294: vhost-vdpa: do not cleanup the vdpa/vhost-net structures if peer nic is present RH-Bugzilla: 2227721 RH-Acked-by: Miroslav Rezanina RH-Commit: [1/1] af8fa659afb3d8a2e38bb745b31d8cd665a1fc77 When a peer nic is still attached to the vdpa backend, it is too early to free up the vhost-net and vdpa structures. If these structures are freed here, then QEMU crashes when the guest is being shut down. The following call chain would result in an assertion failure since the pointer returned from vhost_vdpa_get_vhost_net() would be NULL: do_vm_stop() -> vm_state_notify() -> virtio_set_status() -> virtio_net_vhost_status() -> get_vhost_net(). Therefore, we defer freeing up the structures until at guest shutdown time when qemu_cleanup() calls net_cleanup() which then calls qemu_del_net_client() which would eventually call vhost_vdpa_cleanup() again to free up the structures. This time, the loop in net_cleanup() ensures that vhost_vdpa_cleanup() will be called one last time when all the peer nics are detached and freed. All unit tests pass with this change. CC: imammedo@redhat.com CC: jusual@redhat.com CC: mst@redhat.com Fixes: CVE-2023-3301 Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2128929 Signed-off-by: Ani Sinha Message-Id: <20230619065209.442185-1-anisinha@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin (cherry picked from commit a0d7215e339b61c7d7a7b3fcf754954d80d93eb8) Signed-off-by: Michael Tokarev (Mjt: context change for stable-7.2) (cherry picked from commit 3d12598b74ed4bcc6db8b50818a95c4b770d4487) --- net/vhost-vdpa.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index 7d9c4ea09d..1b4fec59a2 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -180,6 +180,14 @@ static void vhost_vdpa_cleanup(NetClientState *nc) VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc); struct vhost_dev *dev = &s->vhost_net->dev; + /* + * If a peer NIC is attached, do not cleanup anything. + * Cleanup will happen as a part of qemu_cleanup() -> net_cleanup() + * when the guest is shutting down. + */ + if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_NIC) { + return; + } qemu_vfree(s->cvq_cmd_out_buffer); qemu_vfree(s->status); if (dev->vq_index + dev->nvqs == dev->vq_index_end) { -- 2.39.3