From 87c64fc5b0db9f62f4e361444f4b60501ebf67b9 Mon Sep 17 00:00:00 2001 From: Matthieu Herrb Date: Sun, 11 Oct 2020 17:05:09 +0200 Subject: [PATCH] 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 Upstream-Status: Backport https://gitlab.freedesktop.org/xorg/xserver/-/commit/87c64fc5b0db9f62f4e361444f4b60501ebf67b9 CVE: CVE-2020-25712 Signed-off-by: Armin Kuster --- xkb/xkb.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) Index: xorg-server-1.20.8/xkb/xkb.c =================================================================== --- xorg-server-1.20.8.orig/xkb/xkb.c +++ xorg-server-1.20.8/xkb/xkb.c @@ -6625,7 +6625,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; @@ -6646,6 +6648,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); @@ -6664,6 +6671,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; @@ -6681,6 +6692,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; @@ -6760,7 +6775,7 @@ _XkbSetDeviceInfoCheck(ClientPtr client, 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; @@ -6772,7 +6787,11 @@ _XkbSetDeviceInfoCheck(ClientPtr client, 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; @@ -6793,7 +6812,8 @@ _XkbSetDeviceInfoCheck(ClientPtr client, 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; }