diff options
author | Matthieu Herrb <matthieu@herrb.eu> | 2020-10-11 17:05:09 +0200 |
---|---|---|
committer | Matthieu Herrb <matthieu@herrb.eu> | 2020-12-01 15:28:58 +0100 |
commit | 87c64fc5b0db9f62f4e361444f4b60501ebf67b9 (patch) | |
tree | ec70c1582a23e6e647412b343dd7f9f5c9ac5215 | |
parent | 11652706b0aa7d2609b710db0bd1262c5f6ed596 (diff) |
Fix XkbSetDeviceInfo() and SetDeviceIndicators() heap overflows
ZDI-CAN 11389 / CVE-2020-25712
This vulnerability was discovered by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
Signed-off-by: Matthieu Herrb <matthieu@herrb.eu>
-rw-r--r-- | xkb/xkb.c | 26 |
1 files changed, 23 insertions, 3 deletions
@@ -6536,7 +6536,9 @@ SetDeviceIndicators(char *wire, unsigned changed, int num, int *status_rtrn, - ClientPtr client, xkbExtensionDeviceNotify * ev) + ClientPtr client, + xkbExtensionDeviceNotify * ev, + xkbSetDeviceInfoReq * stuff) { xkbDeviceLedsWireDesc *ledWire; int i; @@ -6557,6 +6559,11 @@ SetDeviceIndicators(char *wire, xkbIndicatorMapWireDesc *mapWire; XkbSrvLedInfoPtr sli; + if (!_XkbCheckRequestBounds(client, stuff, ledWire, ledWire + 1)) { + *status_rtrn = BadLength; + return (char *) ledWire; + } + namec = mapc = statec = 0; sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID, XkbXI_IndicatorMapsMask); @@ -6575,6 +6582,10 @@ SetDeviceIndicators(char *wire, memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom)); for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) { if (ledWire->namesPresent & bit) { + if (!_XkbCheckRequestBounds(client, stuff, atomWire, atomWire + 1)) { + *status_rtrn = BadLength; + return (char *) atomWire; + } sli->names[n] = (Atom) *atomWire; if (sli->names[n] == None) ledWire->namesPresent &= ~bit; @@ -6592,6 +6603,10 @@ SetDeviceIndicators(char *wire, if (ledWire->mapsPresent) { for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) { if (ledWire->mapsPresent & bit) { + if (!_XkbCheckRequestBounds(client, stuff, mapWire, mapWire + 1)) { + *status_rtrn = BadLength; + return (char *) mapWire; + } sli->maps[n].flags = mapWire->flags; sli->maps[n].which_groups = mapWire->whichGroups; sli->maps[n].groups = mapWire->groups; @@ -6671,7 +6686,7 @@ _XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev, ed.deviceID = dev->id; wire = (char *) &stuff[1]; if (stuff->change & XkbXI_ButtonActionsMask) { - int nBtns, sz, i; + int nBtns, sz, i; XkbAction *acts; DeviceIntPtr kbd; @@ -6683,7 +6698,11 @@ _XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev, return BadAlloc; dev->button->xkb_acts = acts; } + if (stuff->firstBtn + stuff->nBtns > nBtns) + return BadValue; sz = stuff->nBtns * SIZEOF(xkbActionWireDesc); + if (!_XkbCheckRequestBounds(client, stuff, wire, (char *) wire + sz)) + return BadLength; memcpy((char *) &acts[stuff->firstBtn], (char *) wire, sz); wire += sz; ed.reason |= XkbXI_ButtonActionsMask; @@ -6704,7 +6723,8 @@ _XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev, int status = Success; wire = SetDeviceIndicators(wire, dev, stuff->change, - stuff->nDeviceLedFBs, &status, client, &ed); + stuff->nDeviceLedFBs, &status, client, &ed, + stuff); if (status != Success) return status; } |