From 3d89d972bebf992cbd087fca12910f4f3a24b84e Mon Sep 17 00:00:00 2001 From: Matthieu Herrb Date: Tue, 16 Jan 2024 12:34:24 +0000 Subject: Multiple issues have been found in the X server and Xwayland implementations: 1) CVE-2023-6816 can be triggered by passing an invalid array index to DeviceFocusEvent or ProcXIQueryPointer. 2) CVE-2024-0229 can be triggered if a device has both a button and a key class and zero buttons. 3) CVE-2024-21885 can be triggered if a device with a given ID was removed and a new device with the same ID added both in the same operation. 4) CVE-2024-21886 can be triggered by disabling a master device with disabled slave devices. 5) CVE-2024-0409 can be triggered by enabling SELinux xserver_object_manager and running a client. 6) CVE-2024-0408 can be triggered by enabling SELinux xserver_object_manager and creating a GLX PBuffer. --- xserver/Xi/exevents.c | 1 + xserver/Xi/xichangehierarchy.c | 31 ++++++++++++++++++++++++------- xserver/Xi/xiquerypointer.c | 3 +-- 3 files changed, 26 insertions(+), 9 deletions(-) (limited to 'xserver/Xi') diff --git a/xserver/Xi/exevents.c b/xserver/Xi/exevents.c index 54ea11a93..e16171468 100644 --- a/xserver/Xi/exevents.c +++ b/xserver/Xi/exevents.c @@ -605,6 +605,7 @@ DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to) to->button = calloc(1, sizeof(ButtonClassRec)); if (!to->button) FatalError("[Xi] no memory for class shift.\n"); + to->button->numButtons = from->button->numButtons; } else classes->button = NULL; diff --git a/xserver/Xi/xichangehierarchy.c b/xserver/Xi/xichangehierarchy.c index 504defe56..72d00451e 100644 --- a/xserver/Xi/xichangehierarchy.c +++ b/xserver/Xi/xichangehierarchy.c @@ -270,7 +270,7 @@ remove_master(ClientPtr client, xXIRemoveMasterInfo * r, int flags[MAXDEVICES]) if (rc != Success) goto unwind; - if (!IsMaster(newptr)) { + if (!IsMaster(newptr) || !IsPointerDevice(newptr)) { client->errorValue = r->return_pointer; rc = BadDevice; goto unwind; @@ -281,7 +281,7 @@ remove_master(ClientPtr client, xXIRemoveMasterInfo * r, int flags[MAXDEVICES]) if (rc != Success) goto unwind; - if (!IsMaster(newkeybd)) { + if (!IsMaster(newkeybd) || !IsKeyboardDevice(newkeybd)) { client->errorValue = r->return_keyboard; rc = BadDevice; goto unwind; @@ -416,6 +416,11 @@ ProcXIChangeHierarchy(ClientPtr client) size_t len; /* length of data remaining in request */ int rc = Success; int flags[MAXDEVICES] = { 0 }; + enum { + NO_CHANGE, + FLUSH, + CHANGED, + } changes = NO_CHANGE; REQUEST(xXIChangeHierarchyReq); REQUEST_AT_LEAST_SIZE(xXIChangeHierarchyReq); @@ -465,8 +470,9 @@ ProcXIChangeHierarchy(ClientPtr client) rc = add_master(client, c, flags); if (rc != Success) goto unwind; - } + changes = FLUSH; break; + } case XIRemoveMaster: { xXIRemoveMasterInfo *r = (xXIRemoveMasterInfo *) any; @@ -475,8 +481,9 @@ ProcXIChangeHierarchy(ClientPtr client) rc = remove_master(client, r, flags); if (rc != Success) goto unwind; - } + changes = FLUSH; break; + } case XIDetachSlave: { xXIDetachSlaveInfo *c = (xXIDetachSlaveInfo *) any; @@ -485,8 +492,9 @@ ProcXIChangeHierarchy(ClientPtr client) rc = detach_slave(client, c, flags); if (rc != Success) goto unwind; - } + changes = CHANGED; break; + } case XIAttachSlave: { xXIAttachSlaveInfo *c = (xXIAttachSlaveInfo *) any; @@ -495,16 +503,25 @@ ProcXIChangeHierarchy(ClientPtr client) rc = attach_slave(client, c, flags); if (rc != Success) goto unwind; + changes = CHANGED; + break; } + default: break; } + if (changes == FLUSH) { + XISendDeviceHierarchyEvent(flags); + memset(flags, 0, sizeof(flags)); + changes = NO_CHANGE; + } + len -= any->length * 4; any = (xXIAnyHierarchyChangeInfo *) ((char *) any + any->length * 4); } unwind: - - XISendDeviceHierarchyEvent(flags); + if (changes != NO_CHANGE) + XISendDeviceHierarchyEvent(flags); return rc; } diff --git a/xserver/Xi/xiquerypointer.c b/xserver/Xi/xiquerypointer.c index 5b77b1a44..2b05ac5f3 100644 --- a/xserver/Xi/xiquerypointer.c +++ b/xserver/Xi/xiquerypointer.c @@ -149,8 +149,7 @@ ProcXIQueryPointer(ClientPtr client) if (pDev->button) { int i; - rep.buttons_len = - bytes_to_int32(bits_to_bytes(pDev->button->numButtons)); + rep.buttons_len = bytes_to_int32(bits_to_bytes(256)); /* button map up to 255 */ rep.length += rep.buttons_len; buttons = calloc(rep.buttons_len, 4); if (!buttons) -- cgit v1.2.3