xkb: Add bounds check for action data in CheckKeyActions()

CheckKeyActions() validates the per-key action count bytes individually
but does not verify that the computed total action data region falls
within the request buffer before advancing the wire pointer past it.

After the loop, the function calculates the final wire position as
wire + nActs * sizeof(XkbAnyAction), where nActs is the sum of per-key
action counts read from the request. The upstream length validation in
_XkbSetMapCheckLength() uses req->totalActs from the request header,
not the computed nActs. If a crafted request provides a totalActs value
that passes the length check but per-key action counts that sum to a
different nActs, the wire pointer could advance past the actual request
buffer.

The subsequent SetKeyActions() function uses memcpy to read from this
potentially out-of-bounds region, which could leak heap data or cause
a crash.

Assisted-by: Claude:claude-claude-opus-4-6
(cherry picked from commit a439a7340a)

Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2224>
This commit is contained in:
Peter Hutterer 2026-04-18 07:38:14 +10:00 committed by Alan Coopersmith
parent 5f2ac0de47
commit 852bf24683

View file

@ -1858,6 +1858,11 @@ CheckKeyActions(ClientPtr client,
if (req->nKeyActs % 4)
wire += 4 - (req->nKeyActs % 4);
*wireRtrn = (CARD8 *) (((XkbAnyAction *) wire) + nActs);
if (nActs > 0 &&
!_XkbCheckRequestBounds(client, req, wire, *wireRtrn)) {
*nActsRtrn = _XkbErrCode2(0x25, nActs);
return 0;
}
*nActsRtrn = nActs;
return 1;
}