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>
This commit is contained in:
parent
11652706b0
commit
87c64fc5b0
26
xkb/xkb.c
26
xkb/xkb.c
|
@ -6536,7 +6536,9 @@ SetDeviceIndicators(char *wire,
|
||||||
unsigned changed,
|
unsigned changed,
|
||||||
int num,
|
int num,
|
||||||
int *status_rtrn,
|
int *status_rtrn,
|
||||||
ClientPtr client, xkbExtensionDeviceNotify * ev)
|
ClientPtr client,
|
||||||
|
xkbExtensionDeviceNotify * ev,
|
||||||
|
xkbSetDeviceInfoReq * stuff)
|
||||||
{
|
{
|
||||||
xkbDeviceLedsWireDesc *ledWire;
|
xkbDeviceLedsWireDesc *ledWire;
|
||||||
int i;
|
int i;
|
||||||
|
@ -6557,6 +6559,11 @@ SetDeviceIndicators(char *wire,
|
||||||
xkbIndicatorMapWireDesc *mapWire;
|
xkbIndicatorMapWireDesc *mapWire;
|
||||||
XkbSrvLedInfoPtr sli;
|
XkbSrvLedInfoPtr sli;
|
||||||
|
|
||||||
|
if (!_XkbCheckRequestBounds(client, stuff, ledWire, ledWire + 1)) {
|
||||||
|
*status_rtrn = BadLength;
|
||||||
|
return (char *) ledWire;
|
||||||
|
}
|
||||||
|
|
||||||
namec = mapc = statec = 0;
|
namec = mapc = statec = 0;
|
||||||
sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID,
|
sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID,
|
||||||
XkbXI_IndicatorMapsMask);
|
XkbXI_IndicatorMapsMask);
|
||||||
|
@ -6575,6 +6582,10 @@ SetDeviceIndicators(char *wire,
|
||||||
memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom));
|
memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom));
|
||||||
for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
|
for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
|
||||||
if (ledWire->namesPresent & bit) {
|
if (ledWire->namesPresent & bit) {
|
||||||
|
if (!_XkbCheckRequestBounds(client, stuff, atomWire, atomWire + 1)) {
|
||||||
|
*status_rtrn = BadLength;
|
||||||
|
return (char *) atomWire;
|
||||||
|
}
|
||||||
sli->names[n] = (Atom) *atomWire;
|
sli->names[n] = (Atom) *atomWire;
|
||||||
if (sli->names[n] == None)
|
if (sli->names[n] == None)
|
||||||
ledWire->namesPresent &= ~bit;
|
ledWire->namesPresent &= ~bit;
|
||||||
|
@ -6592,6 +6603,10 @@ SetDeviceIndicators(char *wire,
|
||||||
if (ledWire->mapsPresent) {
|
if (ledWire->mapsPresent) {
|
||||||
for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
|
for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
|
||||||
if (ledWire->mapsPresent & bit) {
|
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].flags = mapWire->flags;
|
||||||
sli->maps[n].which_groups = mapWire->whichGroups;
|
sli->maps[n].which_groups = mapWire->whichGroups;
|
||||||
sli->maps[n].groups = mapWire->groups;
|
sli->maps[n].groups = mapWire->groups;
|
||||||
|
@ -6671,7 +6686,7 @@ _XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev,
|
||||||
ed.deviceID = dev->id;
|
ed.deviceID = dev->id;
|
||||||
wire = (char *) &stuff[1];
|
wire = (char *) &stuff[1];
|
||||||
if (stuff->change & XkbXI_ButtonActionsMask) {
|
if (stuff->change & XkbXI_ButtonActionsMask) {
|
||||||
int nBtns, sz, i;
|
int nBtns, sz, i;
|
||||||
XkbAction *acts;
|
XkbAction *acts;
|
||||||
DeviceIntPtr kbd;
|
DeviceIntPtr kbd;
|
||||||
|
|
||||||
|
@ -6683,7 +6698,11 @@ _XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev,
|
||||||
return BadAlloc;
|
return BadAlloc;
|
||||||
dev->button->xkb_acts = acts;
|
dev->button->xkb_acts = acts;
|
||||||
}
|
}
|
||||||
|
if (stuff->firstBtn + stuff->nBtns > nBtns)
|
||||||
|
return BadValue;
|
||||||
sz = stuff->nBtns * SIZEOF(xkbActionWireDesc);
|
sz = stuff->nBtns * SIZEOF(xkbActionWireDesc);
|
||||||
|
if (!_XkbCheckRequestBounds(client, stuff, wire, (char *) wire + sz))
|
||||||
|
return BadLength;
|
||||||
memcpy((char *) &acts[stuff->firstBtn], (char *) wire, sz);
|
memcpy((char *) &acts[stuff->firstBtn], (char *) wire, sz);
|
||||||
wire += sz;
|
wire += sz;
|
||||||
ed.reason |= XkbXI_ButtonActionsMask;
|
ed.reason |= XkbXI_ButtonActionsMask;
|
||||||
|
@ -6704,7 +6723,8 @@ _XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev,
|
||||||
int status = Success;
|
int status = Success;
|
||||||
|
|
||||||
wire = SetDeviceIndicators(wire, dev, stuff->change,
|
wire = SetDeviceIndicators(wire, dev, stuff->change,
|
||||||
stuff->nDeviceLedFBs, &status, client, &ed);
|
stuff->nDeviceLedFBs, &status, client, &ed,
|
||||||
|
stuff);
|
||||||
if (status != Success)
|
if (status != Success)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user