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
This commit is contained in:
parent
4a5e9b1895
commit
bc1fdbe465
|
@ -453,14 +453,20 @@ DisableDevice(DeviceIntPtr dev, BOOL sendevent)
|
||||||
{
|
{
|
||||||
DeviceIntPtr *prev, other;
|
DeviceIntPtr *prev, other;
|
||||||
BOOL enabled;
|
BOOL enabled;
|
||||||
|
BOOL dev_in_devices_list = FALSE;
|
||||||
int flags[MAXDEVICES] = { 0 };
|
int flags[MAXDEVICES] = { 0 };
|
||||||
|
|
||||||
if (!dev->enabled)
|
if (!dev->enabled)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
for (prev = &inputInfo.devices;
|
for (other = inputInfo.devices; other; other = other->next) {
|
||||||
*prev && (*prev != dev); prev = &(*prev)->next);
|
if (other == dev) {
|
||||||
if (*prev != dev)
|
dev_in_devices_list = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dev_in_devices_list)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
TouchEndPhysicallyActiveTouches(dev);
|
TouchEndPhysicallyActiveTouches(dev);
|
||||||
|
@ -511,6 +517,9 @@ DisableDevice(DeviceIntPtr dev, BOOL sendevent)
|
||||||
LeaveWindow(dev);
|
LeaveWindow(dev);
|
||||||
SetFocusOut(dev);
|
SetFocusOut(dev);
|
||||||
|
|
||||||
|
for (prev = &inputInfo.devices;
|
||||||
|
*prev && (*prev != dev); prev = &(*prev)->next);
|
||||||
|
|
||||||
*prev = dev->next;
|
*prev = dev->next;
|
||||||
dev->next = inputInfo.off_devices;
|
dev->next = inputInfo.off_devices;
|
||||||
inputInfo.off_devices = dev;
|
inputInfo.off_devices = dev;
|
||||||
|
|
Loading…
Reference in New Issue