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