Blame SOURCES/0006-Xext-free-the-XvRTVideoNotify-when-turning-off-from-.patch

290b8e
From a42635ee3c01f71a49052d83a372933504c9db04 Mon Sep 17 00:00:00 2001
290b8e
From: Peter Hutterer <peter.hutterer@who-t.net>
290b8e
Date: Wed, 30 Nov 2022 11:20:40 +1000
290b8e
Subject: [PATCH xserver 6/7] Xext: free the XvRTVideoNotify when turning off
290b8e
 from the same client
290b8e
290b8e
This fixes a use-after-free bug:
290b8e
290b8e
When a client first calls XvdiSelectVideoNotify() on a drawable with a
290b8e
TRUE onoff argument, a struct XvVideoNotifyRec is allocated. This struct
290b8e
is added twice to the resources:
290b8e
  - as the drawable's XvRTVideoNotifyList. This happens only once per
290b8e
    drawable, subsequent calls append to this list.
290b8e
  - as the client's XvRTVideoNotify. This happens for every client.
290b8e
290b8e
The struct keeps the ClientPtr around once it has been added for a
290b8e
client. The idea, presumably, is that if the client disconnects we can remove
290b8e
all structs from the drawable's list that match the client (by resetting
290b8e
the ClientPtr to NULL), but if the drawable is destroyed we can remove
290b8e
and free the whole list.
290b8e
290b8e
However, if the same client then calls XvdiSelectVideoNotify() on the
290b8e
same drawable with a FALSE onoff argument, only the ClientPtr on the
290b8e
existing struct was set to NULL. The struct itself remained in the
290b8e
client's resources.
290b8e
290b8e
If the drawable is now destroyed, the resource system invokes
290b8e
XvdiDestroyVideoNotifyList which frees the whole list for this drawable
290b8e
- including our struct. This function however does not free the resource
290b8e
for the client since our ClientPtr is NULL.
290b8e
290b8e
Later, when the client is destroyed and the resource system invokes
290b8e
XvdiDestroyVideoNotify, we unconditionally set the ClientPtr to NULL. On
290b8e
a struct that has been freed previously. This is generally frowned upon.
290b8e
290b8e
Fix this by calling FreeResource() on the second call instead of merely
290b8e
setting the ClientPtr to NULL. This removes the struct from the client
290b8e
resources (but not from the list), ensuring that it won't be accessed
290b8e
again when the client quits.
290b8e
290b8e
Note that the assignment tpn->client = NULL; is superfluous since the
290b8e
XvdiDestroyVideoNotify function will do this anyway. But it's left for
290b8e
clarity and to match a similar invocation in XvdiSelectPortNotify.
290b8e
290b8e
CVE-2022-46342, ZDI-CAN 19400
290b8e
290b8e
This vulnerability was discovered by:
290b8e
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
290b8e
290b8e
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
290b8e
Acked-by: Olivier Fourdan <ofourdan@redhat.com>
290b8e
---
290b8e
 Xext/xvmain.c | 4 +++-
290b8e
 1 file changed, 3 insertions(+), 1 deletion(-)
290b8e
290b8e
diff --git a/Xext/xvmain.c b/Xext/xvmain.c
290b8e
index f627471938..2a08f8744a 100644
290b8e
--- a/Xext/xvmain.c
290b8e
+++ b/Xext/xvmain.c
290b8e
@@ -811,8 +811,10 @@ XvdiSelectVideoNotify(ClientPtr client, DrawablePtr pDraw, BOOL onoff)
290b8e
         tpn = pn;
290b8e
         while (tpn) {
290b8e
             if (tpn->client == client) {
290b8e
-                if (!onoff)
290b8e
+                if (!onoff) {
290b8e
                     tpn->client = NULL;
290b8e
+                    FreeResource(tpn->id, XvRTVideoNotify);
290b8e
+                }
290b8e
                 return Success;
290b8e
             }
290b8e
             if (!tpn->client)
290b8e
--
290b8e
2.38.1