Commit 87c64fc5 authored by Matthieu Herrb's avatar Matthieu Herrb
Browse files

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's avatarMatthieu Herrb <matthieu@herrb.eu>
parent 11652706
......@@ -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;
}
......
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