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 bc1fdbe465)
			
			
This commit is contained in:
		
							parent
							
								
									6236342157
								
							
						
					
					
						commit
						7b5694368b
					
				| 
						 | 
				
			
			@ -447,14 +447,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);
 | 
			
		||||
| 
						 | 
				
			
			@ -505,6 +511,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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue