dix: when disabling a master, float disabled slaved devices too

Disabling a master device floats all slave devices but we didn't do this
to already-disabled slave devices. As a result those devices kept their
reference to the master device resulting in access to already freed
memory if the master device was removed before the corresponding slave
device.

And to match this behavior, also forcibly reset that pointer during
CloseDownDevices().

Related to CVE-2024-21886, ZDI-CAN-22840
This commit is contained in:
Peter Hutterer 2024-01-05 09:40:27 +10:00 committed by José Expósito
parent bc1fdbe465
commit 26769aa71f

View File

@ -483,6 +483,13 @@ DisableDevice(DeviceIntPtr dev, BOOL sendevent)
flags[other->id] |= XISlaveDetached; flags[other->id] |= XISlaveDetached;
} }
} }
for (other = inputInfo.off_devices; other; other = other->next) {
if (!IsMaster(other) && GetMaster(other, MASTER_ATTACHED) == dev) {
AttachDevice(NULL, other, NULL);
flags[other->id] |= XISlaveDetached;
}
}
} }
else { else {
for (other = inputInfo.devices; other; other = other->next) { for (other = inputInfo.devices; other; other = other->next) {
@ -1088,6 +1095,11 @@ CloseDownDevices(void)
dev->master = NULL; dev->master = NULL;
} }
for (dev = inputInfo.off_devices; dev; dev = dev->next) {
if (!IsMaster(dev) && !IsFloating(dev))
dev->master = NULL;
}
CloseDeviceList(&inputInfo.devices); CloseDeviceList(&inputInfo.devices);
CloseDeviceList(&inputInfo.off_devices); CloseDeviceList(&inputInfo.off_devices);