Blame SOURCES/0005-Xi-flush-hierarchy-events-after-adding-removing-mast.patch

f4a46c
From 4a5e9b1895627d40d26045bd0b7ef3dce503cbd1 Mon Sep 17 00:00:00 2001
f4a46c
From: Peter Hutterer <peter.hutterer@who-t.net>
f4a46c
Date: Thu, 4 Jan 2024 10:01:24 +1000
f4a46c
Subject: [PATCH 5/9] Xi: flush hierarchy events after adding/removing master
f4a46c
 devices
f4a46c
f4a46c
The `XISendDeviceHierarchyEvent()` function allocates space to store up
f4a46c
to `MAXDEVICES` (256) `xXIHierarchyInfo` structures in `info`.
f4a46c
f4a46c
If a device with a given ID was removed and a new device with the same
f4a46c
ID added both in the same operation, the single device ID will lead to
f4a46c
two info structures being written to `info`.
f4a46c
f4a46c
Since this case can occur for every device ID at once, a total of two
f4a46c
times `MAXDEVICES` info structures might be written to the allocation.
f4a46c
f4a46c
To avoid it, once one add/remove master is processed, send out the
f4a46c
device hierarchy event for the current state and continue. That event
f4a46c
thus only ever has exactly one of either added/removed in it (and
f4a46c
optionally slave attached/detached).
f4a46c
f4a46c
CVE-2024-21885, ZDI-CAN-22744
f4a46c
f4a46c
This vulnerability was discovered by:
f4a46c
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
f4a46c
---
f4a46c
 Xi/xichangehierarchy.c | 27 ++++++++++++++++++++++-----
f4a46c
 1 file changed, 22 insertions(+), 5 deletions(-)
f4a46c
f4a46c
diff --git a/Xi/xichangehierarchy.c b/Xi/xichangehierarchy.c
f4a46c
index d2d985848..72d00451e 100644
f4a46c
--- a/Xi/xichangehierarchy.c
f4a46c
+++ b/Xi/xichangehierarchy.c
f4a46c
@@ -416,6 +416,11 @@ ProcXIChangeHierarchy(ClientPtr client)
f4a46c
     size_t len;			/* length of data remaining in request */
f4a46c
     int rc = Success;
f4a46c
     int flags[MAXDEVICES] = { 0 };
f4a46c
+    enum {
f4a46c
+        NO_CHANGE,
f4a46c
+        FLUSH,
f4a46c
+        CHANGED,
f4a46c
+    } changes = NO_CHANGE;
f4a46c
 
f4a46c
     REQUEST(xXIChangeHierarchyReq);
f4a46c
     REQUEST_AT_LEAST_SIZE(xXIChangeHierarchyReq);
f4a46c
@@ -465,8 +470,9 @@ ProcXIChangeHierarchy(ClientPtr client)
f4a46c
             rc = add_master(client, c, flags);
f4a46c
             if (rc != Success)
f4a46c
                 goto unwind;
f4a46c
-        }
f4a46c
+            changes = FLUSH;
f4a46c
             break;
f4a46c
+        }
f4a46c
         case XIRemoveMaster:
f4a46c
         {
f4a46c
             xXIRemoveMasterInfo *r = (xXIRemoveMasterInfo *) any;
f4a46c
@@ -475,8 +481,9 @@ ProcXIChangeHierarchy(ClientPtr client)
f4a46c
             rc = remove_master(client, r, flags);
f4a46c
             if (rc != Success)
f4a46c
                 goto unwind;
f4a46c
-        }
f4a46c
+            changes = FLUSH;
f4a46c
             break;
f4a46c
+        }
f4a46c
         case XIDetachSlave:
f4a46c
         {
f4a46c
             xXIDetachSlaveInfo *c = (xXIDetachSlaveInfo *) any;
f4a46c
@@ -485,8 +492,9 @@ ProcXIChangeHierarchy(ClientPtr client)
f4a46c
             rc = detach_slave(client, c, flags);
f4a46c
             if (rc != Success)
f4a46c
                 goto unwind;
f4a46c
-        }
f4a46c
+            changes = CHANGED;
f4a46c
             break;
f4a46c
+        }
f4a46c
         case XIAttachSlave:
f4a46c
         {
f4a46c
             xXIAttachSlaveInfo *c = (xXIAttachSlaveInfo *) any;
f4a46c
@@ -495,16 +503,25 @@ ProcXIChangeHierarchy(ClientPtr client)
f4a46c
             rc = attach_slave(client, c, flags);
f4a46c
             if (rc != Success)
f4a46c
                 goto unwind;
f4a46c
+            changes = CHANGED;
f4a46c
+            break;
f4a46c
         }
f4a46c
+        default:
f4a46c
             break;
f4a46c
         }
f4a46c
 
f4a46c
+        if (changes == FLUSH) {
f4a46c
+            XISendDeviceHierarchyEvent(flags);
f4a46c
+            memset(flags, 0, sizeof(flags));
f4a46c
+            changes = NO_CHANGE;
f4a46c
+        }
f4a46c
+
f4a46c
         len -= any->length * 4;
f4a46c
         any = (xXIAnyHierarchyChangeInfo *) ((char *) any + any->length * 4);
f4a46c
     }
f4a46c
 
f4a46c
  unwind:
f4a46c
-
f4a46c
-    XISendDeviceHierarchyEvent(flags);
f4a46c
+    if (changes != NO_CHANGE)
f4a46c
+        XISendDeviceHierarchyEvent(flags);
f4a46c
     return rc;
f4a46c
 }
f4a46c
-- 
f4a46c
2.43.0
f4a46c