Blame SOURCES/0006-Xi-do-not-keep-linked-list-pointer-during-recursion.patch

f4a46c
From bc1fdbe46559dd947674375946bbef54dd0ce36b Mon Sep 17 00:00:00 2001
f4a46c
From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= <jexposit@redhat.com>
f4a46c
Date: Fri, 22 Dec 2023 18:28:31 +0100
f4a46c
Subject: [PATCH 6/9] Xi: do not keep linked list pointer during recursion
f4a46c
f4a46c
The `DisableDevice()` function is called whenever an enabled device
f4a46c
is disabled and it moves the device from the `inputInfo.devices` linked
f4a46c
list to the `inputInfo.off_devices` linked list.
f4a46c
f4a46c
However, its link/unlink operation has an issue during the recursive
f4a46c
call to `DisableDevice()` due to the `prev` pointer pointing to a
f4a46c
removed device.
f4a46c
f4a46c
This issue leads to a length mismatch between the total number of
f4a46c
devices and the number of device in the list, leading to a heap
f4a46c
overflow and, possibly, to local privilege escalation.
f4a46c
f4a46c
Simplify the code that checked whether the device passed to
f4a46c
`DisableDevice()` was in `inputInfo.devices` or not and find the
f4a46c
previous device after the recursion.
f4a46c
f4a46c
CVE-2024-21886, ZDI-CAN-22840
f4a46c
f4a46c
This vulnerability was discovered by:
f4a46c
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
f4a46c
---
f4a46c
 dix/devices.c | 15 ++++++++++++---
f4a46c
 1 file changed, 12 insertions(+), 3 deletions(-)
f4a46c
f4a46c
diff --git a/dix/devices.c b/dix/devices.c
f4a46c
index dca98c8d1..389d28a23 100644
f4a46c
--- a/dix/devices.c
f4a46c
+++ b/dix/devices.c
f4a46c
@@ -453,14 +453,20 @@ DisableDevice(DeviceIntPtr dev, BOOL sendevent)
f4a46c
 {
f4a46c
     DeviceIntPtr *prev, other;
f4a46c
     BOOL enabled;
f4a46c
+    BOOL dev_in_devices_list = FALSE;
f4a46c
     int flags[MAXDEVICES] = { 0 };
f4a46c
 
f4a46c
     if (!dev->enabled)
f4a46c
         return TRUE;
f4a46c
 
f4a46c
-    for (prev = &inputInfo.devices;
f4a46c
-         *prev && (*prev != dev); prev = &(*prev)->next);
f4a46c
-    if (*prev != dev)
f4a46c
+    for (other = inputInfo.devices; other; other = other->next) {
f4a46c
+        if (other == dev) {
f4a46c
+            dev_in_devices_list = TRUE;
f4a46c
+            break;
f4a46c
+        }
f4a46c
+    }
f4a46c
+
f4a46c
+    if (!dev_in_devices_list)
f4a46c
         return FALSE;
f4a46c
 
f4a46c
     TouchEndPhysicallyActiveTouches(dev);
f4a46c
@@ -511,6 +517,9 @@ DisableDevice(DeviceIntPtr dev, BOOL sendevent)
f4a46c
     LeaveWindow(dev);
f4a46c
     SetFocusOut(dev);
f4a46c
 
f4a46c
+    for (prev = &inputInfo.devices;
f4a46c
+         *prev && (*prev != dev); prev = &(*prev)->next);
f4a46c
+
f4a46c
     *prev = dev->next;
f4a46c
     dev->next = inputInfo.off_devices;
f4a46c
     inputInfo.off_devices = dev;
f4a46c
-- 
f4a46c
2.43.0
f4a46c