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

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