forked from pool/xorg-x11-server
Stefan Dirsch
b8ff8cd1c1
* XkbSetMap Out-Of-Bounds Access: Insufficient checks on the lengths of the XkbSetMap request can lead to out of bounds memory accesses in the X server. (ZDI-CAN 11572, CVE-2020-14360, bsc#1174908) - U_Fix-XkbSetDeviceInfo-and-SetDeviceIndicators-heap-ov.patch * XkbSetDeviceInfo Heap-based Buffer Overflow: Insufficient checks on input of the XkbSetDeviceInfo request can lead to a buffer overflow on the head in the X server. (ZDI-CAN 11389, CVE-2020-25712, bsc#1177596) OBS-URL: https://build.opensuse.org/package/show/X11:XOrg/xorg-x11-server?expand=0&rev=782
97 lines
4.0 KiB
Diff
97 lines
4.0 KiB
Diff
From 87c64fc5b0db9f62f4e361444f4b60501ebf67b9 Mon Sep 17 00:00:00 2001
|
|
From: Matthieu Herrb <matthieu@herrb.eu>
|
|
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 <matthieu@herrb.eu>
|
|
---
|
|
xkb/xkb.c | 26 +++++++++++++++++++++++---
|
|
1 file changed, 23 insertions(+), 3 deletions(-)
|
|
|
|
Index: xserver-1.20.9/xkb/xkb.c
|
|
===================================================================
|
|
--- xserver-1.20.9.orig/xkb/xkb.c
|
|
+++ xserver-1.20.9/xkb/xkb.c
|
|
@@ -6533,7 +6533,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;
|
|
@@ -6554,6 +6556,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);
|
|
@@ -6572,6 +6579,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;
|
|
@@ -6589,6 +6600,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;
|
|
@@ -6668,7 +6683,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;
|
|
|
|
@@ -6680,7 +6695,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;
|
|
@@ -6701,7 +6720,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;
|
|
}
|