From 3fa480415b22a9a0bad6388bd24d62cfa3cb8090 Mon Sep 17 00:00:00 2001 From: Matthieu Herrb Date: Wed, 25 Oct 2023 05:16:41 +0000 Subject: Fix several input validation errors in the X server CVE-2023-5367 CVE-2023-5380 CVE-2023-5574 --- xserver/Xi/xiproperty.c | 4 ++-- xserver/dix/enterleave.h | 2 -- xserver/fb/fb.h | 1 + xserver/fb/fbscreen.c | 14 ++++++++++---- xserver/hw/vfb/InitOutput.c | 7 ------- xserver/include/eventstr.h | 3 +++ xserver/mi/mipointer.c | 17 +++++++++++++++-- xserver/mi/miscrinit.c | 2 +- xserver/randr/rrproperty.c | 4 ++-- 9 files changed, 34 insertions(+), 20 deletions(-) (limited to 'xserver') diff --git a/xserver/Xi/xiproperty.c b/xserver/Xi/xiproperty.c index 066ba21fb..d315f04d0 100644 --- a/xserver/Xi/xiproperty.c +++ b/xserver/Xi/xiproperty.c @@ -730,7 +730,7 @@ XIChangeDeviceProperty(DeviceIntPtr dev, Atom property, Atom type, XIDestroyDeviceProperty(prop); return BadAlloc; } - new_value.size = len; + new_value.size = total_len; new_value.type = type; new_value.format = format; @@ -747,7 +747,7 @@ XIChangeDeviceProperty(DeviceIntPtr dev, Atom property, Atom type, case PropModePrepend: new_data = new_value.data; old_data = (void *) (((char *) new_value.data) + - (prop_value->size * size_in_bytes)); + (len * size_in_bytes)); break; } if (new_data) diff --git a/xserver/dix/enterleave.h b/xserver/dix/enterleave.h index 4b833d8a3..e8af924c6 100644 --- a/xserver/dix/enterleave.h +++ b/xserver/dix/enterleave.h @@ -58,8 +58,6 @@ extern void DeviceFocusEvent(DeviceIntPtr dev, extern void EnterWindow(DeviceIntPtr dev, WindowPtr win, int mode); -extern void LeaveWindow(DeviceIntPtr dev); - extern void CoreFocusEvent(DeviceIntPtr kbd, int type, int mode, int detail, WindowPtr pWin); diff --git a/xserver/fb/fb.h b/xserver/fb/fb.h index 8ab050d0f..404bca3c9 100644 --- a/xserver/fb/fb.h +++ b/xserver/fb/fb.h @@ -410,6 +410,7 @@ typedef struct { #endif DevPrivateKeyRec gcPrivateKeyRec; DevPrivateKeyRec winPrivateKeyRec; + CloseScreenProcPtr CloseScreen; } FbScreenPrivRec, *FbScreenPrivPtr; #define fbGetScreenPrivate(pScreen) ((FbScreenPrivPtr) \ diff --git a/xserver/fb/fbscreen.c b/xserver/fb/fbscreen.c index 4ab807ab5..c481033f9 100644 --- a/xserver/fb/fbscreen.c +++ b/xserver/fb/fbscreen.c @@ -29,6 +29,7 @@ Bool fbCloseScreen(ScreenPtr pScreen) { + FbScreenPrivPtr screen_priv = fbGetScreenPrivate(pScreen); int d; DepthPtr depths = pScreen->allowedDepths; @@ -37,9 +38,10 @@ fbCloseScreen(ScreenPtr pScreen) free(depths[d].vids); free(depths); free(pScreen->visuals); - if (pScreen->devPrivate) - FreePixmap((PixmapPtr)pScreen->devPrivate); - return TRUE; + + pScreen->CloseScreen = screen_priv->CloseScreen; + + return pScreen->CloseScreen(pScreen); } Bool @@ -144,6 +146,7 @@ fbFinishScreenInit(ScreenPtr pScreen, void *pbits, int xsize, int ysize, int dpix, int dpiy, int width, int bpp) #endif { + FbScreenPrivPtr screen_priv; VisualPtr visuals; DepthPtr depths; int nvisuals; @@ -177,8 +180,11 @@ fbFinishScreenInit(ScreenPtr pScreen, void *pbits, int xsize, int ysize, rootdepth, ndepths, depths, defaultVisual, nvisuals, visuals)) return FALSE; - /* overwrite miCloseScreen with our own */ + + screen_priv = fbGetScreenPrivate(pScreen); + screen_priv->CloseScreen = pScreen->CloseScreen; pScreen->CloseScreen = fbCloseScreen; + return TRUE; } diff --git a/xserver/hw/vfb/InitOutput.c b/xserver/hw/vfb/InitOutput.c index 01e08cca0..08158fbbc 100644 --- a/xserver/hw/vfb/InitOutput.c +++ b/xserver/hw/vfb/InitOutput.c @@ -727,13 +727,6 @@ vfbCloseScreen(ScreenPtr pScreen) pScreen->CloseScreen = pvfb->closeScreen; - /* - * fb overwrites miCloseScreen, so do this here - */ - if (pScreen->devPrivate) - (*pScreen->DestroyPixmap) (pScreen->devPrivate); - pScreen->devPrivate = NULL; - return pScreen->CloseScreen(pScreen); } diff --git a/xserver/include/eventstr.h b/xserver/include/eventstr.h index 93308f9b2..a9926eaee 100644 --- a/xserver/include/eventstr.h +++ b/xserver/include/eventstr.h @@ -335,4 +335,7 @@ union _InternalEvent { GestureEvent gesture_event; }; +extern void +LeaveWindow(DeviceIntPtr dev); + #endif diff --git a/xserver/mi/mipointer.c b/xserver/mi/mipointer.c index a638f25d4..8cf003514 100644 --- a/xserver/mi/mipointer.c +++ b/xserver/mi/mipointer.c @@ -397,8 +397,21 @@ miPointerWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) #ifdef PANORAMIX && noPanoramiXExtension #endif - ) - UpdateSpriteForScreen(pDev, pScreen); + ) { + DeviceIntPtr master = GetMaster(pDev, MASTER_POINTER); + /* Hack for CVE-2023-5380: if we're moving + * screens PointerWindows[] keeps referring to the + * old window. If that gets destroyed we have a UAF + * bug later. Only happens when jumping from a window + * to the root window on the other screen. + * Enter/Leave events are incorrect for that case but + * too niche to fix. + */ + LeaveWindow(pDev); + if (master) + LeaveWindow(master); + UpdateSpriteForScreen(pDev, pScreen); + } } /** diff --git a/xserver/mi/miscrinit.c b/xserver/mi/miscrinit.c index 3bb52b1bc..b88938c9a 100644 --- a/xserver/mi/miscrinit.c +++ b/xserver/mi/miscrinit.c @@ -249,10 +249,10 @@ miScreenInit(ScreenPtr pScreen, void *pbits, /* pointer to screen bits */ pScreen->numVisuals = numVisuals; pScreen->visuals = visuals; if (width) { + pScreen->CloseScreen = miCloseScreen; #ifdef MITSHM ShmRegisterFbFuncs(pScreen); #endif - pScreen->CloseScreen = miCloseScreen; } /* else CloseScreen */ /* QueryBestSize */ diff --git a/xserver/randr/rrproperty.c b/xserver/randr/rrproperty.c index c2fb9585c..25469f57b 100644 --- a/xserver/randr/rrproperty.c +++ b/xserver/randr/rrproperty.c @@ -209,7 +209,7 @@ RRChangeOutputProperty(RROutputPtr output, Atom property, Atom type, RRDestroyOutputProperty(prop); return BadAlloc; } - new_value.size = len; + new_value.size = total_len; new_value.type = type; new_value.format = format; @@ -226,7 +226,7 @@ RRChangeOutputProperty(RROutputPtr output, Atom property, Atom type, case PropModePrepend: new_data = new_value.data; old_data = (void *) (((char *) new_value.data) + - (prop_value->size * size_in_bytes)); + (len * size_in_bytes)); break; } if (new_data) -- cgit v1.2.3