Blame SOURCES/0001-Correct-bounds-checking-in-XkbSetNames.patch

fac0ec
From 1d3a1092c30af660b1366fcd344af745590aa29f Mon Sep 17 00:00:00 2001
fac0ec
From: Matthieu Herrb <matthieu@herrb.eu>
fac0ec
Date: Tue, 18 Aug 2020 14:46:32 +0200
fac0ec
Subject: [PATCH xserver] Correct bounds checking in XkbSetNames()
fac0ec
MIME-Version: 1.0
fac0ec
Content-Type: text/plain; charset=UTF-8
fac0ec
Content-Transfer-Encoding: 8bit
fac0ec
fac0ec
CVE-2020-14345 / ZDI 11428
fac0ec
fac0ec
This vulnerability was discovered by:
fac0ec
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
fac0ec
fac0ec
Signed-off-by: Matthieu Herrb <matthieu@herrb.eu>
fac0ec
(cherry picked from commit 11f22a3bf694d7061d552c99898d843bcdaf0cf1)
fac0ec
Signed-off-by: Michel Dänzer <mdaenzer@redhat.com>
fac0ec
---
fac0ec
 xkb/xkb.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
fac0ec
 1 file changed, 48 insertions(+)
fac0ec
fac0ec
diff --git a/xkb/xkb.c b/xkb/xkb.c
fac0ec
index 3162574a4..2139da7ee 100644
fac0ec
--- a/xkb/xkb.c
fac0ec
+++ b/xkb/xkb.c
fac0ec
@@ -152,6 +152,19 @@ static RESTYPE RT_XKBCLIENT;
fac0ec
 #define	CHK_REQ_KEY_RANGE(err,first,num,r)  \
fac0ec
 	CHK_REQ_KEY_RANGE2(err,first,num,r,client->errorValue,BadValue)
fac0ec
 
fac0ec
+static Bool
fac0ec
+_XkbCheckRequestBounds(ClientPtr client, void *stuff, void *from, void *to) {
fac0ec
+    char *cstuff = (char *)stuff;
fac0ec
+    char *cfrom = (char *)from;
fac0ec
+    char *cto = (char *)to;
fac0ec
+
fac0ec
+    return cfrom < cto &&
fac0ec
+           cfrom >= cstuff &&
fac0ec
+           cfrom < cstuff + ((size_t)client->req_len << 2) &&
fac0ec
+           cto >= cstuff &&
fac0ec
+           cto <= cstuff + ((size_t)client->req_len << 2);
fac0ec
+}
fac0ec
+
fac0ec
 /***====================================================================***/
fac0ec
 
fac0ec
 int
fac0ec
@@ -4045,6 +4058,8 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
fac0ec
             client->errorValue = _XkbErrCode2(0x04, stuff->firstType);
fac0ec
             return BadAccess;
fac0ec
         }
fac0ec
+        if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + stuff->nTypes))
fac0ec
+            return BadLength;
fac0ec
         old = tmp;
fac0ec
         tmp = _XkbCheckAtoms(tmp, stuff->nTypes, client->swapped, &bad;;
fac0ec
         if (!tmp) {
fac0ec
@@ -4074,6 +4089,8 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
fac0ec
         }
fac0ec
         width = (CARD8 *) tmp;
fac0ec
         tmp = (CARD32 *) (((char *) tmp) + XkbPaddedSize(stuff->nKTLevels));
fac0ec
+        if (!_XkbCheckRequestBounds(client, stuff, width, tmp))
fac0ec
+            return BadLength;
fac0ec
         type = &xkb->map->types[stuff->firstKTLevel];
fac0ec
         for (i = 0; i < stuff->nKTLevels; i++, type++) {
fac0ec
             if (width[i] == 0)
fac0ec
@@ -4083,6 +4100,8 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
fac0ec
                                                   type->num_levels, width[i]);
fac0ec
                 return BadMatch;
fac0ec
             }
