Blame SOURCES/0002-xkb-swap-XkbSetDeviceInfo-and-XkbSetDeviceInfoCheck.patch

41197e
From 45a0af83129eb7dc244c5118360afc1972a686c7 Mon Sep 17 00:00:00 2001
41197e
From: Peter Hutterer <peter.hutterer@who-t.net>
41197e
Date: Tue, 5 Jul 2022 09:50:41 +1000
41197e
Subject: [PATCH xserver 2/3] xkb: swap XkbSetDeviceInfo and
41197e
 XkbSetDeviceInfoCheck
41197e
41197e
XKB often uses a FooCheck and Foo function pair, the former is supposed
41197e
to check all values in the request and error out on BadLength,
41197e
BadValue, etc. The latter is then called once we're confident the values
41197e
are good (they may still fail on an individual device, but that's a
41197e
different topic).
41197e
41197e
In the case of XkbSetDeviceInfo, those functions were incorrectly
41197e
named, with XkbSetDeviceInfo ending up as the checker function and
41197e
XkbSetDeviceInfoCheck as the setter function. As a result, the setter
41197e
function was called before the checker function, accessing request
41197e
data and modifying device state before we ensured that the data is
41197e
valid.
41197e
41197e
In particular, the setter function relied on values being already
41197e
byte-swapped. This in turn could lead to potential OOB memory access.
41197e
41197e
Fix this by correctly naming the functions and moving the length checks
41197e
over to the checker function. These were added in 87c64fc5b0 to the
41197e
wrong function, probably due to the incorrect naming.
41197e
41197e
Fixes ZDI-CAN 16070, CVE-2022-2320.
41197e
41197e
This vulnerability was discovered by:
41197e
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
41197e
41197e
Introduced in c06e27b2f6fd9f7b9f827623a48876a225264132
41197e
41197e
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
41197e
(cherry picked from commit dd8caf39e9e15d8f302e54045dd08d8ebf1025dc)
41197e
---
41197e
 xkb/xkb.c | 46 +++++++++++++++++++++++++---------------------
41197e
 1 file changed, 25 insertions(+), 21 deletions(-)
41197e
41197e
diff --git a/xkb/xkb.c b/xkb/xkb.c
41197e
index 684394d77..36464a770 100644
41197e
--- a/xkb/xkb.c
41197e
+++ b/xkb/xkb.c
41197e
@@ -6554,7 +6554,8 @@ ProcXkbGetDeviceInfo(ClientPtr client)
41197e
 static char *
