1From 405484b29f6548c7b86549b0f961b906337aa68a Mon Sep 17 00:00:00 2001 2From: Fiona Ebner <f.ebner@proxmox.com> 3Date: Wed, 24 Jan 2024 11:57:48 +0100 4Subject: [PATCH] ui/clipboard: mark type as not available when there is no 5 data 6MIME-Version: 1.0 7Content-Type: text/plain; charset=UTF-8 8Content-Transfer-Encoding: 8bit 9 10With VNC, a client can send a non-extended VNC_MSG_CLIENT_CUT_TEXT 11message with len=0. In qemu_clipboard_set_data(), the clipboard info 12will be updated setting data to NULL (because g_memdup(data, size) 13returns NULL when size is 0). If the client does not set the 14VNC_ENCODING_CLIPBOARD_EXT feature when setting up the encodings, then 15the 'request' callback for the clipboard peer is not initialized. 16Later, because data is NULL, qemu_clipboard_request() can be reached 17via vdagent_chr_write() and vdagent_clipboard_recv_request() and 18there, the clipboard owner's 'request' callback will be attempted to 19be called, but that is a NULL pointer. 20 21In particular, this can happen when using the KRDC (22.12.3) VNC 22client. 23 24Another scenario leading to the same issue is with two clients (say 25noVNC and KRDC): 26 27The noVNC client sets the extension VNC_FEATURE_CLIPBOARD_EXT and 28initializes its cbpeer. 29 30The KRDC client does not, but triggers a vnc_client_cut_text() (note 31it's not the _ext variant)). There, a new clipboard info with it as 32the 'owner' is created and via qemu_clipboard_set_data() is called, 33which in turn calls qemu_clipboard_update() with that info. 34 35In qemu_clipboard_update(), the notifier for the noVNC client will be 36called, i.e. vnc_clipboard_notify() and also set vs->cbinfo for the 37noVNC client. The 'owner' in that clipboard info is the clipboard peer 38for the KRDC client, which did not initialize the 'request' function. 39That sounds correct to me, it is the owner of that clipboard info. 40 41Then when noVNC sends a VNC_MSG_CLIENT_CUT_TEXT message (it did set 42the VNC_FEATURE_CLIPBOARD_EXT feature correctly, so a check for it 43passes), that clipboard info is passed to qemu_clipboard_request() and 44the original segfault still happens. 45 46Fix the issue by handling updates with size 0 differently. In 47particular, mark in the clipboard info that the type is not available. 48 49While at it, switch to g_memdup2(), because g_memdup() is deprecated. 50 51Cc: qemu-stable@nongnu.org 52Fixes: CVE-2023-6683 53Reported-by: Markus Frank <m.frank@proxmox.com> 54Suggested-by: Marc-André Lureau <marcandre.lureau@redhat.com> 55Signed-off-by: Fiona Ebner <f.ebner@proxmox.com> 56Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> 57Tested-by: Markus Frank <m.frank@proxmox.com> 58Message-ID: <20240124105749.204610-1-f.ebner@proxmox.com> 59 60CVE: CVE-2023-6683 61 62Upstream-Status: Backport [https://github.com/qemu/qemu/commit/405484b29f6548c7b86549b0f961b906337aa68a] 63Signed-off-by: Simone Weiß <simone.p.weiss@posteo.com> 64 65--- 66 ui/clipboard.c | 12 +++++++++--- 67 1 file changed, 9 insertions(+), 3 deletions(-) 68 69diff --git a/ui/clipboard.c b/ui/clipboard.c 70index 3d14bffaf80f..b3f6fa3c9e1f 100644 71--- a/ui/clipboard.c 72+++ b/ui/clipboard.c 73@@ -163,9 +163,15 @@ void qemu_clipboard_set_data(QemuClipboardPeer *peer, 74 } 75 76 g_free(info->types[type].data); 77- info->types[type].data = g_memdup(data, size); 78- info->types[type].size = size; 79- info->types[type].available = true; 80+ if (size) { 81+ info->types[type].data = g_memdup2(data, size); 82+ info->types[type].size = size; 83+ info->types[type].available = true; 84+ } else { 85+ info->types[type].data = NULL; 86+ info->types[type].size = 0; 87+ info->types[type].available = false; 88+ } 89 90 if (update) { 91 qemu_clipboard_update(info); 92