You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
71 lines
2.2 KiB
71 lines
2.2 KiB
11 months ago
|
From 4e0e99ef60f07757756913221847a26c71afc3e8 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] 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
|
||
|
---
|
||
|
dix/devices.c | 15 ++++++++++++---
|
||
|
1 file changed, 12 insertions(+), 3 deletions(-)
|
||
|
|
||
|
diff --git a/dix/devices.c b/dix/devices.c
|
||
|
index 3f3224d62..3a64d8702 100644
|
||
|
--- a/dix/devices.c
|
||
|
+++ b/dix/devices.c
|
||
|
@@ -451,14 +451,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);
|
||
|
@@ -509,6 +515,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
|
||
|
|