mirror of
https://gitlab.freedesktop.org/xorg/xserver.git
synced 2026-05-09 15:28:08 +02:00
xkb: Add more _XkbCheckRequestBounds()
Similar to the recent fixes, add more _XkbCheckRequestBounds() to the
functions that loop over the request data, i.e.:
* CheckKeySyms()
* CheckKeyActions()
* CheckKeyBehaviors()
* CheckVirtualMods()
* CheckKeyExplicit()
* CheckVirtualModMap()
* _XkbSetMapChecks()
All these are static functions so we can add the client to the parameters
without breaking any API.
See also:
CVE-2026-34003, ZDI-CAN-28736, CVE-2026-34002, ZDI-CAN-28737
v2: Check for "nSyms != 0" in CheckKeySyms() to avoid false positives.
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Acked-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit d38c563fab)
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2177>
This commit is contained in:
parent
38e8ae840c
commit
8f5e95beac
1 changed files with 55 additions and 14 deletions
69
xkb/xkb.c
69
xkb/xkb.c
|
|
@ -1751,6 +1751,11 @@ CheckKeySyms(ClientPtr client,
|
|||
KeySym *pSyms;
|
||||
register unsigned nG;
|
||||
|
||||
/* Check we received enough data to read the next xkbSymMapWireDesc */
|
||||
if (!_XkbCheckRequestBounds(client, req, wire, wire + 1)) {
|
||||
*errorRtrn = _XkbErrCode3(0x18, i + req->firstKeySym, i);
|
||||
return 0;
|
||||
}
|
||||
if (client->swapped && doswap) {
|
||||
swaps(&wire->nSyms);
|
||||
}
|
||||
|
|
@ -1789,6 +1794,12 @@ CheckKeySyms(ClientPtr client,
|
|||
return 0;
|
||||
}
|
||||
pSyms = (KeySym *) &wire[1];
|
||||
if (wire->nSyms != 0) {
|
||||
if (!_XkbCheckRequestBounds(client, req, pSyms, &pSyms[wire->nSyms])) {
|
||||
*errorRtrn = _XkbErrCode3(0x19, i + req->firstKeySym, wire->nSyms);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
wire = (xkbSymMapWireDesc *) &pSyms[wire->nSyms];
|
||||
}
|
||||
|
||||
|
|
@ -1812,11 +1823,12 @@ CheckKeySyms(ClientPtr client,
|
|||
}
|
||||
|
||||
static int
|
||||
CheckKeyActions(XkbDescPtr xkb,
|
||||
xkbSetMapReq * req,
|
||||
int nTypes,
|
||||
CARD8 *mapWidths,
|
||||
CARD16 *symsPerKey, CARD8 **wireRtrn, int *nActsRtrn)
|
||||
CheckKeyActions(ClientPtr client,
|
||||
XkbDescPtr xkb,
|
||||
xkbSetMapReq * req,
|
||||
int nTypes,
|
||||
CARD8 *mapWidths,
|
||||
CARD16 *symsPerKey, CARD8 **wireRtrn, int *nActsRtrn)
|
||||
{
|
||||
int nActs;
|
||||
CARD8 *wire = *wireRtrn;
|
||||
|
|
@ -1827,6 +1839,11 @@ CheckKeyActions(XkbDescPtr xkb,
|
|||
CHK_REQ_KEY_RANGE2(0x21, req->firstKeyAct, req->nKeyActs, req, (*nActsRtrn),
|
||||
0);
|
||||
for (nActs = i = 0; i < req->nKeyActs; i++) {
|
||||
/* Check we received enough data to read the next byte on the wire */
|
||||
if (!_XkbCheckRequestBounds(client, req, wire, wire + 1)) {
|
||||
*nActsRtrn = _XkbErrCode3(0x24, i + req->firstKeyAct, i);
|
||||
return 0;
|
||||
}
|
||||
if (wire[0] != 0) {
|
||||
if (wire[0] == symsPerKey[i + req->firstKeyAct])
|
||||
nActs += wire[0];
|
||||
|
|
@ -1845,7 +1862,8 @@ CheckKeyActions(XkbDescPtr xkb,
|
|||
}
|
||||
|
||||
static int
|
||||
CheckKeyBehaviors(XkbDescPtr xkb,
|
||||
CheckKeyBehaviors(ClientPtr client,
|
||||
XkbDescPtr xkb,
|
||||
xkbSetMapReq * req,
|
||||
xkbBehaviorWireDesc ** wireRtrn, int *errorRtrn)
|
||||
{
|
||||
|
|
@ -1871,6 +1889,11 @@ CheckKeyBehaviors(XkbDescPtr xkb,
|
|||
}
|
||||
|
||||
for (i = 0; i < req->totalKeyBehaviors; i++, wire++) {
|
||||
/* Check we received enough data to read the next behavior */
|
||||
if (!_XkbCheckRequestBounds(client, req, wire, wire + 1)) {
|
||||
*errorRtrn = _XkbErrCode3(0x36, first, i);
|
||||
return 0;
|
||||
}
|
||||
if ((wire->key < first) || (wire->key > last)) {
|
||||
*errorRtrn = _XkbErrCode4(0x33, first, last, wire->key);
|
||||
return 0;
|
||||
|
|
@ -1896,7 +1919,8 @@ CheckKeyBehaviors(XkbDescPtr xkb,
|
|||
}
|
||||
|
||||
static int
|
||||
CheckVirtualMods(XkbDescRec * xkb,
|
||||
CheckVirtualMods(ClientPtr client,
|
||||
XkbDescRec * xkb,
|
||||
xkbSetMapReq * req, CARD8 **wireRtrn, int *errorRtrn)
|
||||
{
|
||||
register CARD8 *wire = *wireRtrn;
|
||||
|
|
@ -1908,12 +1932,18 @@ CheckVirtualMods(XkbDescRec * xkb,
|
|||
if (req->virtualMods & bit)
|
||||
nMods++;
|
||||
}
|
||||
/* Check we received enough data for the number of virtual mods expected */
|
||||
if (!_XkbCheckRequestBounds(client, req, wire, wire + XkbPaddedSize(nMods))) {
|
||||
*errorRtrn = _XkbErrCode3(0x37, nMods, i);
|
||||
return 0;
|
||||
}
|
||||
*wireRtrn = (wire + XkbPaddedSize(nMods));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
CheckKeyExplicit(XkbDescPtr xkb,
|
||||
CheckKeyExplicit(ClientPtr client,
|
||||
XkbDescPtr xkb,
|
||||
xkbSetMapReq * req, CARD8 **wireRtrn, int *errorRtrn)
|
||||
{
|
||||
register CARD8 *wire = *wireRtrn;
|
||||
|
|
@ -1939,6 +1969,11 @@ CheckKeyExplicit(XkbDescPtr xkb,
|
|||
}
|
||||
start = wire;
|
||||
for (i = 0; i < req->totalKeyExplicit; i++, wire += 2) {
|
||||
/* Check we received enough data to read the next two bytes */
|
||||
if (!_XkbCheckRequestBounds(client, req, wire, wire + 2)) {
|
||||
*errorRtrn = _XkbErrCode4(0x54, first, last, i);
|
||||
return 0;
|
||||
}
|
||||
if ((wire[0] < first) || (wire[0] > last)) {
|
||||
*errorRtrn = _XkbErrCode4(0x53, first, last, wire[0]);
|
||||
return 0;
|
||||
|
|
@ -1994,7 +2029,8 @@ CheckModifierMap(ClientPtr client, XkbDescPtr xkb, xkbSetMapReq * req,
|
|||
}
|
||||
|
||||
static int
|
||||
CheckVirtualModMap(XkbDescPtr xkb,
|
||||
CheckVirtualModMap(ClientPtr client,
|
||||
XkbDescPtr xkb,
|
||||
xkbSetMapReq * req,
|
||||
xkbVModMapWireDesc ** wireRtrn, int *errRtrn)
|
||||
{
|
||||
|
|
@ -2018,6 +2054,11 @@ CheckVirtualModMap(XkbDescPtr xkb,
|
|||
return 0;
|
||||
}
|
||||
for (i = 0; i < req->totalVModMapKeys; i++, wire++) {
|
||||
/* Check we received enough data to read the next virtual mod map key */
|
||||
if (!_XkbCheckRequestBounds(client, req, wire, wire + 1)) {
|
||||
*errRtrn = _XkbErrCode3(0x74, first, i);
|
||||
return 0;
|
||||
}
|
||||
if ((wire->key < first) || (wire->key > last)) {
|
||||
*errRtrn = _XkbErrCode4(0x73, first, last, wire->key);
|
||||
return 0;
|
||||
|
|
@ -2561,7 +2602,7 @@ _XkbSetMapChecks(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq * req,
|
|||
}
|
||||
|
||||
if ((req->present & XkbKeyActionsMask) &&
|
||||
(!CheckKeyActions(xkb, req, nTypes, mapWidths, symsPerKey,
|
||||
(!CheckKeyActions(client, xkb, req, nTypes, mapWidths, symsPerKey,
|
||||
(CARD8 **) &values, &nActions))) {
|
||||
client->errorValue = nActions;
|
||||
return BadValue;
|
||||
|
|
@ -2569,18 +2610,18 @@ _XkbSetMapChecks(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq * req,
|
|||
|
||||
if ((req->present & XkbKeyBehaviorsMask) &&
|
||||
(!CheckKeyBehaviors
|
||||
(xkb, req, (xkbBehaviorWireDesc **) &values, &error))) {
|
||||
(client, xkb, req, (xkbBehaviorWireDesc **) &values, &error))) {
|
||||
client->errorValue = error;
|
||||
return BadValue;
|
||||
}
|
||||
|
||||
if ((req->present & XkbVirtualModsMask) &&
|
||||
(!CheckVirtualMods(xkb, req, (CARD8 **) &values, &error))) {
|
||||
(!CheckVirtualMods(client, xkb, req, (CARD8 **) &values, &error))) {
|
||||
client->errorValue = error;
|
||||
return BadValue;
|
||||
}
|
||||
if ((req->present & XkbExplicitComponentsMask) &&
|
||||
(!CheckKeyExplicit(xkb, req, (CARD8 **) &values, &error))) {
|
||||
(!CheckKeyExplicit(client, xkb, req, (CARD8 **) &values, &error))) {
|
||||
client->errorValue = error;
|
||||
return BadValue;
|
||||
}
|
||||
|
|
@ -2591,7 +2632,7 @@ _XkbSetMapChecks(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq * req,
|
|||
}
|
||||
if ((req->present & XkbVirtualModMapMask) &&
|
||||
(!CheckVirtualModMap
|
||||
(xkb, req, (xkbVModMapWireDesc **) &values, &error))) {
|
||||
(client, xkb, req, (xkbVModMapWireDesc **) &values, &error))) {
|
||||
client->errorValue = error;
|
||||
return BadValue;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue