74 lines
2.3 KiB
Diff
74 lines
2.3 KiB
Diff
|
From 01cd3a72858ccc1afb0b42ace92263f2912619a3 Mon Sep 17 00:00:00 2001
|
||
|
From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= <jexposit@redhat.com>
|
||
|
Date: Fri, 22 Dec 2023 18:28:31 +0100
|
||
|
Subject: [PATCH xserver 6/9] 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
|
||
|
|
||
|
(cherry picked from commit bc1fdbe46559dd947674375946bbef54dd0ce36b)
|
||
|
---
|
||
|
dix/devices.c | 15 ++++++++++++---
|
||
|
1 file changed, 12 insertions(+), 3 deletions(-)
|
||
|
|
||
|
diff --git a/dix/devices.c b/dix/devices.c
|
||
|
index 8fe4a341c..f3db37203 100644
|
||
|
--- a/dix/devices.c
|
||
|
+++ b/dix/devices.c
|
||
|
@@ -453,14 +453,20 @@ DisableDevice(DeviceIntPtr dev, BOOL sendevent)
|
||
|
{
|
||
|
DeviceIntPtr *prev, other;
|
||
|
BOOL enabled;
|
||
|
+ BOOL dev_in_devices_list = FALSE;
|
||
|
int flags[MAXDEVICES] = { 0 };
|
||
|
|
||
|
if (!dev->enabled)
|
||
|
return TRUE;
|
||
|
|
||
|
- 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;
|
||
|
|
||
|
TouchEndPhysicallyActiveTouches(dev);
|
||
|
@@ -511,6 +517,9 @@ DisableDevice(DeviceIntPtr dev, BOOL sendevent)
|
||
|
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;
|
||
|
--
|
||
|
2.43.0
|
||
|
|