Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[xsrc/netbsd-9]: xsrc/external/mit/xorg-server/dist/xkb Apply patch, requeste...
details: https://anonhg.NetBSD.org/xsrc/rev/1ffd7744fa06
branches: netbsd-9
changeset: 10636:1ffd7744fa06
user: martin <martin%NetBSD.org@localhost>
date: Sun Dec 06 10:18:02 2020 +0000
description:
Apply patch, requested by mrg in ticket #1141:
external/mit/xorg-server/dist/xkb/xkb.c apply patch
Apply upstream patches for:
* CVE-2020-14360 / ZDI CAN 11572 XkbSetMap Out-Of-Bounds Access
* CVE-2020-25712 / ZDI-CAN-11839 XkbSetDeviceInfo Heap-based Buffer Overflow
diffstat:
external/mit/xorg-server/dist/xkb/xkb.c | 197 +++++++++++++++++++++++++++++--
1 files changed, 180 insertions(+), 17 deletions(-)
diffs (truncated from 462 to 300 lines):
diff -r ef50ddea7cbb -r 1ffd7744fa06 external/mit/xorg-server/dist/xkb/xkb.c
--- a/external/mit/xorg-server/dist/xkb/xkb.c Thu Oct 22 11:25:22 2020 +0000
+++ b/external/mit/xorg-server/dist/xkb/xkb.c Sun Dec 06 10:18:02 2020 +0000
@@ -152,6 +152,19 @@
#define CHK_REQ_KEY_RANGE(err,first,num,r) \
CHK_REQ_KEY_RANGE2(err,first,num,r,client->errorValue,BadValue)
+static Bool
+_XkbCheckRequestBounds(ClientPtr client, void *stuff, void *from, void *to) {
+ char *cstuff = (char *)stuff;
+ char *cfrom = (char *)from;
+ char *cto = (char *)to;
+
+ return cfrom < cto &&
+ cfrom >= cstuff &&
+ cfrom < cstuff + ((size_t)client->req_len << 2) &&
+ cto >= cstuff &&
+ cto <= cstuff + ((size_t)client->req_len << 2);
+}
+
/***====================================================================***/
int
@@ -1587,7 +1600,7 @@
XkbDescPtr xkb,
xkbSetMapReq * req,
xkbKeyTypeWireDesc ** wireRtrn,
- int *nMapsRtrn, CARD8 *mapWidthRtrn)
+ int *nMapsRtrn, CARD8 *mapWidthRtrn, Bool doswap)
{
unsigned nMaps;
register unsigned i, n;
@@ -1626,7 +1639,7 @@
for (i = 0; i < req->nTypes; i++) {
unsigned width;
- if (client->swapped) {
+ if (client->swapped && doswap) {
swaps(&wire->virtualMods);
}
n = i + req->firstType;
@@ -1653,7 +1666,7 @@
mapWire = (xkbKTSetMapEntryWireDesc *) &wire[1];
preWire = (xkbModsWireDesc *) &mapWire[wire->nMapEntries];
for (n = 0; n < wire->nMapEntries; n++) {
- if (client->swapped) {
+ if (client->swapped && doswap) {
swaps(&mapWire[n].virtualMods);
}
if (mapWire[n].realMods & (~wire->realMods)) {
@@ -1671,7 +1684,7 @@
return 0;
}
if (wire->preserve) {
- if (client->swapped) {
+ if (client->swapped && doswap) {
swaps(&preWire[n].virtualMods);
}
if (preWire[n].realMods & (~mapWire[n].realMods)) {
@@ -1710,7 +1723,7 @@
xkbSetMapReq * req,
int nTypes,
CARD8 *mapWidths,
- CARD16 *symsPerKey, xkbSymMapWireDesc ** wireRtrn, int *errorRtrn)
+ CARD16 *symsPerKey, xkbSymMapWireDesc ** wireRtrn, int *errorRtrn, Bool doswap)
{
register unsigned i;
XkbSymMapPtr map;
@@ -1724,7 +1737,7 @@
KeySym *pSyms;
register unsigned nG;
- if (client->swapped) {
+ if (client->swapped && doswap) {
swaps(&wire->nSyms);
}
nG = XkbNumGroups(wire->groupInfo);
@@ -2366,13 +2379,100 @@
return (char *) wire;
}
+#define _add_check_len(new) \
+ if (len > UINT32_MAX - (new) || len > req_len - (new)) goto bad; \
+ else len += new
+
+/**
+ * Check the length of the SetMap request
+ */
+static int
+_XkbSetMapCheckLength(xkbSetMapReq *req)
+{
+ size_t len = sz_xkbSetMapReq, req_len = req->length << 2;
+ xkbKeyTypeWireDesc *keytype;
+ xkbSymMapWireDesc *symmap;
+ BOOL preserve;
+ int i, map_count, nSyms;
+
+ if (req_len < len)
+ goto bad;
+ /* types */
+ if (req->present & XkbKeyTypesMask) {
+ keytype = (xkbKeyTypeWireDesc *)(req + 1);
+ for (i = 0; i < req->nTypes; i++) {
+ _add_check_len(XkbPaddedSize(sz_xkbKeyTypeWireDesc));
+ if (req->flags & XkbSetMapResizeTypes) {
+ _add_check_len(keytype->nMapEntries
+ * sz_xkbKTSetMapEntryWireDesc);
+ preserve = keytype->preserve;
+ map_count = keytype->nMapEntries;
+ if (preserve) {
+ _add_check_len(map_count * sz_xkbModsWireDesc);
+ }
+ keytype += 1;
+ keytype = (xkbKeyTypeWireDesc *)
+ ((xkbKTSetMapEntryWireDesc *)keytype + map_count);
+ if (preserve)
+ keytype = (xkbKeyTypeWireDesc *)
+ ((xkbModsWireDesc *)keytype + map_count);
+ }
+ }
+ }
+ /* syms */
+ if (req->present & XkbKeySymsMask) {
+ symmap = (xkbSymMapWireDesc *)((char *)req + len);
+ for (i = 0; i < req->nKeySyms; i++) {
+ _add_check_len(sz_xkbSymMapWireDesc);
+ nSyms = symmap->nSyms;
+ _add_check_len(nSyms*sizeof(CARD32));
+ symmap += 1;
+ symmap = (xkbSymMapWireDesc *)((CARD32 *)symmap + nSyms);
+ }
+ }
+ /* actions */
+ if (req->present & XkbKeyActionsMask) {
+ _add_check_len(req->totalActs * sz_xkbActionWireDesc
+ + XkbPaddedSize(req->nKeyActs));
+ }
+ /* behaviours */
+ if (req->present & XkbKeyBehaviorsMask) {
+ _add_check_len(req->totalKeyBehaviors * sz_xkbBehaviorWireDesc);
+ }
+ /* vmods */
+ if (req->present & XkbVirtualModsMask) {
+ _add_check_len(XkbPaddedSize(Ones(req->virtualMods)));
+ }
+ /* explicit */
+ if (req->present & XkbExplicitComponentsMask) {
+ /* two bytes per non-zero explicit componen */
+ _add_check_len(XkbPaddedSize(req->totalKeyExplicit * sizeof(CARD16)));
+ }
+ /* modmap */
+ if (req->present & XkbModifierMapMask) {
+ /* two bytes per non-zero modmap component */
+ _add_check_len(XkbPaddedSize(req->totalModMapKeys * sizeof(CARD16)));
+ }
+ /* vmodmap */
+ if (req->present & XkbVirtualModMapMask) {
+ _add_check_len(req->totalVModMapKeys * sz_xkbVModMapWireDesc);
+ }
+ if (len == req_len)
+ return Success;
+bad:
+ ErrorF("[xkb] BOGUS LENGTH in SetMap: expected %ld got %ld\n",
+ len, req_len);
+ return BadLength;
+}
+
+
/**
* Check if the given request can be applied to the given device but don't
- * actually do anything..
+ * actually do anything, except swap values when client->swapped and doswap are both true.
*/
static int
_XkbSetMapChecks(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq * req,
- char *values)
+ char *values, Bool doswap)
{
XkbSrvInfoPtr xkbi;
XkbDescPtr xkb;
@@ -2409,10 +2509,13 @@
if ((req->present & XkbKeyTypesMask) &&
(!CheckKeyTypes(client, xkb, req, (xkbKeyTypeWireDesc **) &values,
- &nTypes, mapWidths))) {
+ &nTypes, mapWidths, doswap))) {
client->errorValue = nTypes;
return BadValue;
}
+ else {
+ nTypes = xkb->map->num_types;
+ }
/* symsPerKey/mapWidths must be filled regardless of client-side flags */
map = &xkb->map->key_sym_map[xkb->min_key_code];
@@ -2423,7 +2526,7 @@
for (w = g = 0; g < ng; g++) {
if (map->kt_index[g] >= (unsigned) nTypes) {
client->errorValue = _XkbErrCode4(0x13, i, g, map->kt_index[g]);
- return 0;
+ return BadValue;
}
if (mapWidths[map->kt_index[g]] > w)
w = mapWidths[map->kt_index[g]];
@@ -2433,7 +2536,7 @@
if ((req->present & XkbKeySymsMask) &&
(!CheckKeySyms(client, xkb, req, nTypes, mapWidths, symsPerKey,
- (xkbSymMapWireDesc **) &values, &error))) {
+ (xkbSymMapWireDesc **) &values, &error, doswap))) {
client->errorValue = error;
return BadValue;
}
@@ -2617,12 +2720,17 @@
CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
CHK_MASK_LEGAL(0x01, stuff->present, XkbAllMapComponentsMask);
+ /* first verify the request length carefully */
+ rc = _XkbSetMapCheckLength(stuff);
+ if (rc != Success)
+ return rc;
+
tmp = (char *) &stuff[1];
/* Check if we can to the SetMap on the requested device. If this
succeeds, do the same thing for all extension devices (if needed).
If any of them fails, fail. */
- rc = _XkbSetMapChecks(client, dev, stuff, tmp);
+ rc = _XkbSetMapChecks(client, dev, stuff, tmp, TRUE);
if (rc != Success)
return rc;
@@ -2638,7 +2746,7 @@
rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
DixManageAccess);
if (rc == Success) {
- rc = _XkbSetMapChecks(client, other, stuff, tmp);
+ rc = _XkbSetMapChecks(client, other, stuff, tmp, FALSE);
if (rc != Success)
return rc;
}
@@ -2652,7 +2760,7 @@
(other != master || dev != master->lastSlave))
continue;
- rc = _XkbSetMapChecks(client, other, stuff, tmp);
+ rc = _XkbSetMapChecks(client, other, stuff, tmp, FALSE);
if (rc != Success)
return rc;
}
@@ -4036,6 +4144,8 @@
client->errorValue = _XkbErrCode2(0x04, stuff->firstType);
return BadAccess;
}
+ if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + stuff->nTypes))
+ return BadLength;
old = tmp;
tmp = _XkbCheckAtoms(tmp, stuff->nTypes, client->swapped, &bad);
if (!tmp) {
@@ -4065,6 +4175,8 @@
}
width = (CARD8 *) tmp;
tmp = (CARD32 *) (((char *) tmp) + XkbPaddedSize(stuff->nKTLevels));
+ if (!_XkbCheckRequestBounds(client, stuff, width, tmp))
+ return BadLength;
type = &xkb->map->types[stuff->firstKTLevel];
for (i = 0; i < stuff->nKTLevels; i++, type++) {
if (width[i] == 0)
@@ -4074,6 +4186,8 @@
type->num_levels, width[i]);
return BadMatch;
}
+ if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + width[i]))
+ return BadLength;
tmp = _XkbCheckAtoms(tmp, width[i], client->swapped, &bad);
if (!tmp) {
client->errorValue = bad;
@@ -4086,6 +4200,9 @@
client->errorValue = 0x08;
return BadMatch;
}
+ if (!_XkbCheckRequestBounds(client, stuff, tmp,
+ tmp + Ones(stuff->indicators)))
+ return BadLength;
tmp = _XkbCheckMaskedAtoms(tmp, XkbNumIndicators, stuff->indicators,
client->swapped, &bad);
if (!tmp) {
@@ -4098,6 +4215,9 @@
client->errorValue = 0x09;
return BadMatch;
}
+ if (!_XkbCheckRequestBounds(client, stuff, tmp,
+ tmp + Ones(stuff->virtualMods)))
+ return BadLength;
tmp = _XkbCheckMaskedAtoms(tmp, XkbNumVirtualMods,
(CARD32) stuff->virtualMods,
client->swapped, &bad);
@@ -4111,6 +4231,9 @@
client->errorValue = 0x0a;
return BadMatch;
Home |
Main Index |
Thread Index |
Old Index