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

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