From 2146140683f8b0b196f3779807ef6a6ac929cfcc Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Wed, 12 Jun 2024 11:20:59 +0800 Subject: [PATCH] Fix CVE-2022-2320 Conflict:NA Reference:https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/938/diffs --- xkb/xkb.c | 88 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 62 insertions(+), 26 deletions(-) diff --git a/xkb/xkb.c b/xkb/xkb.c index bfc21de..fc970bd 100644 --- a/xkb/xkb.c +++ b/xkb/xkb.c @@ -5157,7 +5157,7 @@ _GetCountedString(char **wire_inout, ClientPtr client, char **str) } static Status -_CheckSetDoodad(char **wire_inout, +_CheckSetDoodad(char **wire_inout, xkbSetGeometryReq *req, XkbGeometryPtr geom, XkbSectionPtr section, ClientPtr client) { char *wire; @@ -5168,6 +5168,9 @@ _CheckSetDoodad(char **wire_inout, Status status; dWire = (xkbDoodadWireDesc *) (*wire_inout); + if (!_XkbCheckRequestBounds(client, req, dWire, dWire + 1)) + return BadLength; + any = dWire->any; wire = (char *) &dWire[1]; if (client->swapped) { @@ -5270,7 +5273,7 @@ _CheckSetDoodad(char **wire_inout, } static Status -_CheckSetOverlay(char **wire_inout, +_CheckSetOverlay(char **wire_inout, xkbSetGeometryReq *req, XkbGeometryPtr geom, XkbSectionPtr section, ClientPtr client) { register int r; @@ -5281,7 +5284,10 @@ _CheckSetOverlay(char **wire_inout, wire = *wire_inout; olWire = (xkbOverlayWireDesc *) wire; - if (client->swapped) { + if (!_XkbCheckRequestBounds(client, req, olWire, olWire + 1)) + return BadLength; + + if (client->swapped) { swapl(&olWire->name); } CHK_ATOM_ONLY(olWire->name); @@ -5291,6 +5297,8 @@ _CheckSetOverlay(char **wire_inout, register int k; xkbOverlayKeyWireDesc *kWire; XkbOverlayRowPtr row; + if (!_XkbCheckRequestBounds(client, req, rWire, rWire + 1)) + return BadLength; if (rWire->rowUnder > section->num_rows) { client->errorValue = _XkbErrCode4(0x20, r, section->num_rows, @@ -5300,6 +5308,9 @@ _CheckSetOverlay(char **wire_inout, row = XkbAddGeomOverlayRow(ol, rWire->rowUnder, rWire->nKeys); kWire = (xkbOverlayKeyWireDesc *) &rWire[1]; for (k = 0; k < rWire->nKeys; k++, kWire++) { + if (!_XkbCheckRequestBounds(client, req, kWire, kWire + 1)) + return BadLength; + if (XkbAddGeomOverlayKey(ol, row, (char *) kWire->over, (char *) kWire->under) == NULL) { @@ -5332,6 +5343,8 @@ _CheckSetSections(XkbGeometryPtr geom, for (s = 0; s < req->nSections; s++) { register int r; xkbRowWireDesc *rWire; + if (!_XkbCheckRequestBounds(client, req, sWire, sWire + 1)) + return BadLength; if (client->swapped) { swapl(&sWire->name); @@ -5357,6 +5370,9 @@ _CheckSetSections(XkbGeometryPtr geom, register int k; XkbRowPtr row; xkbKeyWireDesc *kWire; + if (!_XkbCheckRequestBounds(client, req, rWire, rWire + 1)) + return BadLength; + if (client->swapped) { swaps(&rWire->top); @@ -5371,6 +5387,8 @@ _CheckSetSections(XkbGeometryPtr geom, kWire = (xkbKeyWireDesc *) &rWire[1]; for (k = 0; k < rWire->nKeys; k++) { XkbKeyPtr key; + if (!_XkbCheckRequestBounds(client, req, kWire, kWire + 1)) + return BadLength; key = XkbAddGeomKey(row); if (!key) @@ -5397,7 +5415,7 @@ _CheckSetSections(XkbGeometryPtr geom, register int d; for (d = 0; d < sWire->nDoodads; d++) { - status = _CheckSetDoodad(&wire, geom, section, client); + status = _CheckSetDoodad(&wire, req, geom, section, client); if (status != Success) return status; } @@ -5406,7 +5424,7 @@ _CheckSetSections(XkbGeometryPtr geom, register int o; for (o = 0; o < sWire->nOverlays; o++) { - status = _CheckSetOverlay(&wire, geom, section, client); + status = _CheckSetOverlay(&wire, req, geom, section, client); if (status != Success) return status; } @@ -5439,6 +5457,9 @@ _CheckSetShapes(XkbGeometryPtr geom, for (i = 0; i < req->nShapes; i++) { xkbOutlineWireDesc *olWire; XkbOutlinePtr ol; + if (!_XkbCheckRequestBounds(client, req, shapeWire, shapeWire + 1)) + return BadLength; + shape = XkbAddGeomShape(geom, shapeWire->name, shapeWire->nOutlines); @@ -5449,6 +5470,9 @@ _CheckSetShapes(XkbGeometryPtr geom, register int p; XkbPointPtr pt; xkbPointWireDesc *ptWire; + if (!_XkbCheckRequestBounds(client, req, olWire, olWire + 1)) + return BadLength; + ol = XkbAddGeomOutline(shape, olWire->nPoints); if (!ol) @@ -5456,6 +5480,9 @@ _CheckSetShapes(XkbGeometryPtr geom, ol->corner_radius = olWire->cornerRadius; ptWire = (xkbPointWireDesc *) &olWire[1]; for (p = 0, pt = ol->points; p < olWire->nPoints; p++, pt++) { + if (!_XkbCheckRequestBounds(client, req, ptWire, ptWire + 1)) + return BadLength; + pt->x = ptWire[p].x; pt->y = ptWire[p].y; if (client->swapped) { @@ -5561,12 +5588,15 @@ _CheckSetGeom(XkbGeometryPtr geom, xkbSetGeometryReq * req, ClientPtr client) return status; for (i = 0; i < req->nDoodads; i++) { - status = _CheckSetDoodad(&wire, geom, NULL, client); + status = _CheckSetDoodad(&wire, req, geom, NULL, client); if (status != Success) return status; } for (i = 0; i < req->nKeyAliases; i++) { + if (!_XkbCheckRequestBounds(client, req, wire, wire + XkbKeyNameLength)) + return BadLength; + if (XkbAddGeomKeyAlias(geom, &wire[XkbKeyNameLength], wire) == NULL) return BadAlloc; wire += 2 * XkbKeyNameLength; @@ -6551,7 +6581,8 @@ ProcXkbGetDeviceInfo(ClientPtr client) static char * CheckSetDeviceIndicators(char *wire, DeviceIntPtr dev, - int num, int *status_rtrn, ClientPtr client) + int num, int *status_rtrn, ClientPtr client, + xkbSetDeviceInfoReq * stuff) { xkbDeviceLedsWireDesc *ledWire; int i; @@ -6559,6 +6590,12 @@ CheckSetDeviceIndicators(char *wire, ledWire = (xkbDeviceLedsWireDesc *) wire; for (i = 0; i < num; i++) { + if (!_XkbCheckRequestBounds(client, stuff, ledWire, ledWire + 1)) { + *status_rtrn = BadLength; + return (char *) ledWire; + } + + if (client->swapped) { swaps(&ledWire->ledClass); swaps(&ledWire->ledID); @@ -6586,6 +6623,11 @@ CheckSetDeviceIndicators(char *wire, atomWire = (CARD32 *) &ledWire[1]; if (nNames > 0) { for (n = 0; n < nNames; n++) { + if (!_XkbCheckRequestBounds(client, stuff, atomWire, atomWire + 1)) { + *status_rtrn = BadLength; + return (char *) atomWire; + } + if (client->swapped) { swapl(atomWire); } @@ -6597,6 +6639,11 @@ CheckSetDeviceIndicators(char *wire, mapWire = (xkbIndicatorMapWireDesc *) atomWire; if (nMaps > 0) { for (n = 0; n < nMaps; n++) { + if (!_XkbCheckRequestBounds(client, stuff, mapWire, mapWire + 1)) { + *status_rtrn = BadLength; + return (char *) mapWire; + } + if (client->swapped) { swaps(&mapWire->virtualMods); swapl(&mapWire->ctrls); @@ -6648,11 +6695,6 @@ SetDeviceIndicators(char *wire, xkbIndicatorMapWireDesc *mapWire; XkbSrvLedInfoPtr sli; - if (!_XkbCheckRequestBounds(client, stuff, ledWire, ledWire + 1)) { - *status_rtrn = BadLength; - return (char *) ledWire; - } - namec = mapc = statec = 0; sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID, XkbXI_IndicatorMapsMask); @@ -6671,10 +6713,6 @@ SetDeviceIndicators(char *wire, memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom)); for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) { if (ledWire->namesPresent & bit) { - if (!_XkbCheckRequestBounds(client, stuff, atomWire, atomWire + 1)) { - *status_rtrn = BadLength; - return (char *) atomWire; - } sli->names[n] = (Atom) *atomWire; if (sli->names[n] == None) ledWire->namesPresent &= ~bit; @@ -6692,10 +6730,6 @@ SetDeviceIndicators(char *wire, if (ledWire->mapsPresent) { for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) { if (ledWire->mapsPresent & bit) { - if (!_XkbCheckRequestBounds(client, stuff, mapWire, mapWire + 1)) { - *status_rtrn = BadLength; - return (char *) mapWire; - } sli->maps[n].flags = mapWire->flags; sli->maps[n].which_groups = mapWire->whichGroups; sli->maps[n].groups = mapWire->groups; @@ -6731,13 +6765,17 @@ SetDeviceIndicators(char *wire, } static int -_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev, +_XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev, xkbSetDeviceInfoReq * stuff) { char *wire; wire = (char *) &stuff[1]; if (stuff->change & XkbXI_ButtonActionsMask) { + int sz = stuff->nBtns * SIZEOF(xkbActionWireDesc); + if (!_XkbCheckRequestBounds(client, stuff, wire, (char *) wire + sz)) + return BadLength; + if (!dev->button) { client->errorValue = _XkbErrCode2(XkbErr_BadClass, ButtonClass); return XkbKeyboardErrorCode; @@ -6748,13 +6786,13 @@ _XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev, dev->button->numButtons); return BadMatch; } - wire += (stuff->nBtns * SIZEOF(xkbActionWireDesc)); + wire += sz; } if (stuff->change & XkbXI_IndicatorsMask) { int status = Success; wire = CheckSetDeviceIndicators(wire, dev, stuff->nDeviceLedFBs, - &status, client); + &status, client, stuff); if (status != Success) return status; } @@ -6765,7 +6803,7 @@ _XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev, } static int -_XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev, +_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev, xkbSetDeviceInfoReq * stuff) { char *wire; @@ -6790,8 +6828,6 @@ _XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev, if (stuff->firstBtn + stuff->nBtns > nBtns) return BadValue; sz = stuff->nBtns * SIZEOF(xkbActionWireDesc); - if (!_XkbCheckRequestBounds(client, stuff, wire, (char *) wire + sz)) - return BadLength; memcpy((char *) &acts[stuff->firstBtn], (char *) wire, sz); wire += sz; ed.reason |= XkbXI_ButtonActionsMask; -- 2.33.0