41197e
 CheckSetDeviceIndicators(char *wire,
41197e
                          DeviceIntPtr dev,
41197e
-                         int num, int *status_rtrn, ClientPtr client)
41197e
+                         int num, int *status_rtrn, ClientPtr client,
41197e
+                         xkbSetDeviceInfoReq * stuff)
41197e
 {
41197e
     xkbDeviceLedsWireDesc *ledWire;
41197e
     int i;
41197e
@@ -6562,6 +6563,11 @@ CheckSetDeviceIndicators(char *wire,
41197e
 
41197e
     ledWire = (xkbDeviceLedsWireDesc *) wire;
41197e
     for (i = 0; i < num; i++) {
41197e
+        if (!_XkbCheckRequestBounds(client, stuff, ledWire, ledWire + 1)) {
41197e
+            *status_rtrn = BadLength;
41197e
+            return (char *) ledWire;
41197e
+        }
41197e
+
41197e
         if (client->swapped) {
41197e
             swaps(&ledWire->ledClass);
41197e
             swaps(&ledWire->ledID);
41197e
@@ -6589,6 +6595,11 @@ CheckSetDeviceIndicators(char *wire,
41197e
             atomWire = (CARD32 *) &ledWire[1];
41197e
             if (nNames > 0) {
41197e
                 for (n = 0; n < nNames; n++) {
41197e
+                    if (!_XkbCheckRequestBounds(client, stuff, atomWire, atomWire + 1)) {
41197e
+                        *status_rtrn = BadLength;
41197e
+                        return (char *) atomWire;
41197e
+                    }
41197e
+
41197e
                     if (client->swapped) {
41197e
                         swapl(atomWire);
41197e
                     }
41197e
@@ -6600,6 +6611,10 @@ CheckSetDeviceIndicators(char *wire,
41197e
             mapWire = (xkbIndicatorMapWireDesc *) atomWire;
41197e
             if (nMaps > 0) {
41197e
                 for (n = 0; n < nMaps; n++) {
41197e
+                    if (!_XkbCheckRequestBounds(client, stuff, mapWire, mapWire + 1)) {
41197e
+                        *status_rtrn = BadLength;
41197e
+                        return (char *) mapWire;
41197e
+                    }
41197e
                     if (client->swapped) {
41197e
                         swaps(&mapWire->virtualMods);
41197e
                         swapl(&mapWire->ctrls);
41197e
@@ -6651,11 +6666,6 @@ SetDeviceIndicators(char *wire,
41197e
         xkbIndicatorMapWireDesc *mapWire;
41197e
         XkbSrvLedInfoPtr sli;
41197e
 
41197e
-        if (!_XkbCheckRequestBounds(client, stuff, ledWire, ledWire + 1)) {
41197e
-            *status_rtrn = BadLength;
41197e
-            return (char *) ledWire;
41197e
-        }
41197e
-
41197e
         namec = mapc = statec = 0;
41197e
         sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID,
41197e
                                 XkbXI_IndicatorMapsMask);
41197e
@@ -6674,10 +6684,6 @@ SetDeviceIndicators(char *wire,
41197e
             memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom));
41197e
             for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
41197e
                 if (ledWire->namesPresent & bit) {
41197e
-                    if (!_XkbCheckRequestBounds(client, stuff, atomWire, atomWire + 1)) {
41197e
-                        *status_rtrn = BadLength;
41197e
-                        return (char *) atomWire;
41197e
-                    }
41197e
                     sli->names[n] = (Atom) *atomWire;
41197e
                     if (sli->names[n] == None)
41197e
                         ledWire->namesPresent &= ~bit;
41197e
@@ -6695,10 +6701,6 @@ SetDeviceIndicators(char *wire,
41197e
         if (ledWire->mapsPresent) {
41197e
             for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
41197e
                 if (ledWire->mapsPresent & bit) {
41197e
-                    if (!_XkbCheckRequestBounds(client, stuff, mapWire, mapWire + 1)) {
41197e
-                        *status_rtrn = BadLength;
41197e
-                        return (char *) mapWire;
41197e
-                    }
41197e
                     sli->maps[n].flags = mapWire->flags;
41197e
                     sli->maps[n].which_groups = mapWire->whichGroups;
41197e
                     sli->maps[n].groups = mapWire->groups;
41197e
@@ -6734,13 +6736,17 @@ SetDeviceIndicators(char *wire,
41197e
 }
41197e
 
41197e
 static int
41197e
-_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev,
41197e
+_XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev,
41197e
                   xkbSetDeviceInfoReq * stuff)
41197e
 {
41197e
     char *wire;
41197e
 
41197e
     wire = (char *) &stuff[1];
41197e
     if (stuff->change & XkbXI_ButtonActionsMask) {
41197e
+        int sz = stuff->nBtns * SIZEOF(xkbActionWireDesc);
41197e
+        if (!_XkbCheckRequestBounds(client, stuff, wire, (char *) wire + sz))
41197e
+            return BadLength;
41197e
+
41197e
         if (!dev->button) {
41197e
             client->errorValue = _XkbErrCode2(XkbErr_BadClass, ButtonClass);
41197e
             return XkbKeyboardErrorCode;
41197e
@@ -6751,13 +6757,13 @@ _XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev,
41197e
                              dev->button->numButtons);
41197e
             return BadMatch;
41197e
         }
41197e
-        wire += (stuff->nBtns * SIZEOF(xkbActionWireDesc));
41197e
+        wire += sz;
41197e
     }
41197e
     if (stuff->change & XkbXI_IndicatorsMask) {
41197e
         int status = Success;
41197e
 
41197e
         wire = CheckSetDeviceIndicators(wire, dev, stuff->nDeviceLedFBs,
41197e
-                                        &status, client);
41197e
+                                        &status, client, stuff);
41197e
         if (status != Success)
41197e
             return status;
41197e
     }
41197e
@@ -6768,8 +6774,8 @@ _XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev,
41197e
 }
41197e
 
41197e
 static int
41197e
-_XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev,
41197e
-                       xkbSetDeviceInfoReq * stuff)
41197e
+_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev,
41197e
+                  xkbSetDeviceInfoReq * stuff)
41197e
 {
41197e
     char *wire;
41197e
     xkbExtensionDeviceNotify ed;
41197e
@@ -6793,8 +6799,6 @@ _XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev,
41197e
         if (stuff->firstBtn + stuff->nBtns > nBtns)
41197e
             return BadValue;
41197e
         sz = stuff->nBtns * SIZEOF(xkbActionWireDesc);
41197e
-        if (!_XkbCheckRequestBounds(client, stuff, wire, (char *) wire + sz))
41197e
-            return BadLength;
41197e
         memcpy((char *) &acts[stuff->firstBtn], (char *) wire, sz);
41197e
         wire += sz;
41197e
         ed.reason |= XkbXI_ButtonActionsMask;
41197e
-- 
41197e
2.36.1
41197e