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

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