Commit f7cd1276 authored by Matthieu Herrb's avatar Matthieu Herrb

Correct bounds checking in XkbSetNames()

CVE-2020-14345 / ZDI 11428

This vulnerability was discovered by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
Signed-off-by: Matthieu Herrb's avatarMatthieu Herrb <matthieu@herrb.eu>
parent 1cccb486
...@@ -152,6 +152,19 @@ static RESTYPE RT_XKBCLIENT; ...@@ -152,6 +152,19 @@ static RESTYPE RT_XKBCLIENT;
#define CHK_REQ_KEY_RANGE(err,first,num,r) \ #define CHK_REQ_KEY_RANGE(err,first,num,r) \
CHK_REQ_KEY_RANGE2(err,first,num,r,client->errorValue,BadValue) CHK_REQ_KEY_RANGE2(err,first,num,r,client->errorValue,BadValue)
static Bool
_XkbCheckRequestBounds(ClientPtr client, void *stuff, void *from, void *to) {
char *cstuff = (char *)stuff;
char *cfrom = (char *)from;
char *cto = (char *)to;
return cfrom < cto &&
cfrom >= cstuff &&
cfrom < cstuff + ((size_t)client->req_len << 2) &&
cto >= cstuff &&
cto <= cstuff + ((size_t)client->req_len << 2);
}
/***====================================================================***/ /***====================================================================***/
int int
...@@ -4048,6 +4061,8 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev, ...@@ -4048,6 +4061,8 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
client->errorValue = _XkbErrCode2(0x04, stuff->firstType); client->errorValue = _XkbErrCode2(0x04, stuff->firstType);
return BadAccess; return BadAccess;
} }
if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + stuff->nTypes))
return BadLength;
old = tmp; old = tmp;
tmp = _XkbCheckAtoms(tmp, stuff->nTypes, client->swapped, &bad); tmp = _XkbCheckAtoms(tmp, stuff->nTypes, client->swapped, &bad);
if (!tmp) { if (!tmp) {
...@@ -4077,6 +4092,8 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev, ...@@ -4077,6 +4092,8 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
} }
width = (CARD8 *) tmp; width = (CARD8 *) tmp;
tmp = (CARD32 *) (((char *) tmp) + XkbPaddedSize(stuff->nKTLevels)); tmp = (CARD32 *) (((char *) tmp) + XkbPaddedSize(stuff->nKTLevels));
if (!_XkbCheckRequestBounds(client, stuff, width, tmp))
return BadLength;
type = &xkb->map->types[stuff->firstKTLevel]; type = &xkb->map->types[stuff->firstKTLevel];
for (i = 0; i < stuff->nKTLevels; i++, type++) { for (i = 0; i < stuff->nKTLevels; i++, type++) {
if (width[i] == 0) if (width[i] == 0)
...@@ -4086,6 +4103,8 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev, ...@@ -4086,6 +4103,8 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
type->num_levels, width[i]); type->num_levels, width[i]);
return BadMatch; return BadMatch;
} }
if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + width[i]))
return BadLength;
tmp = _XkbCheckAtoms(tmp, width[i], client->swapped, &bad); tmp = _XkbCheckAtoms(tmp, width[i], client->swapped, &bad);
if (!tmp) { if (!tmp) {
client->errorValue = bad; client->errorValue = bad;
...@@ -4098,6 +4117,9 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev, ...@@ -4098,6 +4117,9 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
client->errorValue = 0x08; client->errorValue = 0x08;
return BadMatch; return BadMatch;
} }
if (!_XkbCheckRequestBounds(client, stuff, tmp,
tmp + Ones(stuff->indicators)))
return BadLength;
tmp = _XkbCheckMaskedAtoms(tmp, XkbNumIndicators, stuff->indicators, tmp = _XkbCheckMaskedAtoms(tmp, XkbNumIndicators, stuff->indicators,
client->swapped, &bad); client->swapped, &bad);
if (!tmp) { if (!tmp) {
...@@ -4110,6 +4132,9 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev, ...@@ -4110,6 +4132,9 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
client->errorValue = 0x09; client->errorValue = 0x09;
return BadMatch; return BadMatch;
} }
if (!_XkbCheckRequestBounds(client, stuff, tmp,
tmp + Ones(stuff->virtualMods)))
return BadLength;
tmp = _XkbCheckMaskedAtoms(tmp, XkbNumVirtualMods, tmp = _XkbCheckMaskedAtoms(tmp, XkbNumVirtualMods,
(CARD32) stuff->virtualMods, (CARD32) stuff->virtualMods,
client->swapped, &bad); client->swapped, &bad);
...@@ -4123,6 +4148,9 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev, ...@@ -4123,6 +4148,9 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
client->errorValue = 0x0a; client->errorValue = 0x0a;
return BadMatch; return BadMatch;
} }
if (!_XkbCheckRequestBounds(client, stuff, tmp,
tmp + Ones(stuff->groupNames)))
return BadLength;
tmp = _XkbCheckMaskedAtoms(tmp, XkbNumKbdGroups, tmp = _XkbCheckMaskedAtoms(tmp, XkbNumKbdGroups,
(CARD32) stuff->groupNames, (CARD32) stuff->groupNames,
client->swapped, &bad); client->swapped, &bad);
...@@ -4144,9 +4172,14 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev, ...@@ -4144,9 +4172,14 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
stuff->nKeys); stuff->nKeys);
return BadValue; return BadValue;
} }
if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + stuff->nKeys))
return BadLength;
tmp += stuff->nKeys; tmp += stuff->nKeys;
} }
if ((stuff->which & XkbKeyAliasesMask) && (stuff->nKeyAliases > 0)) { if ((stuff->which & XkbKeyAliasesMask) && (stuff->nKeyAliases > 0)) {
if (!_XkbCheckRequestBounds(client, stuff, tmp,
tmp + (stuff->nKeyAliases * 2)))
return BadLength;
tmp += stuff->nKeyAliases * 2; tmp += stuff->nKeyAliases * 2;
} }
if (stuff->which & XkbRGNamesMask) { if (stuff->which & XkbRGNamesMask) {
...@@ -4154,6 +4187,9 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev, ...@@ -4154,6 +4187,9 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
client->errorValue = _XkbErrCode2(0x0d, stuff->nRadioGroups); client->errorValue = _XkbErrCode2(0x0d, stuff->nRadioGroups);
return BadValue; return BadValue;
} }
if (!_XkbCheckRequestBounds(client, stuff, tmp,
tmp + stuff->nRadioGroups))
return BadLength;
tmp = _XkbCheckAtoms(tmp, stuff->nRadioGroups, client->swapped, &bad); tmp = _XkbCheckAtoms(tmp, stuff->nRadioGroups, client->swapped, &bad);
if (!tmp) { if (!tmp) {
client->errorValue = bad; client->errorValue = bad;
...@@ -4347,6 +4383,8 @@ ProcXkbSetNames(ClientPtr client) ...@@ -4347,6 +4383,8 @@ ProcXkbSetNames(ClientPtr client)
/* check device-independent stuff */ /* check device-independent stuff */
tmp = (CARD32 *) &stuff[1]; tmp = (CARD32 *) &stuff[1];
if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
return BadLength;
if (stuff->which & XkbKeycodesNameMask) { if (stuff->which & XkbKeycodesNameMask) {
tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad); tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
if (!tmp) { if (!tmp) {
...@@ -4354,6 +4392,8 @@ ProcXkbSetNames(ClientPtr client) ...@@ -4354,6 +4392,8 @@ ProcXkbSetNames(ClientPtr client)
return BadAtom; return BadAtom;
} }
} }
if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
return BadLength;
if (stuff->which & XkbGeometryNameMask) { if (stuff->which & XkbGeometryNameMask) {
tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad); tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
if (!tmp) { if (!tmp) {
...@@ -4361,6 +4401,8 @@ ProcXkbSetNames(ClientPtr client) ...@@ -4361,6 +4401,8 @@ ProcXkbSetNames(ClientPtr client)
return BadAtom; return BadAtom;
} }
} }
if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
return BadLength;
if (stuff->which & XkbSymbolsNameMask) { if (stuff->which & XkbSymbolsNameMask) {
tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad); tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
if (!tmp) { if (!tmp) {
...@@ -4368,6 +4410,8 @@ ProcXkbSetNames(ClientPtr client) ...@@ -4368,6 +4410,8 @@ ProcXkbSetNames(ClientPtr client)
return BadAtom; return BadAtom;
} }
} }
if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
return BadLength;
if (stuff->which & XkbPhysSymbolsNameMask) { if (stuff->which & XkbPhysSymbolsNameMask) {
tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad); tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
if (!tmp) { if (!tmp) {
...@@ -4375,6 +4419,8 @@ ProcXkbSetNames(ClientPtr client) ...@@ -4375,6 +4419,8 @@ ProcXkbSetNames(ClientPtr client)
return BadAtom; return BadAtom;
} }
} }
if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
return BadLength;
if (stuff->which & XkbTypesNameMask) { if (stuff->which & XkbTypesNameMask) {
tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad); tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
if (!tmp) { if (!tmp) {
...@@ -4382,6 +4428,8 @@ ProcXkbSetNames(ClientPtr client) ...@@ -4382,6 +4428,8 @@ ProcXkbSetNames(ClientPtr client)
return BadAtom; return BadAtom;
} }
} }
if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
return BadLength;
if (stuff->which & XkbCompatNameMask) { if (stuff->which & XkbCompatNameMask) {
tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad); tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
if (!tmp) { if (!tmp) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment