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

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