Fedora Account System
Red Hat Associate
Red Hat Customer
AI_ONLY_REPORT package: libXi-1.8.2-4.1.hum1 ------ Summary: OOB read in XI2 enter/leave/focus cookie conversion (`wireToEnterLeave`): malformed XI2 enter/leave/focus GenericEvents can cause a client-side out-of-bounds read when `buttons_len` exceeds the actual payload length. Requirements to exploit: An attacker must control or compromise the X server or X11 transport endpoint used by a libXi-linked client, and the client must process XI2 `XI_Enter`, `XI_Leave`, `XI_FocusIn`, or `XI_FocusOut` events through the cookie conversion path. Component affected: `libXi-1.8.2-4.1.hum1`, `src/XExtInt.c`, `XInputWireToCookie()` and `wireToEnterLeave()` Version affected: `libXi-1.8.2-4.1.hum1`, when used by a client that accepts XI2 enter/leave/focus GenericEvents from a malicious or compromised X server Patch available: no released package fix established; proposed patch included below Version fixed: unknown Upstream coordination: Not notified. CVSS: CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:H - 6.1 (MEDIUM) AV:L - The attacker must control the X server endpoint the client is already connected to, rather than reach a network service exposed by the package itself. AC:L - Crafting a GenericEvent with a short payload and oversized `buttons_len` is straightforward once the attacker controls that event stream. PR:N - No privileges are required on the victim host beyond providing the malicious X server data. UI:R - A user must run an affected client and connect it to the malicious or compromised X server. S:U - The effect is confined to the client process that parses the event. C:L - Adjacent in-process bytes may be copied past the received event buffer, creating limited disclosure potential, although disclosure was not directly demonstrated. I:N - The issue does not provide a write primitive or direct data modification capability. A:H - The malformed event can crash the client or otherwise disrupt event processing. Impact: Moderate. This issue can cause client-side denial of service and may allow limited disclosure of adjacent in-process data, but exploitation depends on a malicious or compromised X server and a client taking the affected XI2 cookie conversion path. That makes it harder to exploit than Red Hat's Important or Critical categories, while still representing more than minimal security impact when reachable. Embargo: no Reason: This is a client-side parsing issue with a constrained threat model, no demonstrated code execution, and straightforward operational mitigation by avoiding untrusted X servers until a fix is available. Acknowledgement: Aisle Research Vulnerability Details: In `src/XExtInt.c`, `XInputWireToCookie()` routes `XI_Enter`, `XI_Leave`, `XI_FocusIn`, and `XI_FocusOut` to `wireToEnterLeave()` without passing validated wire-event size context. `wireToEnterLeave()` then trusts the wire-supplied `buttons_len` field when sizing the destination buffer and copying button-mask bytes: ```c static int wireToEnterLeave(xXIEnterEvent *in, XGenericEventCookie *cookie) { int len; XIEnterEvent *out; len = sizeof(XIEnterEvent) + in->buttons_len * 4; ... out->buttons.mask_len = in->buttons_len * 4; memcpy(out->buttons.mask, &in[1], out->buttons.mask_len); return 1; } ``` There is no validation on this path that `buttons_len * 4` fits within the received GenericEvent payload before the `memcpy()` occurs. A malformed `XI_Enter`, `XI_Leave`, `XI_FocusIn`, or `XI_FocusOut` event can therefore drive a client-side out-of-bounds read. The directly supported impact is application crash or event-processing failure; limited in-process memory disclosure is also plausible because bytes beyond the received event buffer may be copied into cookie data. Steps to reproduce: 1. Build `libXi-1.8.2-4.1.hum1` and a minimal XI2 client with AddressSanitizer enabled that selects XI2 events and processes them via `XNextEvent()` and the cookie path. 2. Run the client with `DISPLAY` pointing to a controlled X server or protocol fuzzer that can emit crafted XI2 `GenericEvent` messages. 3. Emit an `XI_Enter` event (the same applies to `XI_Leave`, `XI_FocusIn`, and `XI_FocusOut`) with a small `ge.length` so the trailing payload is short, but with `buttons_len` set so `buttons_len * 4` exceeds the available payload bytes. 4. Observe an AddressSanitizer invalid read at `memcpy(out->buttons.mask, &in[1], out->buttons.mask_len)` in `wireToEnterLeave()` or an equivalent client crash. Mitigation: Until this is fixed, avoid connecting libXi-linked XI2 clients to untrusted or compromised X servers. Where operationally possible, restrict applications to trusted local display servers and avoid exposing attacker-controlled X11 event streams to the affected cookie conversion path. Proposed Fix: Pass the actual received event size into `wireToEnterLeave()`, validate the derived button-mask length against that size, and reject malformed events before allocation and copy. ```diff diff --git a/libXi-1.8.2/src/XExtInt.c b/libXi-1.8.2/src/XExtInt.c index 0000000..0000000 100644 — a/libXi-1.8.2/src/XExtInt.c +++ b/libXi-1.8.2/src/XExtInt.c @@ -55,6 +55,7 @@ #include <config.h> #endif +#include <limits.h> #include <stdio.h> #include <stdint.h> #include <X11/extensions/XI.h> @@ -118,7 +119,8 @@ wireToHierarchyChangedEvent(xXIHierarchyEvent *in, XGenericEventCookie *cookie) static int wireToRawEvent(XExtDisplayInfo *info, xXIRawEvent *in, XGenericEventCookie *cookie); static int -wireToEnterLeave(xXIEnterEvent *in, XGenericEventCookie *cookie); +wireToEnterLeave(xXIEnterEvent *in, size_t event_bytes, + XGenericEventCookie *cookie); static int wireToPropertyEvent(xXIPropertyEvent *in, XGenericEventCookie *cookie); @@ -1017,7 +1019,9 @@ XInputWireToCookie( case XI_FocusIn: case XI_FocusOut: *cookie = (XGenericEventCookie)save; if (!wireToEnterLeave((xXIEnterEvent*)event, cookie)) + if (!wireToEnterLeave((xXIEnterEvent*)event, + sizeof(xEvent) + ((size_t)ge->length * 4), + cookie)) { printf("XInputWireToCookie: CONVERSION FAILURE! evtype=%d\n", ge->evtype); @@ -2014,12 +2018,23 @@ wireToRawEvent(XExtDisplayInfo *info, xXIRawEvent *in, XGenericEventCookie *coo [event][modifiers][group][button] */ static int -wireToEnterLeave(xXIEnterEvent *in, XGenericEventCookie *cookie) +wireToEnterLeave(xXIEnterEvent *in, size_t event_bytes, + XGenericEventCookie *cookie) { int len; + size_t mask_len, len; XIEnterEvent *out; len = sizeof(XIEnterEvent) + in->buttons_len * 4; + mask_len = (size_t)in->buttons_len * 4u; + + if (mask_len > (size_t)INT_MAX) + return 0; + if (event_bytes < sizeof(*in) || mask_len > event_bytes - sizeof(*in)) + return 0; + if (mask_len > SIZE_MAX - sizeof(XIEnterEvent)) + return 0; + + len = sizeof(XIEnterEvent) + mask_len; cookie->data = out = malloc(len); if (!out) @@ -2057,8 +2072,8 @@ wireToEnterLeave(xXIEnterEvent *in, XGenericEventCookie *cookie) out->group.latched = in->group.latched_group; out->group.effective = in->group.effective_group; out->buttons.mask_len = in->buttons_len * 4; memcpy(out->buttons.mask, &in[1], out->buttons.mask_len); + out->buttons.mask_len = (int)mask_len; + memcpy(out->buttons.mask, &in[1], mask_len); return 1; } ``` ------ This report was generated using AI technology. Always review AI-generated content prior to use