Toshaan Bharvani
11 months ago
16 changed files with 1082 additions and 1 deletions
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
From 9ca7d3f61a88ae6cf47fdf139b6215d745db976b Mon Sep 17 00:00:00 2001 |
||||
From: Peter Hutterer <peter.hutterer@who-t.net> |
||||
Date: Wed, 25 Jan 2023 11:41:40 +1000 |
||||
Subject: [PATCH xserver] Xi: fix potential use-after-free in |
||||
DeepCopyPointerClasses |
||||
|
||||
CVE-2023-0494, ZDI-CAN-19596 |
||||
|
||||
This vulnerability was discovered by: |
||||
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative |
||||
|
||||
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> |
||||
(cherry picked from commit 0ba6d8c37071131a49790243cdac55392ecf71ec) |
||||
--- |
||||
Xi/exevents.c | 4 +++- |
||||
1 file changed, 3 insertions(+), 1 deletion(-) |
||||
|
||||
diff --git a/Xi/exevents.c b/Xi/exevents.c |
||||
index 217baa9561..dcd4efb3bc 100644 |
||||
--- a/Xi/exevents.c |
||||
+++ b/Xi/exevents.c |
||||
@@ -619,8 +619,10 @@ DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to) |
||||
memcpy(to->button->xkb_acts, from->button->xkb_acts, |
||||
sizeof(XkbAction)); |
||||
} |
||||
- else |
||||
+ else { |
||||
free(to->button->xkb_acts); |
||||
+ to->button->xkb_acts = NULL; |
||||
+ } |
||||
|
||||
memcpy(to->button->labels, from->button->labels, |
||||
from->button->numButtons * sizeof(Atom)); |
||||
-- |
||||
2.39.0 |
||||
|
@ -0,0 +1,52 @@
@@ -0,0 +1,52 @@
|
||||
From b320ca0ffe4c0c872eeb3a93d9bde21f765c7c63 Mon Sep 17 00:00:00 2001 |
||||
From: Peter Hutterer <peter.hutterer@who-t.net> |
||||
Date: Tue, 29 Nov 2022 12:55:45 +1000 |
||||
Subject: [PATCH xserver 1/7] Xtest: disallow GenericEvents in |
||||
XTestSwapFakeInput |
||||
|
||||
XTestSwapFakeInput assumes all events in this request are |
||||
sizeof(xEvent) and iterates through these in 32-byte increments. |
||||
However, a GenericEvent may be of arbitrary length longer than 32 bytes, |
||||
so any GenericEvent in this list would result in subsequent events to be |
||||
misparsed. |
||||
|
||||
Additional, the swapped event is written into a stack-allocated struct |
||||
xEvent (size 32 bytes). For any GenericEvent longer than 32 bytes, |
||||
swapping the event may thus smash the stack like an avocado on toast. |
||||
|
||||
Catch this case early and return BadValue for any GenericEvent. |
||||
Which is what would happen in unswapped setups anyway since XTest |
||||
doesn't support GenericEvent. |
||||
|
||||
CVE-2022-46340, ZDI-CAN 19265 |
||||
|
||||
This vulnerability was discovered by: |
||||
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative |
||||
|
||||
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> |
||||
Acked-by: Olivier Fourdan <ofourdan@redhat.com> |
||||
--- |
||||
Xext/xtest.c | 5 +++-- |
||||
1 file changed, 3 insertions(+), 2 deletions(-) |
||||
|
||||
diff --git a/Xext/xtest.c b/Xext/xtest.c |
||||
index bf27eb590b..2985a4ce6e 100644 |
||||
--- a/Xext/xtest.c |
||||
+++ b/Xext/xtest.c |
||||
@@ -502,10 +502,11 @@ XTestSwapFakeInput(ClientPtr client, xReq * req) |
||||
|
||||
nev = ((req->length << 2) - sizeof(xReq)) / sizeof(xEvent); |
||||
for (ev = (xEvent *) &req[1]; --nev >= 0; ev++) { |
||||
+ int evtype = ev->u.u.type & 0x177; |
||||
/* Swap event */ |
||||
- proc = EventSwapVector[ev->u.u.type & 0177]; |
||||
+ proc = EventSwapVector[evtype]; |
||||
/* no swapping proc; invalid event type? */ |
||||
- if (!proc || proc == NotImplemented) { |
||||
+ if (!proc || proc == NotImplemented || evtype == GenericEvent) { |
||||
client->errorValue = ev->u.u.type; |
||||
return BadValue; |
||||
} |
||||
-- |
||||
2.38.1 |
||||
|
@ -0,0 +1,72 @@
@@ -0,0 +1,72 @@
|
||||
From e67e988730346c63d2f0cdf2531ed36b0c7ad5a6 Mon Sep 17 00:00:00 2001 |
||||
From: Peter Hutterer <peter.hutterer@who-t.net> |
||||
Date: Wed, 23 Nov 2022 14:50:29 +1000 |
||||
Subject: [PATCH xserver] configure.ac: search for the fontrootdir ourselves |
||||
|
||||
This replaces the use of font-utils' .m4 macro set with a copy of the |
||||
only one we actually want: the bit for the fontrootpath. |
||||
|
||||
We don't need configure options for every single subfont directory, so |
||||
let's hardcode those in the default font path. Like meson does upstream |
||||
too. |
||||
|
||||
With this patch we no longer require the font-utils dependency. |
||||
|
||||
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> |
||||
--- |
||||
configure.ac | 28 +++++++++++++++++----------- |
||||
1 file changed, 17 insertions(+), 11 deletions(-) |
||||
|
||||
diff --git a/configure.ac b/configure.ac |
||||
index 0909cc5b4d..2349320888 100644 |
||||
--- a/configure.ac |
||||
+++ b/configure.ac |
||||
@@ -49,9 +49,6 @@ XORG_WITH_XSLTPROC |
||||
XORG_ENABLE_UNIT_TESTS |
||||
XORG_LD_WRAP([optional]) |
||||
|
||||
-m4_ifndef([XORG_FONT_MACROS_VERSION], [m4_fatal([must install font-util 1.1 or later before running autoconf/autogen])]) |
||||
-XORG_FONT_MACROS_VERSION(1.1) |
||||
- |
||||
dnl this gets generated by autoheader, and thus contains all the defines. we |
||||
dnl don't ever actually use it, internally. |
||||
AC_CONFIG_HEADERS(include/do-not-use-config.h) |
||||
@@ -450,18 +447,27 @@ AC_MSG_RESULT([$FALLBACK_INPUT_DRIVER]) |
||||
AC_DEFINE_UNQUOTED(FALLBACK_INPUT_DRIVER, ["$FALLBACK_INPUT_DRIVER"], [ Fallback input driver ]) |
||||
|
||||
dnl Determine font path |
||||
-XORG_FONTROOTDIR |
||||
-XORG_FONTSUBDIR(FONTMISCDIR, fontmiscdir, misc) |
||||
-XORG_FONTSUBDIR(FONTOTFDIR, fontotfdir, OTF) |
||||
-XORG_FONTSUBDIR(FONTTTFDIR, fontttfdir, TTF) |
||||
-XORG_FONTSUBDIR(FONTTYPE1DIR, fonttype1dir, Type1) |
||||
-XORG_FONTSUBDIR(FONT75DPIDIR, font75dpidir, 75dpi) |
||||
-XORG_FONTSUBDIR(FONT100DPIDIR, font100dpidir, 100dpi) |
||||
+dnl This is a copy of XORG_FONTROOTDIR from font-utils so we can drop the dependency |
||||
+AC_MSG_CHECKING([for root directory for font files]) |
||||
+AC_ARG_WITH(fontrootdir, |
||||
+ AS_HELP_STRING([--with-fontrootdir=DIR], |
||||
+ [Path to root directory for font files]), |
||||
+ [FONTROOTDIR="$withval"]) |
||||
+# if --with-fontrootdir not specified... |
||||
+if test "x${FONTROOTDIR}" = "x"; then |
||||
+ FONTROOTDIR=`$PKG_CONFIG --variable=fontrootdir fontutil` |
||||
+fi |
||||
+# ...and if pkg-config didn't find fontdir in fontutil.pc... |
||||
+if test "x${FONTROOTDIR}" = "x"; then |
||||
+ FONTROOTDIR="${datadir}/fonts/X11" |
||||
+fi |
||||
+AC_SUBST(FONTROOTDIR) |
||||
+AC_MSG_RESULT([${FONTROOTDIR}]) |
||||
|
||||
dnl Uses --with-default-font-path if set, otherwise uses standard |
||||
dnl subdirectories of FONTROOTDIR. Some distros set the default font path to |
||||
dnl "catalogue:/etc/X11/fontpath.d,built-ins" |
||||
-DEFAULT_FONT_PATH="${FONTMISCDIR}/,${FONTTTFDIR}/,${FONTOTFDIR}/,${FONTTYPE1DIR}/,${FONT100DPIDIR}/,${FONT75DPIDIR}/" |
||||
+DEFAULT_FONT_PATH="${FONTROOTDIR}/misc,${FONTROOTDIR}/OTF,${FONTROOTDIR}/TTF,${FONTROOTDIR}/Type1,${FONTROOTDIR}/75dpi,${FONTROOTDIR}/100dpi" |
||||
case $host_os in |
||||
darwin*) DEFAULT_FONT_PATH="${DEFAULT_FONT_PATH},/Library/Fonts,/System/Library/Fonts" ;; |
||||
esac |
||||
-- |
||||
2.38.1 |
||||
|
@ -0,0 +1,59 @@
@@ -0,0 +1,59 @@
|
||||
From 18f91b950e22c2a342a4fbc55e9ddf7534a707d2 Mon Sep 17 00:00:00 2001 |
||||
From: Peter Hutterer <peter.hutterer@who-t.net> |
||||
Date: Wed, 13 Jul 2022 11:23:09 +1000 |
||||
Subject: [PATCH xserver] xkb: fix some possible memleaks in XkbGetKbdByName |
||||
|
||||
GetComponentByName returns an allocated string, so let's free that if we |
||||
fail somewhere. |
||||
|
||||
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> |
||||
--- |
||||
xkb/xkb.c | 26 ++++++++++++++++++++------ |
||||
1 file changed, 20 insertions(+), 6 deletions(-) |
||||
|
||||
diff --git a/xkb/xkb.c b/xkb/xkb.c |
||||
index 4692895db..b79a269e3 100644 |
||||
--- a/xkb/xkb.c |
||||
+++ b/xkb/xkb.c |
||||
@@ -5935,18 +5935,32 @@ ProcXkbGetKbdByName(ClientPtr client) |
||||
xkb = dev->key->xkbInfo->desc; |
||||
status = Success; |
||||
str = (unsigned char *) &stuff[1]; |
||||
- if (GetComponentSpec(&str, TRUE, &status)) /* keymap, unsupported */ |
||||
- return BadMatch; |
||||
+ { |
||||
+ char *keymap = GetComponentSpec(&str, TRUE, &status); /* keymap, unsupported */ |
||||
+ if (keymap) { |
||||
+ free(keymap); |
||||
+ return BadMatch; |
||||
+ } |
||||
+ } |
||||
names.keycodes = GetComponentSpec(&str, TRUE, &status); |
||||
names.types = GetComponentSpec(&str, TRUE, &status); |
||||
names.compat = GetComponentSpec(&str, TRUE, &status); |
||||
names.symbols = GetComponentSpec(&str, TRUE, &status); |
||||
names.geometry = GetComponentSpec(&str, TRUE, &status); |
||||
- if (status != Success) |
||||
+ if (status == Success) { |
||||
+ len = str - ((unsigned char *) stuff); |
||||
+ if ((XkbPaddedSize(len) / 4) != stuff->length) |
||||
+ status = BadLength; |
||||
+ } |
||||
+ |
||||
+ if (status != Success) { |
||||
+ free(names.keycodes); |
||||
+ free(names.types); |
||||
+ free(names.compat); |
||||
+ free(names.symbols); |
||||
+ free(names.geometry); |
||||
return status; |
||||
- len = str - ((unsigned char *) stuff); |
||||
- if ((XkbPaddedSize(len) / 4) != stuff->length) |
||||
- return BadLength; |
||||
+ } |
||||
|
||||
CHK_MASK_LEGAL(0x01, stuff->want, XkbGBN_AllComponentsMask); |
||||
CHK_MASK_LEGAL(0x02, stuff->need, XkbGBN_AllComponentsMask); |
||||
-- |
||||
2.38.1 |
||||
|
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
From 11beef0b7f1ed290348e45618e5fa0d2bffcb72e Mon Sep 17 00:00:00 2001 |
||||
From: Peter Hutterer <peter.hutterer@who-t.net> |
||||
Date: Tue, 5 Jul 2022 12:06:20 +1000 |
||||
Subject: [PATCH xserver] xkb: proof GetCountedString against request length |
||||
attacks |
||||
|
||||
GetCountedString did a check for the whole string to be within the |
||||
request buffer but not for the initial 2 bytes that contain the length |
||||
field. A swapped client could send a malformed request to trigger a |
||||
swaps() on those bytes, writing into random memory. |
||||
|
||||
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> |
||||
--- |
||||
xkb/xkb.c | 5 +++++ |
||||
1 file changed, 5 insertions(+) |
||||
|
||||
diff --git a/xkb/xkb.c b/xkb/xkb.c |
||||
index f42f59ef3..1841cff26 100644 |
||||
--- a/xkb/xkb.c |
||||
+++ b/xkb/xkb.c |
||||
@@ -5137,6 +5137,11 @@ _GetCountedString(char **wire_inout, ClientPtr client, char **str) |
||||
CARD16 len; |
||||
|
||||
wire = *wire_inout; |
||||
+ |
||||
+ if (client->req_len < |
||||
+ bytes_to_int32(wire + 2 - (char *) client->requestBuffer)) |
||||
+ return BadValue; |
||||
+ |
||||
len = *(CARD16 *) wire; |
||||
if (client->swapped) { |
||||
swaps(&len); |
||||
-- |
||||
2.38.1 |
||||
|
@ -0,0 +1,77 @@
@@ -0,0 +1,77 @@
|
||||
From c9b379ec5a1a34692af06056925bd0fc5f809713 Mon Sep 17 00:00:00 2001 |
||||
From: Peter Hutterer <peter.hutterer@who-t.net> |
||||
Date: Tue, 5 Jul 2022 12:40:47 +1000 |
||||
Subject: [PATCH xserver 1/3] xkb: switch to array index loops to moving |
||||
pointers |
||||
|
||||
Most similar loops here use a pointer that advances with each loop |
||||
iteration, let's do the same here for consistency. |
||||
|
||||
No functional changes. |
||||
|
||||
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> |
||||
Reviewed-by: Olivier Fourdan <ofourdan@redhat.com> |
||||
(cherry picked from commit f1070c01d616c5f21f939d5ebc533738779451ac) |
||||
--- |
||||
xkb/xkb.c | 20 ++++++++++---------- |
||||
1 file changed, 10 insertions(+), 10 deletions(-) |
||||
|
||||
diff --git a/xkb/xkb.c b/xkb/xkb.c |
||||
index d056c698c..684394d77 100644 |
||||
--- a/xkb/xkb.c |
||||
+++ b/xkb/xkb.c |
||||
@@ -5372,16 +5372,16 @@ _CheckSetSections(XkbGeometryPtr geom, |
||||
row->left = rWire->left; |
||||
row->vertical = rWire->vertical; |
||||
kWire = (xkbKeyWireDesc *) &rWire[1]; |
||||
- for (k = 0; k < rWire->nKeys; k++) { |
||||
+ for (k = 0; k < rWire->nKeys; k++, kWire++) { |
||||
XkbKeyPtr key; |
||||
|
||||
key = XkbAddGeomKey(row); |
||||
if (!key) |
||||
return BadAlloc; |
||||
- memcpy(key->name.name, kWire[k].name, XkbKeyNameLength); |
||||
- key->gap = kWire[k].gap; |
||||
- key->shape_ndx = kWire[k].shapeNdx; |
||||
- key->color_ndx = kWire[k].colorNdx; |
||||
+ memcpy(key->name.name, kWire->name, XkbKeyNameLength); |
||||
+ key->gap = kWire->gap; |
||||
+ key->shape_ndx = kWire->shapeNdx; |
||||
+ key->color_ndx = kWire->colorNdx; |
||||
if (key->shape_ndx >= geom->num_shapes) { |
||||
client->errorValue = _XkbErrCode3(0x10, key->shape_ndx, |
||||
geom->num_shapes); |
||||
@@ -5393,7 +5393,7 @@ _CheckSetSections(XkbGeometryPtr geom, |
||||
return BadMatch; |
||||
} |
||||
} |
||||
- rWire = (xkbRowWireDesc *) &kWire[rWire->nKeys]; |
||||
+ rWire = (xkbRowWireDesc *)kWire; |
||||
} |
||||
wire = (char *) rWire; |
||||
if (sWire->nDoodads > 0) { |
||||
@@ -5458,16 +5458,16 @@ _CheckSetShapes(XkbGeometryPtr geom, |
||||
return BadAlloc; |
||||
ol->corner_radius = olWire->cornerRadius; |
||||
ptWire = (xkbPointWireDesc *) &olWire[1]; |
||||
- for (p = 0, pt = ol->points; p < olWire->nPoints; p++, pt++) { |
||||
- pt->x = ptWire[p].x; |
||||
- pt->y = ptWire[p].y; |
||||
+ for (p = 0, pt = ol->points; p < olWire->nPoints; p++, pt++, ptWire++) { |
||||
+ pt->x = ptWire->x; |
||||
+ pt->y = ptWire->y; |
||||
if (client->swapped) { |
||||
swaps(&pt->x); |
||||
swaps(&pt->y); |
||||
} |
||||
} |
||||
ol->num_points = olWire->nPoints; |
||||
- olWire = (xkbOutlineWireDesc *) (&ptWire[olWire->nPoints]); |
||||
+ olWire = (xkbOutlineWireDesc *)ptWire; |
||||
} |
||||
if (shapeWire->primaryNdx != XkbNoShape) |
||||
shape->primary = &shape->outlines[shapeWire->primaryNdx]; |
||||
-- |
||||
2.36.1 |
||||
|
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
From cb260ba95d2bb1ae98b05e289d1b7947ac409230 Mon Sep 17 00:00:00 2001 |
||||
From: Peter Hutterer <peter.hutterer@who-t.net> |
||||
Date: Tue, 29 Nov 2022 13:24:00 +1000 |
||||
Subject: [PATCH xserver 2/7] Xi: return an error from XI property changes if |
||||
verification failed |
||||
|
||||
Both ProcXChangeDeviceProperty and ProcXIChangeProperty checked the |
||||
property for validity but didn't actually return the potential error. |
||||
|
||||
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> |
||||
Acked-by: Olivier Fourdan <ofourdan@redhat.com> |
||||
--- |
||||
Xi/xiproperty.c | 5 +++++ |
||||
1 file changed, 5 insertions(+) |
||||
|
||||
diff --git a/Xi/xiproperty.c b/Xi/xiproperty.c |
||||
index a36f7d61df..68c362c628 100644 |
||||
--- a/Xi/xiproperty.c |
||||
+++ b/Xi/xiproperty.c |
||||
@@ -902,6 +902,8 @@ ProcXChangeDeviceProperty(ClientPtr client) |
||||
|
||||
rc = check_change_property(client, stuff->property, stuff->type, |
||||
stuff->format, stuff->mode, stuff->nUnits); |
||||
+ if (rc != Success) |
||||
+ return rc; |
||||
|
||||
len = stuff->nUnits; |
||||
if (len > (bytes_to_int32(0xffffffff - sizeof(xChangeDevicePropertyReq)))) |
||||
@@ -1141,6 +1143,9 @@ ProcXIChangeProperty(ClientPtr client) |
||||
|
||||
rc = check_change_property(client, stuff->property, stuff->type, |
||||
stuff->format, stuff->mode, stuff->num_items); |
||||
+ if (rc != Success) |
||||
+ return rc; |
||||
+ |
||||
len = stuff->num_items; |
||||
if (len > bytes_to_int32(0xffffffff - sizeof(xXIChangePropertyReq))) |
||||
return BadLength; |
||||
-- |
||||
2.38.1 |
||||
|
@ -0,0 +1,180 @@
@@ -0,0 +1,180 @@
|
||||
From 45a0af83129eb7dc244c5118360afc1972a686c7 Mon Sep 17 00:00:00 2001 |
||||
From: Peter Hutterer <peter.hutterer@who-t.net> |
||||
Date: Tue, 5 Jul 2022 09:50:41 +1000 |
||||
Subject: [PATCH xserver 2/3] xkb: swap XkbSetDeviceInfo and |
||||
XkbSetDeviceInfoCheck |
||||
|
||||
XKB often uses a FooCheck and Foo function pair, the former is supposed |
||||
to check all values in the request and error out on BadLength, |
||||
BadValue, etc. The latter is then called once we're confident the values |
||||
are good (they may still fail on an individual device, but that's a |
||||
different topic). |
||||
|
||||
In the case of XkbSetDeviceInfo, those functions were incorrectly |
||||
named, with XkbSetDeviceInfo ending up as the checker function and |
||||
XkbSetDeviceInfoCheck as the setter function. As a result, the setter |
||||
function was called before the checker function, accessing request |
||||
data and modifying device state before we ensured that the data is |
||||
valid. |
||||
|
||||
In particular, the setter function relied on values being already |
||||
byte-swapped. This in turn could lead to potential OOB memory access. |
||||
|
||||
Fix this by correctly naming the functions and moving the length checks |
||||
over to the checker function. These were added in 87c64fc5b0 to the |
||||
wrong function, probably due to the incorrect naming. |
||||
|
||||
Fixes ZDI-CAN 16070, CVE-2022-2320. |
||||
|
||||
This vulnerability was discovered by: |
||||
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative |
||||
|
||||
Introduced in c06e27b2f6fd9f7b9f827623a48876a225264132 |
||||
|
||||
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> |
||||
(cherry picked from commit dd8caf39e9e15d8f302e54045dd08d8ebf1025dc) |
||||
--- |
||||
xkb/xkb.c | 46 +++++++++++++++++++++++++--------------------- |
||||
1 file changed, 25 insertions(+), 21 deletions(-) |
||||
|
||||
diff --git a/xkb/xkb.c b/xkb/xkb.c |
||||
index 684394d77..36464a770 100644 |
||||
--- a/xkb/xkb.c |
||||
+++ b/xkb/xkb.c |
||||
@@ -6554,7 +6554,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; |
||||
@@ -6562,6 +6563,11 @@ 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); |
||||
@@ -6589,6 +6595,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); |
||||
} |
||||
@@ -6600,6 +6611,10 @@ 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); |
||||
@@ -6651,11 +6666,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); |
||||
@@ -6674,10 +6684,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; |
||||
@@ -6695,10 +6701,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; |
||||
@@ -6734,13 +6736,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; |
||||
@@ -6751,13 +6757,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; |
||||
} |
||||
@@ -6768,8 +6774,8 @@ _XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev, |
||||
} |
||||
|
||||
static int |
||||
-_XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev, |
||||
- xkbSetDeviceInfoReq * stuff) |
||||
+_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev, |
||||
+ xkbSetDeviceInfoReq * stuff) |
||||
{ |
||||
char *wire; |
||||
xkbExtensionDeviceNotify ed; |
||||
@@ -6793,8 +6799,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.36.1 |
||||
|
@ -0,0 +1,71 @@
@@ -0,0 +1,71 @@
|
||||
From a16f2b9693d248b81703821fd22fba8b5ba83e1a Mon Sep 17 00:00:00 2001 |
||||
From: Peter Hutterer <peter.hutterer@who-t.net> |
||||
Date: Tue, 29 Nov 2022 13:26:57 +1000 |
||||
Subject: [PATCH xserver 3/7] Xi: avoid integer truncation in length check of |
||||
ProcXIChangeProperty |
||||
|
||||
This fixes an OOB read and the resulting information disclosure. |
||||
|
||||
Length calculation for the request was clipped to a 32-bit integer. With |
||||
the correct stuff->num_items value the expected request size was |
||||
truncated, passing the REQUEST_FIXED_SIZE check. |
||||
|
||||
The server then proceeded with reading at least stuff->num_items bytes |
||||
(depending on stuff->format) from the request and stuffing whatever it |
||||
finds into the property. In the process it would also allocate at least |
||||
stuff->num_items bytes, i.e. 4GB. |
||||
|
||||
The same bug exists in ProcChangeProperty and ProcXChangeDeviceProperty, |
||||
so let's fix that too. |
||||
|
||||
CVE-2022-46344, ZDI-CAN 19405 |
||||
|
||||
This vulnerability was discovered by: |
||||
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative |
||||
|
||||
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> |
||||
Acked-by: Olivier Fourdan <ofourdan@redhat.com> |
||||
--- |
||||
Xi/xiproperty.c | 4 ++-- |
||||
dix/property.c | 3 ++- |
||||
2 files changed, 4 insertions(+), 3 deletions(-) |
||||
|
||||
diff --git a/Xi/xiproperty.c b/Xi/xiproperty.c |
||||
index 68c362c628..066ba21fba 100644 |
||||
--- a/Xi/xiproperty.c |
||||
+++ b/Xi/xiproperty.c |
||||
@@ -890,7 +890,7 @@ ProcXChangeDeviceProperty(ClientPtr client) |
||||
REQUEST(xChangeDevicePropertyReq); |
||||
DeviceIntPtr dev; |
||||
unsigned long len; |
||||
- int totalSize; |
||||
+ uint64_t totalSize; |
||||
int rc; |
||||
|
||||
REQUEST_AT_LEAST_SIZE(xChangeDevicePropertyReq); |
||||
@@ -1130,7 +1130,7 @@ ProcXIChangeProperty(ClientPtr client) |
||||
{ |
||||
int rc; |
||||
DeviceIntPtr dev; |
||||
- int totalSize; |
||||
+ uint64_t totalSize; |
||||
unsigned long len; |
||||
|
||||
REQUEST(xXIChangePropertyReq); |
||||
diff --git a/dix/property.c b/dix/property.c |
||||
index 94ef5a0ec0..acce94b2c6 100644 |
||||
--- a/dix/property.c |
||||
+++ b/dix/property.c |
||||
@@ -205,7 +205,8 @@ ProcChangeProperty(ClientPtr client) |
||||
WindowPtr pWin; |
||||
char format, mode; |
||||
unsigned long len; |
||||
- int sizeInBytes, totalSize, err; |
||||
+ int sizeInBytes, err; |
||||
+ uint64_t totalSize; |
||||
|
||||
REQUEST(xChangePropertyReq); |
||||
|
||||
-- |
||||
2.38.1 |
||||
|
@ -0,0 +1,183 @@
@@ -0,0 +1,183 @@
|
||||
From bd134231e282d9eb126b6fdaa40bb383180fa72b Mon Sep 17 00:00:00 2001 |
||||
From: Peter Hutterer <peter.hutterer@who-t.net> |
||||
Date: Tue, 5 Jul 2022 11:11:06 +1000 |
||||
Subject: [PATCH xserver 3/3] xkb: add request length validation for |
||||
XkbSetGeometry |
||||
|
||||
No validation of the various fields on that report were done, so a |
||||
malicious client could send a short request that claims it had N |
||||
sections, or rows, or keys, and the server would process the request for |
||||
N sections, running out of bounds of the actual request data. |
||||
|
||||
Fix this by adding size checks to ensure our data is valid. |
||||
|
||||
ZDI-CAN 16062, CVE-2022-2319. |
||||
|
||||
This vulnerability was discovered by: |
||||
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative |
||||
|
||||
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> |
||||
(cherry picked from commit 6907b6ea2b4ce949cb07271f5b678d5966d9df42) |
||||
--- |
||||
xkb/xkb.c | 43 ++++++++++++++++++++++++++++++++++++++----- |
||||
1 file changed, 38 insertions(+), 5 deletions(-) |
||||
|
||||
diff --git a/xkb/xkb.c b/xkb/xkb.c |
||||
index 36464a770..27d19793e 100644 |
||||
--- a/xkb/xkb.c |
||||
+++ b/xkb/xkb.c |
||||
@@ -5160,7 +5160,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; |
||||
@@ -5171,6 +5171,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) { |
||||
@@ -5273,7 +5276,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; |
||||
@@ -5284,6 +5287,9 @@ _CheckSetOverlay(char **wire_inout, |
||||
|
||||
wire = *wire_inout; |
||||
olWire = (xkbOverlayWireDesc *) wire; |
||||
+ if (!_XkbCheckRequestBounds(client, req, olWire, olWire + 1)) |
||||
+ return BadLength; |
||||
+ |
||||
if (client->swapped) { |
||||
swapl(&olWire->name); |
||||
} |
||||
@@ -5295,6 +5301,9 @@ _CheckSetOverlay(char **wire_inout, |
||||
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, |
||||
rWire->rowUnder); |
||||
@@ -5303,6 +5312,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) { |
||||
@@ -5336,6 +5348,9 @@ _CheckSetSections(XkbGeometryPtr geom, |
||||
register int r; |
||||
xkbRowWireDesc *rWire; |
||||
|
||||
+ if (!_XkbCheckRequestBounds(client, req, sWire, sWire + 1)) |
||||
+ return BadLength; |
||||
+ |
||||
if (client->swapped) { |
||||
swapl(&sWire->name); |
||||
swaps(&sWire->top); |
||||
@@ -5361,6 +5376,9 @@ _CheckSetSections(XkbGeometryPtr geom, |
||||
XkbRowPtr row; |
||||
xkbKeyWireDesc *kWire; |
||||
|
||||
+ if (!_XkbCheckRequestBounds(client, req, rWire, rWire + 1)) |
||||
+ return BadLength; |
||||
+ |
||||
if (client->swapped) { |
||||
swaps(&rWire->top); |
||||
swaps(&rWire->left); |
||||
@@ -5375,6 +5393,9 @@ _CheckSetSections(XkbGeometryPtr geom, |
||||
for (k = 0; k < rWire->nKeys; k++, kWire++) { |
||||
XkbKeyPtr key; |
||||
|
||||
+ if (!_XkbCheckRequestBounds(client, req, kWire, kWire + 1)) |
||||
+ return BadLength; |
||||
+ |
||||
key = XkbAddGeomKey(row); |
||||
if (!key) |
||||
return BadAlloc; |
||||
@@ -5400,7 +5421,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; |
||||
} |
||||
@@ -5409,7 +5430,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; |
||||
} |
||||
@@ -5443,6 +5464,9 @@ _CheckSetShapes(XkbGeometryPtr geom, |
||||
xkbOutlineWireDesc *olWire; |
||||
XkbOutlinePtr ol; |
||||
|
||||
+ if (!_XkbCheckRequestBounds(client, req, shapeWire, shapeWire + 1)) |
||||
+ return BadLength; |
||||
+ |
||||
shape = |
||||
XkbAddGeomShape(geom, shapeWire->name, shapeWire->nOutlines); |
||||
if (!shape) |
||||
@@ -5453,12 +5477,18 @@ _CheckSetShapes(XkbGeometryPtr geom, |
||||
XkbPointPtr pt; |
||||
xkbPointWireDesc *ptWire; |
||||
|
||||
+ if (!_XkbCheckRequestBounds(client, req, olWire, olWire + 1)) |
||||
+ return BadLength; |
||||
+ |
||||
ol = XkbAddGeomOutline(shape, olWire->nPoints); |
||||
if (!ol) |
||||
return BadAlloc; |
||||
ol->corner_radius = olWire->cornerRadius; |
||||
ptWire = (xkbPointWireDesc *) &olWire[1]; |
||||
for (p = 0, pt = ol->points; p < olWire->nPoints; p++, pt++, ptWire++) { |
||||
+ if (!_XkbCheckRequestBounds(client, req, ptWire, ptWire + 1)) |
||||
+ return BadLength; |
||||
+ |
||||
pt->x = ptWire->x; |
||||
pt->y = ptWire->y; |
||||
if (client->swapped) { |
||||
@@ -5564,12 +5594,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; |
||||
-- |
||||
2.36.1 |
||||
|
@ -0,0 +1,82 @@
@@ -0,0 +1,82 @@
|
||||
From be6bcbfa3f388ca0705db8baf10fa5c2d29b7d36 Mon Sep 17 00:00:00 2001 |
||||
From: Peter Hutterer <peter.hutterer@who-t.net> |
||||
Date: Tue, 29 Nov 2022 13:55:32 +1000 |
||||
Subject: [PATCH xserver 4/7] Xi: disallow passive grabs with a detail > 255 |
||||
|
||||
The XKB protocol effectively prevents us from ever using keycodes above |
||||
255. For buttons it's theoretically possible but realistically too niche |
||||
to worry about. For all other passive grabs, the detail must be zero |
||||
anyway. |
||||
|
||||
This fixes an OOB write: |
||||
|
||||
ProcXIPassiveUngrabDevice() calls DeletePassiveGrabFromList with a |
||||
temporary grab struct which contains tempGrab->detail.exact = stuff->detail. |
||||
For matching existing grabs, DeleteDetailFromMask is called with the |
||||
stuff->detail value. This function creates a new mask with the one bit |
||||
representing stuff->detail cleared. |
||||
|
||||
However, the array size for the new mask is 8 * sizeof(CARD32) bits, |
||||
thus any detail above 255 results in an OOB array write. |
||||
|
||||
CVE-2022-46341, ZDI-CAN 19381 |
||||
|
||||
This vulnerability was discovered by: |
||||
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative |
||||
|
||||
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> |
||||
Acked-by: Olivier Fourdan <ofourdan@redhat.com> |
||||
--- |
||||
Xi/xipassivegrab.c | 22 ++++++++++++++-------- |
||||
1 file changed, 14 insertions(+), 8 deletions(-) |
||||
|
||||
diff --git a/Xi/xipassivegrab.c b/Xi/xipassivegrab.c |
||||
index 2769fb7c94..c9ac2f8553 100644 |
||||
--- a/Xi/xipassivegrab.c |
||||
+++ b/Xi/xipassivegrab.c |
||||
@@ -137,6 +137,12 @@ ProcXIPassiveGrabDevice(ClientPtr client) |
||||
return BadValue; |
||||
} |
||||
|
||||
+ /* XI2 allows 32-bit keycodes but thanks to XKB we can never |
||||
+ * implement this. Just return an error for all keycodes that |
||||
+ * cannot work anyway, same for buttons > 255. */ |
||||
+ if (stuff->detail > 255) |
||||
+ return XIAlreadyGrabbed; |
||||
+ |
||||
if (XICheckInvalidMaskBits(client, (unsigned char *) &stuff[1], |
||||
stuff->mask_len * 4) != Success) |
||||
return BadValue; |
||||
@@ -207,14 +213,8 @@ ProcXIPassiveGrabDevice(ClientPtr client) |
||||
¶m, XI2, &mask); |
||||
break; |
||||
case XIGrabtypeKeycode: |
||||
- /* XI2 allows 32-bit keycodes but thanks to XKB we can never |
||||
- * implement this. Just return an error for all keycodes that |
||||
- * cannot work anyway */ |
||||
- if (stuff->detail > 255) |
||||
- status = XIAlreadyGrabbed; |
||||
- else |
||||
- status = GrabKey(client, dev, mod_dev, stuff->detail, |
||||
- ¶m, XI2, &mask); |
||||
+ status = GrabKey(client, dev, mod_dev, stuff->detail, |
||||
+ ¶m, XI2, &mask); |
||||
break; |
||||
case XIGrabtypeEnter: |
||||
case XIGrabtypeFocusIn: |
||||
@@ -334,6 +334,12 @@ ProcXIPassiveUngrabDevice(ClientPtr client) |
||||
return BadValue; |
||||
} |
||||
|
||||
+ /* We don't allow passive grabs for details > 255 anyway */ |
||||
+ if (stuff->detail > 255) { |
||||
+ client->errorValue = stuff->detail; |
||||
+ return BadValue; |
||||
+ } |
||||
+ |
||||
rc = dixLookupWindow(&win, stuff->grab_window, client, DixSetAttrAccess); |
||||
if (rc != Success) |
||||
return rc; |
||||
-- |
||||
2.38.1 |
||||
|
@ -0,0 +1,48 @@
@@ -0,0 +1,48 @@
|
||||
From 6b59bdddf30dde413c4e0391cf84f3b94d4b4e31 Mon Sep 17 00:00:00 2001 |
||||
From: Peter Hutterer <peter.hutterer@who-t.net> |
||||
Date: Tue, 29 Nov 2022 14:53:07 +1000 |
||||
Subject: [PATCH xserver 5/7] Xext: free the screen saver resource when |
||||
replacing it |
||||
|
||||
This fixes a use-after-free bug: |
||||
|
||||
When a client first calls ScreenSaverSetAttributes(), a struct |
||||
ScreenSaverAttrRec is allocated and added to the client's |
||||
resources. |
||||
|
||||
When the same client calls ScreenSaverSetAttributes() again, a new |
||||
struct ScreenSaverAttrRec is allocated, replacing the old struct. The |
||||
old struct was freed but not removed from the clients resources. |
||||
|
||||
Later, when the client is destroyed the resource system invokes |
||||
ScreenSaverFreeAttr and attempts to clean up the already freed struct. |
||||
|
||||
Fix this by letting the resource system free the old attrs instead. |
||||
|
||||
CVE-2022-46343, ZDI-CAN 19404 |
||||
|
||||
This vulnerability was discovered by: |
||||
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative |
||||
|
||||
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> |
||||
Acked-by: Olivier Fourdan <ofourdan@redhat.com> |
||||
--- |
||||
Xext/saver.c | 2 +- |
||||
1 file changed, 1 insertion(+), 1 deletion(-) |
||||
|
||||
diff --git a/Xext/saver.c b/Xext/saver.c |
||||
index f813ba08d1..fd6153c313 100644 |
||||
--- a/Xext/saver.c |
||||
+++ b/Xext/saver.c |
||||
@@ -1051,7 +1051,7 @@ ScreenSaverSetAttributes(ClientPtr client) |
||||
pVlist++; |
||||
} |
||||
if (pPriv->attr) |
||||
- FreeScreenAttr(pPriv->attr); |
||||
+ FreeResource(pPriv->attr->resource, AttrType); |
||||
pPriv->attr = pAttr; |
||||
pAttr->resource = FakeClientID(client->index); |
||||
if (!AddResource(pAttr->resource, AttrType, (void *) pAttr)) |
||||
-- |
||||
2.38.1 |
||||
|
@ -0,0 +1,74 @@
@@ -0,0 +1,74 @@
|
||||
From 40f06ae1bd12f4416df59382324a0d31ab2ba704 Mon Sep 17 00:00:00 2001 |
||||
From: Peter Hutterer <peter.hutterer@who-t.net> |
||||
Date: Wed, 30 Nov 2022 11:20:40 +1000 |
||||
Subject: [PATCH xserver 6/7] Xext: free the XvRTVideoNotify when turning off |
||||
from the same client |
||||
|
||||
This fixes a use-after-free bug: |
||||
|
||||
When a client first calls XvdiSelectVideoNotify() on a drawable with a |
||||
TRUE onoff argument, a struct XvVideoNotifyRec is allocated. This struct |
||||
is added twice to the resources: |
||||
- as the drawable's XvRTVideoNotifyList. This happens only once per |
||||
drawable, subsequent calls append to this list. |
||||
- as the client's XvRTVideoNotify. This happens for every client. |
||||
|
||||
The struct keeps the ClientPtr around once it has been added for a |
||||
client. The idea, presumably, is that if the client disconnects we can remove |
||||
all structs from the drawable's list that match the client (by resetting |
||||
the ClientPtr to NULL), but if the drawable is destroyed we can remove |
||||
and free the whole list. |
||||
|
||||
However, if the same client then calls XvdiSelectVideoNotify() on the |
||||
same drawable with a FALSE onoff argument, only the ClientPtr on the |
||||
existing struct was set to NULL. The struct itself remained in the |
||||
client's resources. |
||||
|
||||
If the drawable is now destroyed, the resource system invokes |
||||
XvdiDestroyVideoNotifyList which frees the whole list for this drawable |
||||
- including our struct. This function however does not free the resource |
||||
for the client since our ClientPtr is NULL. |
||||
|
||||
Later, when the client is destroyed and the resource system invokes |
||||
XvdiDestroyVideoNotify, we unconditionally set the ClientPtr to NULL. On |
||||
a struct that has been freed previously. This is generally frowned upon. |
||||
|
||||
Fix this by calling FreeResource() on the second call instead of merely |
||||
setting the ClientPtr to NULL. This removes the struct from the client |
||||
resources (but not from the list), ensuring that it won't be accessed |
||||
again when the client quits. |
||||
|
||||
Note that the assignment tpn->client = NULL; is superfluous since the |
||||
XvdiDestroyVideoNotify function will do this anyway. But it's left for |
||||
clarity and to match a similar invocation in XvdiSelectPortNotify. |
||||
|
||||
CVE-2022-46342, ZDI-CAN 19400 |
||||
|
||||
This vulnerability was discovered by: |
||||
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative |
||||
|
||||
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> |
||||
Acked-by: Olivier Fourdan <ofourdan@redhat.com> |
||||
--- |
||||
Xext/xvmain.c | 4 +++- |
||||
1 file changed, 3 insertions(+), 1 deletion(-) |
||||
|
||||
diff --git a/Xext/xvmain.c b/Xext/xvmain.c |
||||
index f627471938..2a08f8744a 100644 |
||||
--- a/Xext/xvmain.c |
||||
+++ b/Xext/xvmain.c |
||||
@@ -811,8 +811,10 @@ XvdiSelectVideoNotify(ClientPtr client, DrawablePtr pDraw, BOOL onoff) |
||||
tpn = pn; |
||||
while (tpn) { |
||||
if (tpn->client == client) { |
||||
- if (!onoff) |
||||
+ if (!onoff) { |
||||
tpn->client = NULL; |
||||
+ FreeResource(tpn->id, XvRTVideoNotify); |
||||
+ } |
||||
return Success; |
||||
} |
||||
if (!tpn->client) |
||||
-- |
||||
2.38.1 |
||||
|
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
From 9c70f90b24ba5de5eeb8a854c25f72a38d497fb7 Mon Sep 17 00:00:00 2001 |
||||
From: Peter Hutterer <peter.hutterer@who-t.net> |
||||
Date: Mon, 5 Dec 2022 15:55:54 +1000 |
||||
Subject: [PATCH xserver 7/7] xkb: reset the radio_groups pointer to NULL after |
||||
freeing it |
||||
|
||||
Unlike other elements of the keymap, this pointer was freed but not |
||||
reset. On a subsequent XkbGetKbdByName request, the server may access |
||||
already freed memory. |
||||
|
||||
CVE-2022-46283, ZDI-CAN-19530 |
||||
|
||||
This vulnerability was discovered by: |
||||
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative |
||||
|
||||
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> |
||||
Acked-by: Olivier Fourdan <ofourdan@redhat.com> |
||||
--- |
||||
xkb/xkbUtils.c | 1 + |
||||
1 file changed, 1 insertion(+) |
||||
|
||||
diff --git a/xkb/xkbUtils.c b/xkb/xkbUtils.c |
||||
index dd089c2046..3f5791a183 100644 |
||||
--- a/xkb/xkbUtils.c |
||||
+++ b/xkb/xkbUtils.c |
||||
@@ -1326,6 +1326,7 @@ _XkbCopyNames(XkbDescPtr src, XkbDescPtr dst) |
||||
} |
||||
else { |
||||
free(dst->names->radio_groups); |
||||
+ dst->names->radio_groups = NULL; |
||||
} |
||||
dst->names->num_rg = src->names->num_rg; |
||||
|
||||
-- |
||||
2.38.1 |
||||
|
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
From bb1711b7fba42f2a0c7d1c09beee241a1b2bcc30 Mon Sep 17 00:00:00 2001 |
||||
From: Peter Hutterer <peter.hutterer@who-t.net> |
||||
Date: Mon, 19 Dec 2022 10:06:45 +1000 |
||||
Subject: [PATCH xserver] Xext: fix invalid event type mask in |
||||
XTestSwapFakeInput |
||||
|
||||
In commit b320ca0 the mask was inadvertently changed from octal 0177 to |
||||
hexadecimal 0x177. |
||||
|
||||
Fixes commit b320ca0ffe4c0c872eeb3a93d9bde21f765c7c63 |
||||
Xtest: disallow GenericEvents in XTestSwapFakeInput |
||||
|
||||
Found by Stuart Cassoff |
||||
|
||||
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> |
||||
--- |
||||
Xext/xtest.c | 2 +- |
||||
1 file changed, 1 insertion(+), 1 deletion(-) |
||||
|
||||
diff --git a/Xext/xtest.c b/Xext/xtest.c |
||||
index 2985a4ce6e..dde5c4cf9d 100644 |
||||
--- a/Xext/xtest.c |
||||
+++ b/Xext/xtest.c |
||||
@@ -502,7 +502,7 @@ XTestSwapFakeInput(ClientPtr client, xReq * req) |
||||
|
||||
nev = ((req->length << 2) - sizeof(xReq)) / sizeof(xEvent); |
||||
for (ev = (xEvent *) &req[1]; --nev >= 0; ev++) { |
||||
- int evtype = ev->u.u.type & 0x177; |
||||
+ int evtype = ev->u.u.type & 0177; |
||||
/* Swap event */ |
||||
proc = EventSwapVector[evtype]; |
||||
/* no swapping proc; invalid event type? */ |
||||
-- |
||||
2.38.1 |
||||
|
Loading…
Reference in new issue