Module Name:    xsrc
Committed By:   mrg
Date:           Sun Nov  3 00:28:24 UTC 2024

Modified Files:
        xsrc/external/mit/xorg-server.old/dist/dix: devices.c

Log Message:
merge upstream change bc1fdbe46559dd947674375946bbef54dd0ce36b

Subject: [PATCH] Xi: do not keep linked list pointer during recursion

The `DisableDevice()` function is called whenever an enabled device
is disabled and it moves the device from the `inputInfo.devices` linked
list to the `inputInfo.off_devices` linked list.

However, its link/unlink operation has an issue during the recursive
call to `DisableDevice()` due to the `prev` pointer pointing to a
removed device.

This issue leads to a length mismatch between the total number of
devices and the number of device in the list, leading to a heap
overflow and, possibly, to local privilege escalation.

Simplify the code that checked whether the device passed to
`DisableDevice()` was in `inputInfo.devices` or not and find the
previous device after the recursion.

CVE-2024-21886, ZDI-CAN-22840

This vulnerability was discovered by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative


To generate a diff of this commit:
cvs rdiff -u -r1.1.1.1 -r1.2 \
    xsrc/external/mit/xorg-server.old/dist/dix/devices.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: xsrc/external/mit/xorg-server.old/dist/dix/devices.c
diff -u xsrc/external/mit/xorg-server.old/dist/dix/devices.c:1.1.1.1 xsrc/external/mit/xorg-server.old/dist/dix/devices.c:1.2
--- xsrc/external/mit/xorg-server.old/dist/dix/devices.c:1.1.1.1	Thu Jun  9 09:07:56 2016
+++ xsrc/external/mit/xorg-server.old/dist/dix/devices.c	Sun Nov  3 00:28:24 2024
@@ -432,13 +432,17 @@ DisableDevice(DeviceIntPtr dev, BOOL sen
 {
     DeviceIntPtr *prev, other;
     BOOL enabled;
+    BOOL dev_in_devices_list = FALSE;
     int flags[MAXDEVICES] = {0};
 
-    for (prev = &inputInfo.devices;
-	 *prev && (*prev != dev);
-	 prev = &(*prev)->next)
-	;
-    if (*prev != dev)
+    for (other = inputInfo.devices; other; other = other->next) {
+        if (other == dev) {
+            dev_in_devices_list = TRUE;
+            break;
+        }
+    }
+
+    if (!dev_in_devices_list)
 	return FALSE;
 
     /* float attached devices */
@@ -491,6 +495,9 @@ DisableDevice(DeviceIntPtr dev, BOOL sen
     LeaveWindow(dev);
     SetFocusOut(dev);
 
+    for (prev = &inputInfo.devices;
+         *prev && (*prev != dev); prev = &(*prev)->next);
+
     *prev = dev->next;
     dev->next = inputInfo.off_devices;
     inputInfo.off_devices = dev;

Reply via email to