aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHawkins Jiawei <yin31149@gmail.com>2023-07-08 00:44:42 +0800
committerMichael Tokarev <mjt@tls.msk.ru>2023-08-05 20:49:49 +0300
commitade1bed2b7c2b64499d63a4f4ba445463dbc96f7 (patch)
treee8591b6b512c13313651e35dd64a3a86dd3451cf
parente85ab8f753112c96f81fbd7cae08a5753b477b26 (diff)
vdpa: Fix possible use-after-free for VirtQueueElement
QEMU uses vhost_handle_guest_kick() to forward guest's available buffers to the vdpa device in SVQ avail ring. In vhost_handle_guest_kick(), a `g_autofree` `elem` is used to iterate through the available VirtQueueElements. This `elem` is then passed to `svq->ops->avail_handler`, specifically to the vhost_vdpa_net_handle_ctrl_avail(). If this handler fails to process the CVQ command, vhost_handle_guest_kick() regains ownership of the `elem`, and either frees it or requeues it. Yet the problem is that, vhost_vdpa_net_handle_ctrl_avail() mistakenly frees the `elem`, even if it fails to forward the CVQ command to vdpa device. This can result in a use-after-free for the `elem` in vhost_handle_guest_kick(). This patch solves this problem by refactoring vhost_vdpa_net_handle_ctrl_avail() to only freeing the `elem` if it owns it. Fixes: bd907ae4b0 ("vdpa: manual forward CVQ buffers") Signed-off-by: Hawkins Jiawei <yin31149@gmail.com> Message-Id: <e3f2d7db477734afe5c6a5ab3fa8b8317514ea34.1688746840.git.yin31149@gmail.com> Reviewed-by: Eugenio PĂ©rez <eperezma@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> (cherry picked from commit 031b1abacbdb3f4e016b6b926f7e7876c05339bb) Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
-rw-r--r--net/vhost-vdpa.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
index 2086a92965..7c2c4fb7ea 100644
--- a/net/vhost-vdpa.c
+++ b/net/vhost-vdpa.c
@@ -790,7 +790,16 @@ out:
error_report("Bad device CVQ written length");
}
vhost_svq_push_elem(svq, elem, MIN(in_len, sizeof(status)));
- g_free(elem);
+ /*
+ * `elem` belongs to vhost_vdpa_net_handle_ctrl_avail() only when
+ * the function successfully forwards the CVQ command, indicated
+ * by a non-negative value of `dev_written`. Otherwise, it still
+ * belongs to SVQ.
+ * This function should only free the `elem` when it owns.
+ */
+ if (dev_written >= 0) {
+ g_free(elem);
+ }
return dev_written < 0 ? dev_written : 0;
}