fac0ec
+            if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + width[i]))
fac0ec
+                return BadLength;
fac0ec
             tmp = _XkbCheckAtoms(tmp, width[i], client->swapped, &bad;;
fac0ec
             if (!tmp) {
fac0ec
                 client->errorValue = bad;
fac0ec
@@ -4095,6 +4114,9 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
fac0ec
             client->errorValue = 0x08;
fac0ec
             return BadMatch;
fac0ec
         }
fac0ec
+        if (!_XkbCheckRequestBounds(client, stuff, tmp,
fac0ec
+                                    tmp + Ones(stuff->indicators)))
fac0ec
+            return BadLength;
fac0ec
         tmp = _XkbCheckMaskedAtoms(tmp, XkbNumIndicators, stuff->indicators,
fac0ec
                                    client->swapped, &bad;;
fac0ec
         if (!tmp) {
fac0ec
@@ -4107,6 +4129,9 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
fac0ec
             client->errorValue = 0x09;
fac0ec
             return BadMatch;
fac0ec
         }
fac0ec
+        if (!_XkbCheckRequestBounds(client, stuff, tmp,
fac0ec
+                                    tmp + Ones(stuff->virtualMods)))
fac0ec
+            return BadLength;
fac0ec
         tmp = _XkbCheckMaskedAtoms(tmp, XkbNumVirtualMods,
fac0ec
                                    (CARD32) stuff->virtualMods,
fac0ec
                                    client->swapped, &bad;;
fac0ec
@@ -4120,6 +4145,9 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
fac0ec
             client->errorValue = 0x0a;
fac0ec
             return BadMatch;
fac0ec
         }
fac0ec
+        if (!_XkbCheckRequestBounds(client, stuff, tmp,
fac0ec
+                                    tmp + Ones(stuff->groupNames)))
fac0ec
+            return BadLength;
fac0ec
         tmp = _XkbCheckMaskedAtoms(tmp, XkbNumKbdGroups,
fac0ec
                                    (CARD32) stuff->groupNames,
fac0ec
                                    client->swapped, &bad;;
fac0ec
@@ -4141,9 +4169,14 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
fac0ec
                              stuff->nKeys);
fac0ec
             return BadValue;
fac0ec
         }
fac0ec
+        if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + stuff->nKeys))
fac0ec
+            return BadLength;
fac0ec
         tmp += stuff->nKeys;
fac0ec
     }
fac0ec
     if ((stuff->which & XkbKeyAliasesMask) && (stuff->nKeyAliases > 0)) {
fac0ec
+        if (!_XkbCheckRequestBounds(client, stuff, tmp,
fac0ec
+                                    tmp + (stuff->nKeyAliases * 2)))
fac0ec
+            return BadLength;
fac0ec
         tmp += stuff->nKeyAliases * 2;
fac0ec
     }
fac0ec
     if (stuff->which & XkbRGNamesMask) {
fac0ec
@@ -4151,6 +4184,9 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
fac0ec
             client->errorValue = _XkbErrCode2(0x0d, stuff->nRadioGroups);
fac0ec
             return BadValue;
fac0ec
         }
fac0ec
+        if (!_XkbCheckRequestBounds(client, stuff, tmp,
fac0ec
+                                    tmp + stuff->nRadioGroups))
fac0ec
+            return BadLength;
fac0ec
         tmp = _XkbCheckAtoms(tmp, stuff->nRadioGroups, client->swapped, &bad;;
fac0ec
         if (!tmp) {
fac0ec
             client->errorValue = bad;
fac0ec
@@ -4344,6 +4380,8 @@ ProcXkbSetNames(ClientPtr client)
fac0ec
     /* check device-independent stuff */
fac0ec
     tmp = (CARD32 *) &stuff[1];
fac0ec
 
fac0ec
+    if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
fac0ec
+        return BadLength;
fac0ec
     if (stuff->which & XkbKeycodesNameMask) {
fac0ec
         tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad;;
fac0ec
         if (!tmp) {
fac0ec
@@ -4351,6 +4389,8 @@ ProcXkbSetNames(ClientPtr client)
fac0ec
             return BadAtom;
fac0ec
         }
fac0ec
     }
fac0ec
+    if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
fac0ec
+        return BadLength;
fac0ec
     if (stuff->which & XkbGeometryNameMask) {
fac0ec
         tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad;;
fac0ec
         if (!tmp) {
fac0ec
@@ -4358,6 +4398,8 @@ ProcXkbSetNames(ClientPtr client)
fac0ec
             return BadAtom;
fac0ec
         }
fac0ec
     }
fac0ec
+    if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
fac0ec
+        return BadLength;
fac0ec
     if (stuff->which & XkbSymbolsNameMask) {
fac0ec
         tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad;;
fac0ec
         if (!tmp) {
fac0ec
@@ -4365,6 +4407,8 @@ ProcXkbSetNames(ClientPtr client)
fac0ec
             return BadAtom;
fac0ec
         }
fac0ec
     }
fac0ec
+    if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
fac0ec
+        return BadLength;
fac0ec
     if (stuff->which & XkbPhysSymbolsNameMask) {
fac0ec
         tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad;;
fac0ec
         if (!tmp) {
fac0ec
@@ -4372,6 +4416,8 @@ ProcXkbSetNames(ClientPtr client)
fac0ec
             return BadAtom;
fac0ec
         }
fac0ec
     }
fac0ec
+    if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
fac0ec
+        return BadLength;
fac0ec
     if (stuff->which & XkbTypesNameMask) {
fac0ec
         tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad;;
fac0ec
         if (!tmp) {
fac0ec
@@ -4379,6 +4425,8 @@ ProcXkbSetNames(ClientPtr client)
fac0ec
             return BadAtom;
fac0ec
         }
fac0ec
     }
fac0ec
+    if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
fac0ec
+        return BadLength;
fac0ec
     if (stuff->which & XkbCompatNameMask) {
fac0ec
         tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad;;
fac0ec
         if (!tmp) {
fac0ec
-- 
fac0ec
2.28.0
fac0ec