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 <matthieu@herrb.eu>
This commit is contained in:
parent
1cccb486d4
commit
f7cd1276bb
48
xkb/xkb.c
48
xkb/xkb.c
|
@ -152,6 +152,19 @@ static RESTYPE RT_XKBCLIENT;
|
|||
#define CHK_REQ_KEY_RANGE(err,first,num,r) \
|
||||
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
|
||||
|
@ -4048,6 +4061,8 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
|
|||
client->errorValue = _XkbErrCode2(0x04, stuff->firstType);
|
||||
return BadAccess;
|
||||
}
|
||||
if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + stuff->nTypes))
|
||||
return BadLength;
|
||||
old = tmp;
|
||||
tmp = _XkbCheckAtoms(tmp, stuff->nTypes, client->swapped, &bad);
|
||||
if (!tmp) {
|
||||
|
@ -4077,6 +4092,8 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
|
|||
}
|
||||
width = (CARD8 *) tmp;
|
||||
tmp = (CARD32 *) (((char *) tmp) + XkbPaddedSize(stuff->nKTLevels));
|
||||
if (!_XkbCheckRequestBounds(client, stuff, width, tmp))
|
||||
return BadLength;
|
||||
type = &xkb->map->types[stuff->firstKTLevel];
|
||||
for (i = 0; i < stuff->nKTLevels; i++, type++) {
|
||||
if (width[i] == 0)
|
||||
|
@ -4086,6 +4103,8 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
|
|||
type->num_levels, width[i]);
|
||||
return BadMatch;
|
||||
}
|
||||
if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + width[i]))
|
||||
return BadLength;
|
||||
tmp = _XkbCheckAtoms(tmp, width[i], client->swapped, &bad);
|
||||
if (!tmp) {
|
||||
client->errorValue = bad;
|
||||
|
@ -4098,6 +4117,9 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
|
|||
client->errorValue = 0x08;
|
||||
return BadMatch;
|
||||
}
|
||||
if (!_XkbCheckRequestBounds(client, stuff, tmp,
|
||||
tmp + Ones(stuff->indicators)))
|
||||
return BadLength;
|
||||
tmp = _XkbCheckMaskedAtoms(tmp, XkbNumIndicators, stuff->indicators,
|
||||
client->swapped, &bad);
|
||||
if (!tmp) {
|
||||
|
@ -4110,6 +4132,9 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
|
|||
client->errorValue = 0x09;
|
||||
return BadMatch;
|
||||
}
|
||||
if (!_XkbCheckRequestBounds(client, stuff, tmp,
|
||||
tmp + Ones(stuff->virtualMods)))
|
||||
return BadLength;
|
||||
tmp = _XkbCheckMaskedAtoms(tmp, XkbNumVirtualMods,
|
||||
(CARD32) stuff->virtualMods,
|
||||
client->swapped, &bad);
|
||||
|
@ -4123,6 +4148,9 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
|
|||
client->errorValue = 0x0a;
|
||||
return BadMatch;
|
||||
}
|
||||
if (!_XkbCheckRequestBounds(client, stuff, tmp,
|
||||
tmp + Ones(stuff->groupNames)))
|
||||
return BadLength;
|
||||
tmp = _XkbCheckMaskedAtoms(tmp, XkbNumKbdGroups,
|
||||
(CARD32) stuff->groupNames,
|
||||
client->swapped, &bad);
|
||||
|
@ -4144,9 +4172,14 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
|
|||
stuff->nKeys);
|
||||
return BadValue;
|
||||
}
|
||||
if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + stuff->nKeys))
|
||||
return BadLength;
|
||||
tmp += stuff->nKeys;
|
||||
}
|
||||
if ((stuff->which & XkbKeyAliasesMask) && (stuff->nKeyAliases > 0)) {
|
||||
if (!_XkbCheckRequestBounds(client, stuff, tmp,
|
||||
tmp + (stuff->nKeyAliases * 2)))
|
||||
return BadLength;
|
||||
tmp += stuff->nKeyAliases * 2;
|
||||
}
|
||||
if (stuff->which & XkbRGNamesMask) {
|
||||
|
@ -4154,6 +4187,9 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
|
|||
client->errorValue = _XkbErrCode2(0x0d, stuff->nRadioGroups);
|
||||
return BadValue;
|
||||
}
|
||||
if (!_XkbCheckRequestBounds(client, stuff, tmp,
|
||||
tmp + stuff->nRadioGroups))
|
||||
return BadLength;
|
||||
tmp = _XkbCheckAtoms(tmp, stuff->nRadioGroups, client->swapped, &bad);
|
||||
if (!tmp) {
|
||||
client->errorValue = bad;
|
||||
|
@ -4347,6 +4383,8 @@ ProcXkbSetNames(ClientPtr client)
|
|||
/* check device-independent stuff */
|
||||
tmp = (CARD32 *) &stuff[1];
|
||||
|
||||
if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
|
||||
return BadLength;
|
||||
if (stuff->which & XkbKeycodesNameMask) {
|
||||
tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
|
||||
if (!tmp) {
|
||||
|
@ -4354,6 +4392,8 @@ ProcXkbSetNames(ClientPtr client)
|
|||
return BadAtom;
|
||||
}
|
||||
}
|
||||
if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
|
||||
return BadLength;
|
||||
if (stuff->which & XkbGeometryNameMask) {
|
||||
tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
|
||||
if (!tmp) {
|
||||
|
@ -4361,6 +4401,8 @@ ProcXkbSetNames(ClientPtr client)
|
|||
return BadAtom;
|
||||
}
|
||||
}
|
||||
if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
|
||||
return BadLength;
|
||||
if (stuff->which & XkbSymbolsNameMask) {
|
||||
tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
|
||||
if (!tmp) {
|
||||
|
@ -4368,6 +4410,8 @@ ProcXkbSetNames(ClientPtr client)
|
|||
return BadAtom;
|
||||
}
|
||||
}
|
||||
if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
|
||||
return BadLength;
|
||||
if (stuff->which & XkbPhysSymbolsNameMask) {
|
||||
tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
|
||||
if (!tmp) {
|
||||
|
@ -4375,6 +4419,8 @@ ProcXkbSetNames(ClientPtr client)
|
|||
return BadAtom;
|
||||
}
|
||||
}
|
||||
if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
|
||||
return BadLength;
|
||||
if (stuff->which & XkbTypesNameMask) {
|
||||
tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
|
||||
if (!tmp) {
|
||||
|
@ -4382,6 +4428,8 @@ ProcXkbSetNames(ClientPtr client)
|
|||
return BadAtom;
|
||||
}
|
||||
}
|
||||
if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
|
||||
return BadLength;
|
||||
if (stuff->which & XkbCompatNameMask) {
|
||||
tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
|
||||
if (!tmp) {
|
||||
|
|
Loading…
Reference in New Issue