diff options
Diffstat (limited to 'patches/source/xorg-server/patch')
12 files changed, 963 insertions, 0 deletions
diff --git a/patches/source/xorg-server/patch/xorg-server.patch b/patches/source/xorg-server/patch/xorg-server.patch new file mode 100644 index 000000000..52169835e --- /dev/null +++ b/patches/source/xorg-server/patch/xorg-server.patch @@ -0,0 +1,35 @@ +# We've used this one forever. +zcat $CWD/patch/xorg-server/x11.startwithblackscreen.diff.gz | patch -p1 --verbose || { touch ${SLACK_X_BUILD_DIR}/${PKGNAME}.failed ; continue ; } + +# Without this patch, combo mouse/keyboard (such as Logitech through unified +# receiver) may be unable to set the desired keyboard layout. +zcat $CWD/patch/xorg-server/xorg-server.combo.mouse.keyboard.layout.patch.gz | patch -p1 --verbose || { touch ${SLACK_X_BUILD_DIR}/${PKGNAME}.failed ; continue ; } + +# Fix a segfault in xorg-server-1.20.0. Odds are good this will be fixed in +# the next xorg-server and will no longer apply then. +zcat $CWD/patch/xorg-server/fix-nouveau-segfault.diff.gz | patch -p1 --verbose || { touch ${SLACK_X_BUILD_DIR}/${PKGNAME}.failed ; continue ; } + +# From Fedora Rawhide 2018/7 (possibly useful, doesn't seem like it will hurt anything): +zcat $CWD/patch/xorg-server/0001-Always-install-vbe-and-int10-sdk-headers.patch.gz | patch -p1 --verbose || { touch ${SLACK_X_BUILD_DIR}/${PKGNAME}.failed ; continue ; } + +# From Fedora Rawhide 2018/7, looks like many other distributions have added +# this patch for a long time. Keep an eye out for newer versions though, and +# revisit this if any DE begin to manage secondary GPUs (although none do yet): +zcat $CWD/patch/xorg-server/0001-autobind-GPUs-to-the-screen.patch.gz | patch -p1 --verbose || { touch ${SLACK_X_BUILD_DIR}/${PKGNAME}.failed ; continue ; } + +# The upstream nouveau developers recommend this. On newer nvidia cards it works +# better to use the generic modesetting ddx rather than nouveau. +# Reference: https://bugs.freedesktop.org/show_bug.cgi?id=94844 +# Added here 2018/7. +zcat $CWD/patch/xorg-server/0001-xfree86-use-modesetting-driver-by-default-on-GeForce.patch.gz | patch -p1 --verbose || { touch ${SLACK_X_BUILD_DIR}/${PKGNAME}.failed ; continue ; } + +# Fix a PCI related segfault: +zcat $CWD/patch/xorg-server/fix-pci-segfault.diff.gz | patch -p1 --verbose || { touch ${SLACK_X_BUILD_DIR}/${PKGNAME}.failed ; continue ; } + +# Only use Intel DDX with pre-gen4 hardware. Newer hardware will the the modesetting driver by default: +zcat $CWD/patch/xorg-server/06_use-intel-only-on-pre-gen4.diff.gz | patch -p1 --verbose || { touch ${SLACK_X_BUILD_DIR}/${PKGNAME}.failed ; continue ; } + +# Patch CVE-2022-2320 and CVE-2022-2319: +zcat $CWD/patch/xorg-server/0001-f1070c01d616c5f21f939d5ebc533738779451ac.patch.gz | patch -p1 --verbose || { touch ${SLACK_X_BUILD_DIR}/${PKGNAME}.failed ; continue ; } +zcat $CWD/patch/xorg-server/0002-dd8caf39e9e15d8f302e54045dd08d8ebf1025dc.patch.gz | patch -p1 --verbose || { touch ${SLACK_X_BUILD_DIR}/${PKGNAME}.failed ; continue ; } +zcat $CWD/patch/xorg-server/0003-6907b6ea2b4ce949cb07271f5b678d5966d9df42.patch.gz | patch -p1 --verbose || { touch ${SLACK_X_BUILD_DIR}/${PKGNAME}.failed ; continue ; } diff --git a/patches/source/xorg-server/patch/xorg-server/0001-Always-install-vbe-and-int10-sdk-headers.patch b/patches/source/xorg-server/patch/xorg-server/0001-Always-install-vbe-and-int10-sdk-headers.patch new file mode 100644 index 000000000..c613eb8f9 --- /dev/null +++ b/patches/source/xorg-server/patch/xorg-server/0001-Always-install-vbe-and-int10-sdk-headers.patch @@ -0,0 +1,37 @@ +From e96a83d9b1b5a52a41213c7a4840dc96b4f5b06f Mon Sep 17 00:00:00 2001 +From: Adam Jackson <ajax@redhat.com> +Date: Wed, 15 Aug 2012 12:35:21 -0400 +Subject: [PATCH] Always install vbe and int10 sdk headers + +Signed-off-by: Adam Jackson <ajax@redhat.com> +--- + hw/xfree86/Makefile.am | 12 ++---------- + 1 file changed, 2 insertions(+), 10 deletions(-) + +diff --git a/hw/xfree86/Makefile.am b/hw/xfree86/Makefile.am +index b876b79..a170b58 100644 +--- a/hw/xfree86/Makefile.am ++++ b/hw/xfree86/Makefile.am +@@ -26,17 +26,9 @@ if VGAHW + VGAHW_SUBDIR = vgahw + endif + +-if VBE +-VBE_SUBDIR = vbe +-endif +- +-if INT10MODULE +-INT10_SUBDIR = int10 +-endif +- +-SUBDIRS = common ddc x86emu $(INT10_SUBDIR) os-support parser \ ++SUBDIRS = common ddc x86emu int10 os-support parser \ + ramdac $(VGAHW_SUBDIR) loader modes $(DRI_SUBDIR) \ +- $(DRI2_SUBDIR) . $(VBE_SUBDIR) i2c dixmods xkb \ ++ $(DRI2_SUBDIR) . vbe i2c dixmods xkb \ + fbdevhw shadowfb exa $(XF86UTILS_SUBDIR) doc man \ + $(GLAMOR_EGL_SUBDIR) drivers + +-- +2.13.6 + diff --git a/patches/source/xorg-server/patch/xorg-server/0001-autobind-GPUs-to-the-screen.patch b/patches/source/xorg-server/patch/xorg-server/0001-autobind-GPUs-to-the-screen.patch new file mode 100644 index 000000000..86b96a23e --- /dev/null +++ b/patches/source/xorg-server/patch/xorg-server/0001-autobind-GPUs-to-the-screen.patch @@ -0,0 +1,293 @@ +From 471289fa1dc359555ceed6302f7d9605ab6be3ea Mon Sep 17 00:00:00 2001 +From: Dave Airlie <airlied@redhat.com> +Date: Mon, 2 Apr 2018 16:49:02 -0400 +Subject: [PATCH] autobind GPUs to the screen + +This is a modified version of a patch we've been carry-ing in Fedora and +RHEL for years now. This patch automatically adds secondary GPUs to the +master as output sink / offload source making e.g. the use of +slave-outputs just work, with requiring the user to manually run +"xrandr --setprovideroutputsource" before he can hookup an external +monitor to his hybrid graphics laptop. + +There is one problem with this patch, which is why it was not upstreamed +before. What to do when a secondary GPU gets detected really is a policy +decission (e.g. one may want to autobind PCI GPUs but not USB ones) and +as such should be under control of the Desktop Environment. + +Unconditionally adding autobinding support to the xserver will result +in races between the DE dealing with the hotplug of a secondary GPU +and the server itself dealing with it. + +However we've waited for years for any Desktop Environments to actually +start doing some sort of autoconfiguration of secondary GPUs and there +is still not a single DE dealing with this, so I believe that it is +time to upstream this now. + +To avoid potential future problems if any DEs get support for doing +secondary GPU configuration themselves, the new autobind functionality +is made optional. Since no DEs currently support doing this themselves it +is enabled by default. When DEs grow support for doing this themselves +they can disable the servers autobinding through the servers cmdline or a +xorg.conf snippet. + +Signed-off-by: Dave Airlie <airlied@gmail.com> +[hdegoede@redhat.com: Make configurable, fix with nvidia, submit upstream] +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + hw/xfree86/common/xf86Config.c | 19 +++++++++++++++++++ + hw/xfree86/common/xf86Globals.c | 2 ++ + hw/xfree86/common/xf86Init.c | 20 ++++++++++++++++++++ + hw/xfree86/common/xf86Priv.h | 1 + + hw/xfree86/common/xf86Privstr.h | 1 + + hw/xfree86/common/xf86platformBus.c | 4 ++++ + hw/xfree86/man/Xorg.man | 7 +++++++ + hw/xfree86/man/xorg.conf.man | 6 ++++++ + randr/randrstr.h | 3 +++ + randr/rrprovider.c | 22 ++++++++++++++++++++++ + 10 files changed, 85 insertions(+) + +diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c +index 2c1d335..d7d7c2e 100644 +--- a/hw/xfree86/common/xf86Config.c ++++ b/hw/xfree86/common/xf86Config.c +@@ -643,6 +643,7 @@ typedef enum { + FLAG_DRI2, + FLAG_USE_SIGIO, + FLAG_AUTO_ADD_GPU, ++ FLAG_AUTO_BIND_GPU, + FLAG_MAX_CLIENTS, + FLAG_IGLX, + FLAG_DEBUG, +@@ -699,6 +700,8 @@ static OptionInfoRec FlagOptions[] = { + {0}, FALSE}, + {FLAG_AUTO_ADD_GPU, "AutoAddGPU", OPTV_BOOLEAN, + {0}, FALSE}, ++ {FLAG_AUTO_BIND_GPU, "AutoBindGPU", OPTV_BOOLEAN, ++ {0}, FALSE}, + {FLAG_MAX_CLIENTS, "MaxClients", OPTV_INTEGER, + {0}, FALSE }, + {FLAG_IGLX, "IndirectGLX", OPTV_BOOLEAN, +@@ -779,6 +782,22 @@ configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts) + } + xf86Msg(from, "%sutomatically adding GPU devices\n", + xf86Info.autoAddGPU ? "A" : "Not a"); ++ ++ if (xf86AutoBindGPUDisabled) { ++ xf86Info.autoBindGPU = FALSE; ++ from = X_CMDLINE; ++ } ++ else if (xf86IsOptionSet(FlagOptions, FLAG_AUTO_BIND_GPU)) { ++ xf86GetOptValBool(FlagOptions, FLAG_AUTO_BIND_GPU, ++ &xf86Info.autoBindGPU); ++ from = X_CONFIG; ++ } ++ else { ++ from = X_DEFAULT; ++ } ++ xf86Msg(from, "%sutomatically binding GPU devices\n", ++ xf86Info.autoBindGPU ? "A" : "Not a"); ++ + /* + * Set things up based on the config file information. Some of these + * settings may be overridden later when the command line options are +diff --git a/hw/xfree86/common/xf86Globals.c b/hw/xfree86/common/xf86Globals.c +index e890f05..7b27b4c 100644 +--- a/hw/xfree86/common/xf86Globals.c ++++ b/hw/xfree86/common/xf86Globals.c +@@ -131,6 +131,7 @@ xf86InfoRec xf86Info = { + #else + .autoAddGPU = FALSE, + #endif ++ .autoBindGPU = TRUE, + }; + + const char *xf86ConfigFile = NULL; +@@ -191,6 +192,7 @@ Bool xf86FlipPixels = FALSE; + Gamma xf86Gamma = { 0.0, 0.0, 0.0 }; + + Bool xf86AllowMouseOpenFail = FALSE; ++Bool xf86AutoBindGPUDisabled = FALSE; + + #ifdef XF86VIDMODE + Bool xf86VidModeDisabled = FALSE; +diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c +index ea42ec9..ec255b6 100644 +--- a/hw/xfree86/common/xf86Init.c ++++ b/hw/xfree86/common/xf86Init.c +@@ -76,6 +76,7 @@ + #include "xf86DDC.h" + #include "xf86Xinput.h" + #include "xf86InPriv.h" ++#include "xf86Crtc.h" + #include "picturestr.h" + #include "randrstr.h" + #include "glxvndabi.h" +@@ -237,6 +238,19 @@ xf86PrivsElevated(void) + return PrivsElevated(); + } + ++static void ++xf86AutoConfigOutputDevices(void) ++{ ++ int i; ++ ++ if (!xf86Info.autoBindGPU) ++ return; ++ ++ for (i = 0; i < xf86NumGPUScreens; i++) ++ RRProviderAutoConfigGpuScreen(xf86ScrnToScreen(xf86GPUScreens[i]), ++ xf86ScrnToScreen(xf86Screens[0])); ++} ++ + static void + TrapSignals(void) + { +@@ -770,6 +784,8 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv) + for (i = 0; i < xf86NumGPUScreens; i++) + AttachUnboundGPU(xf86Screens[0]->pScreen, xf86GPUScreens[i]->pScreen); + ++ xf86AutoConfigOutputDevices(); ++ + xf86VGAarbiterWrapFunctions(); + if (sigio_blocked) + input_unlock(); +@@ -1278,6 +1294,10 @@ ddxProcessArgument(int argc, char **argv, int i) + xf86Info.iglxFrom = X_CMDLINE; + return 0; + } ++ if (!strcmp(argv[i], "-noautoBindGPU")) { ++ xf86AutoBindGPUDisabled = TRUE; ++ return 1; ++ } + + /* OS-specific processing */ + return xf86ProcessArgument(argc, argv, i); +diff --git a/hw/xfree86/common/xf86Priv.h b/hw/xfree86/common/xf86Priv.h +index 4fe2b5f..6566622 100644 +--- a/hw/xfree86/common/xf86Priv.h ++++ b/hw/xfree86/common/xf86Priv.h +@@ -46,6 +46,7 @@ + extern _X_EXPORT const char *xf86ConfigFile; + extern _X_EXPORT const char *xf86ConfigDir; + extern _X_EXPORT Bool xf86AllowMouseOpenFail; ++extern _X_EXPORT Bool xf86AutoBindGPUDisabled; + + #ifdef XF86VIDMODE + extern _X_EXPORT Bool xf86VidModeDisabled; +diff --git a/hw/xfree86/common/xf86Privstr.h b/hw/xfree86/common/xf86Privstr.h +index 21c2e1f..6c71863 100644 +--- a/hw/xfree86/common/xf86Privstr.h ++++ b/hw/xfree86/common/xf86Privstr.h +@@ -98,6 +98,7 @@ typedef struct { + + Bool autoAddGPU; + const char *debug; ++ Bool autoBindGPU; + } xf86InfoRec, *xf86InfoPtr; + + /* ISC's cc can't handle ~ of UL constants, so explicitly type cast them. */ +diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c +index cef47da..913a324 100644 +--- a/hw/xfree86/common/xf86platformBus.c ++++ b/hw/xfree86/common/xf86platformBus.c +@@ -49,6 +49,7 @@ + #include "Pci.h" + #include "xf86platformBus.h" + #include "xf86Config.h" ++#include "xf86Crtc.h" + + #include "randrstr.h" + int platformSlotClaimed; +@@ -665,6 +666,9 @@ xf86platformAddDevice(int index) + } + /* attach unbound to 0 protocol screen */ + AttachUnboundGPU(xf86Screens[0]->pScreen, xf86GPUScreens[i]->pScreen); ++ if (xf86Info.autoBindGPU) ++ RRProviderAutoConfigGpuScreen(xf86ScrnToScreen(xf86GPUScreens[i]), ++ xf86ScrnToScreen(xf86Screens[0])); + + RRResourcesChanged(xf86Screens[0]->pScreen); + RRTellChanged(xf86Screens[0]->pScreen); +diff --git a/hw/xfree86/man/Xorg.man b/hw/xfree86/man/Xorg.man +index 13a9dc3..745f986 100644 +--- a/hw/xfree86/man/Xorg.man ++++ b/hw/xfree86/man/Xorg.man +@@ -283,6 +283,13 @@ is a comma separated list of directories to search for + server modules. This option is only available when the server is run + as root (i.e, with real-uid 0). + .TP 8 ++.B \-noautoBindGPU ++Disable automatically setting secondary GPUs up as output sinks and offload ++sources. This is equivalent to setting the ++.B AutoBindGPU ++xorg.conf(__filemansuffix__) file option. To ++.B false. ++.TP 8 + .B \-nosilk + Disable Silken Mouse support. + .TP 8 +diff --git a/hw/xfree86/man/xorg.conf.man b/hw/xfree86/man/xorg.conf.man +index 9589262..8d51e06 100644 +--- a/hw/xfree86/man/xorg.conf.man ++++ b/hw/xfree86/man/xorg.conf.man +@@ -672,6 +672,12 @@ Enabled by default. + If this option is disabled, then no GPU devices will be added from the udev + backend. Enabled by default. (May need to be disabled to setup Xinerama). + .TP 7 ++.BI "Option \*qAutoBindGPU\*q \*q" boolean \*q ++If enabled then secondary GPUs will be automatically set up as output-sinks and ++offload-sources. Making e.g. laptop outputs connected only to the secondary ++GPU directly available for use without needing to run ++"xrandr --setprovideroutputsource". Enabled by default. ++.TP 7 + .BI "Option \*qLog\*q \*q" string \*q + This option controls whether the log is flushed and/or synced to disk after + each message. +diff --git a/randr/randrstr.h b/randr/randrstr.h +index f94174b..092d726 100644 +--- a/randr/randrstr.h ++++ b/randr/randrstr.h +@@ -1039,6 +1039,9 @@ RRProviderLookup(XID id, RRProviderPtr *provider_p); + extern _X_EXPORT void + RRDeliverProviderEvent(ClientPtr client, WindowPtr pWin, RRProviderPtr provider); + ++extern _X_EXPORT void ++RRProviderAutoConfigGpuScreen(ScreenPtr pScreen, ScreenPtr masterScreen); ++ + /* rrproviderproperty.c */ + + extern _X_EXPORT void +diff --git a/randr/rrprovider.c b/randr/rrprovider.c +index e4bc2bf..e04c18f 100644 +--- a/randr/rrprovider.c ++++ b/randr/rrprovider.c +@@ -485,3 +485,25 @@ RRDeliverProviderEvent(ClientPtr client, WindowPtr pWin, RRProviderPtr provider) + + WriteEventsToClient(client, 1, (xEvent *) &pe); + } ++ ++void ++RRProviderAutoConfigGpuScreen(ScreenPtr pScreen, ScreenPtr masterScreen) ++{ ++ rrScrPrivPtr pScrPriv = rrGetScrPriv(pScreen); ++ rrScrPrivPtr masterPriv = rrGetScrPriv(masterScreen); ++ RRProviderPtr provider = pScrPriv->provider; ++ RRProviderPtr master_provider = masterPriv->provider; ++ ++ if (!provider || !master_provider) ++ return; ++ ++ if ((provider->capabilities & RR_Capability_SinkOutput) && ++ (master_provider->capabilities & RR_Capability_SourceOutput)) { ++ pScrPriv->rrProviderSetOutputSource(pScreen, provider, master_provider); ++ RRInitPrimeSyncProps(pScreen); ++ } ++ ++ if ((provider->capabilities & RR_Capability_SourceOffload) && ++ (master_provider->capabilities & RR_Capability_SinkOffload)) ++ pScrPriv->rrProviderSetOffloadSink(pScreen, provider, master_provider); ++} +-- +2.16.2 + diff --git a/patches/source/xorg-server/patch/xorg-server/0001-f1070c01d616c5f21f939d5ebc533738779451ac.patch b/patches/source/xorg-server/patch/xorg-server/0001-f1070c01d616c5f21f939d5ebc533738779451ac.patch new file mode 100644 index 000000000..0efddcf56 --- /dev/null +++ b/patches/source/xorg-server/patch/xorg-server/0001-f1070c01d616c5f21f939d5ebc533738779451ac.patch @@ -0,0 +1,75 @@ +From f1070c01d616c5f21f939d5ebc533738779451ac 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] 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> +--- + xkb/xkb.c | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +diff --git a/xkb/xkb.c b/xkb/xkb.c +index a29262c24..64e52611e 100644 +--- a/xkb/xkb.c ++++ b/xkb/xkb.c +@@ -5368,16 +5368,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); +@@ -5389,7 +5389,7 @@ _CheckSetSections(XkbGeometryPtr geom, + return BadMatch; + } + } +- rWire = (xkbRowWireDesc *) &kWire[rWire->nKeys]; ++ rWire = (xkbRowWireDesc *)kWire; + } + wire = (char *) rWire; + if (sWire->nDoodads > 0) { +@@ -5454,16 +5454,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]; +-- +GitLab + diff --git a/patches/source/xorg-server/patch/xorg-server/0001-xfree86-use-modesetting-driver-by-default-on-GeForce.patch b/patches/source/xorg-server/patch/xorg-server/0001-xfree86-use-modesetting-driver-by-default-on-GeForce.patch new file mode 100644 index 000000000..87b287796 --- /dev/null +++ b/patches/source/xorg-server/patch/xorg-server/0001-xfree86-use-modesetting-driver-by-default-on-GeForce.patch @@ -0,0 +1,47 @@ +From aa2f34d80ef3118eae0cce73b610c36cdcb978fe Mon Sep 17 00:00:00 2001 +From: Ben Skeggs <bskeggs@redhat.com> +Date: Sat, 22 Apr 2017 02:26:28 +1000 +Subject: [PATCH xserver] xfree86: use modesetting driver by default on GeForce + 8 and newer + +Signed-off-by: Ben Skeggs <bskeggs@redhat.com> +--- + hw/xfree86/common/xf86pciBus.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +--- ./hw/xfree86/common/xf86pciBus.c.orig 2019-02-26 13:28:50.000000000 -0600 ++++ ./hw/xfree86/common/xf86pciBus.c 2019-02-26 17:16:04.131096857 -0600 +@@ -37,6 +37,7 @@ + #include <unistd.h> + #include <X11/X.h> + #include <pciaccess.h> ++#include <xf86drm.h> + #include "os.h" + #include "Pci.h" + #include "xf86.h" +@@ -1191,6 +1192,25 @@ + int idx = 0; + + #if defined(__linux__) || defined(__NetBSD__) ++ char busid[32]; ++ int fd; ++ ++ snprintf(busid, sizeof(busid), "pci:%04x:%02x:%02x.%d", ++ dev->domain, dev->bus, dev->dev, dev->func); ++ ++ /* 'modesetting' is preferred for GeForce 8 and newer GPUs */ ++ fd = drmOpenWithType("nouveau", busid, DRM_NODE_RENDER); ++ if (fd >= 0) { ++ uint64_t args[] = { 11 /* NOUVEAU_GETPARAM_CHIPSET_ID */, 0 }; ++ int ret = drmCommandWriteRead(fd, 0 /* DRM_NOUVEAU_GETPARAM */, ++ &args, sizeof(args)); ++ drmClose(fd); ++ if (ret == 0) { ++ if (args[1] == 0x050 || args[1] >= 0x80) ++ break; ++ } ++ } ++ + driverList[idx++] = "nouveau"; + #endif + driverList[idx++] = "nv"; diff --git a/patches/source/xorg-server/patch/xorg-server/0002-dd8caf39e9e15d8f302e54045dd08d8ebf1025dc.patch b/patches/source/xorg-server/patch/xorg-server/0002-dd8caf39e9e15d8f302e54045dd08d8ebf1025dc.patch new file mode 100644 index 000000000..72d30f36b --- /dev/null +++ b/patches/source/xorg-server/patch/xorg-server/0002-dd8caf39e9e15d8f302e54045dd08d8ebf1025dc.patch @@ -0,0 +1,178 @@ +From dd8caf39e9e15d8f302e54045dd08d8ebf1025dc 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] 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> +--- + xkb/xkb.c | 46 +++++++++++++++++++++++++--------------------- + 1 file changed, 25 insertions(+), 21 deletions(-) + +diff --git a/xkb/xkb.c b/xkb/xkb.c +index 64e52611e..34b2c290b 100644 +--- a/xkb/xkb.c ++++ b/xkb/xkb.c +@@ -6550,7 +6550,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; +@@ -6558,6 +6559,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); +@@ -6585,6 +6591,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); + } +@@ -6596,6 +6607,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); +@@ -6647,11 +6662,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); +@@ -6670,10 +6680,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; +@@ -6691,10 +6697,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; +@@ -6730,13 +6732,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; +@@ -6747,13 +6753,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; + } +@@ -6764,8 +6770,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; +@@ -6789,8 +6795,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; +-- +GitLab + diff --git a/patches/source/xorg-server/patch/xorg-server/0003-6907b6ea2b4ce949cb07271f5b678d5966d9df42.patch b/patches/source/xorg-server/patch/xorg-server/0003-6907b6ea2b4ce949cb07271f5b678d5966d9df42.patch new file mode 100644 index 000000000..11121070b --- /dev/null +++ b/patches/source/xorg-server/patch/xorg-server/0003-6907b6ea2b4ce949cb07271f5b678d5966d9df42.patch @@ -0,0 +1,181 @@ +From 6907b6ea2b4ce949cb07271f5b678d5966d9df42 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] 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> +--- + xkb/xkb.c | 43 ++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 38 insertions(+), 5 deletions(-) + +diff --git a/xkb/xkb.c b/xkb/xkb.c +index 34b2c290b..4692895db 100644 +--- a/xkb/xkb.c ++++ b/xkb/xkb.c +@@ -5156,7 +5156,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; +@@ -5167,6 +5167,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) { +@@ -5269,7 +5272,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; +@@ -5280,6 +5283,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); + } +@@ -5291,6 +5297,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); +@@ -5299,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 +5344,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); +@@ -5357,6 +5372,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); +@@ -5371,6 +5389,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; +@@ -5396,7 +5417,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; + } +@@ -5405,7 +5426,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 +5460,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) +@@ -5449,12 +5473,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) { +@@ -5560,12 +5590,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; +-- +GitLab + diff --git a/patches/source/xorg-server/patch/xorg-server/06_use-intel-only-on-pre-gen4.diff b/patches/source/xorg-server/patch/xorg-server/06_use-intel-only-on-pre-gen4.diff new file mode 100644 index 000000000..4994492f6 --- /dev/null +++ b/patches/source/xorg-server/patch/xorg-server/06_use-intel-only-on-pre-gen4.diff @@ -0,0 +1,30 @@ +Description: Use intel ddx only on pre-gen4 hw, newer ones will fall back to modesetting +Author: Timo Aaltonen <tjaalton@debian.org> + +--- a/hw/xfree86/common/xf86pciBus.c ++++ b/hw/xfree86/common/xf86pciBus.c +@@ -1173,7 +1173,23 @@ xf86VideoPtrToDriverList(struct pci_devi + case 0x0bef: + /* Use fbdev/vesa driver on Oaktrail, Medfield, CDV */ + break; +- default: ++ /* Default to intel only on pre-gen4 chips */ ++ case 0x3577: ++ case 0x2562: ++ case 0x3582: ++ case 0x358e: ++ case 0x2572: ++ case 0x2582: ++ case 0x258a: ++ case 0x2592: ++ case 0x2772: ++ case 0x27a2: ++ case 0x27ae: ++ case 0x29b2: ++ case 0x29c2: ++ case 0x29d2: ++ case 0xa001: ++ case 0xa011: + driverList[0] = "intel"; + break; + } diff --git a/patches/source/xorg-server/patch/xorg-server/fix-nouveau-segfault.diff b/patches/source/xorg-server/patch/xorg-server/fix-nouveau-segfault.diff new file mode 100644 index 000000000..db66956f3 --- /dev/null +++ b/patches/source/xorg-server/patch/xorg-server/fix-nouveau-segfault.diff @@ -0,0 +1,12 @@ +--- ./render/mipict.c.orig 2018-05-10 11:32:37.000000000 -0500 ++++ ./render/mipict.c 2018-05-30 00:01:50.648530333 -0500 +@@ -394,6 +394,9 @@ + CARD32 r, g, b, a; + miIndexedPtr pIndexed; + ++ if(! format) ++ *pixel = (color->alpha >> 8 << 24) | (color->red >> 8 << 16) | (color->green & 0xff00) | (color->blue >> 8); ++ else + switch (format->type) { + case PictTypeDirect: + r = color->red >> (16 - Ones(format->direct.redMask)); diff --git a/patches/source/xorg-server/patch/xorg-server/fix-pci-segfault.diff b/patches/source/xorg-server/patch/xorg-server/fix-pci-segfault.diff new file mode 100644 index 000000000..400376287 --- /dev/null +++ b/patches/source/xorg-server/patch/xorg-server/fix-pci-segfault.diff @@ -0,0 +1,12 @@ +diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c +index cef47da03d0e91e6a56a5e3cb14a51d931633eff..dadbac6c8f0ae6f3d636fdfe245e61bc0c98581d 100644 +--- a/hw/xfree86/common/xf86platformBus.c ++++ b/hw/xfree86/common/xf86platformBus.c +@@ -289,7 +289,7 @@ xf86platformProbe(void) + for (i = 0; i < xf86_num_platform_devices; i++) { + char *busid = xf86_platform_odev_attributes(i)->busid; + +- if (pci && (strncmp(busid, "pci:", 4) == 0)) { ++ if (pci && busid && (strncmp(busid, "pci:", 4) == 0)) { + platform_find_pci_info(&xf86_platform_devices[i], busid); + } diff --git a/patches/source/xorg-server/patch/xorg-server/x11.startwithblackscreen.diff b/patches/source/xorg-server/patch/xorg-server/x11.startwithblackscreen.diff new file mode 100644 index 000000000..8c0e3b546 --- /dev/null +++ b/patches/source/xorg-server/patch/xorg-server/x11.startwithblackscreen.diff @@ -0,0 +1,14 @@ +diff -Nur xorg-server-1.12.1.orig/dix/window.c xorg-server-1.12.1/dix/window.c +--- xorg-server-1.12.1.orig/dix/window.c 2012-03-29 21:57:25.000000000 -0500 ++++ xorg-server-1.12.1/dix/window.c 2012-04-13 22:01:24.456073603 -0500 +@@ -145,8 +145,8 @@ + + Bool bgNoneRoot = FALSE; + +-static unsigned char _back_lsb[4] = { 0x88, 0x22, 0x44, 0x11 }; +-static unsigned char _back_msb[4] = { 0x11, 0x44, 0x22, 0x88 }; ++static unsigned char _back_lsb[4] = { 0x00, 0x00, 0x00, 0x00 }; ++static unsigned char _back_msb[4] = { 0x00, 0x00, 0x00, 0x00 }; + + static Bool WindowParentHasDeviceCursor(WindowPtr pWin, + DeviceIntPtr pDev, CursorPtr pCurs); diff --git a/patches/source/xorg-server/patch/xorg-server/xorg-server.combo.mouse.keyboard.layout.patch b/patches/source/xorg-server/patch/xorg-server/xorg-server.combo.mouse.keyboard.layout.patch new file mode 100644 index 000000000..83f673030 --- /dev/null +++ b/patches/source/xorg-server/patch/xorg-server/xorg-server.combo.mouse.keyboard.layout.patch @@ -0,0 +1,49 @@ +--- b/Xi/exevents.c 2013-12-27 19:38:52.000000000 +0200 ++++ a/Xi/exevents.c 2014-03-04 19:44:15.228721619 +0200 +@@ -665,7 +665,8 @@ + DeepCopyFeedbackClasses(from, to); + + if ((dce->flags & DEVCHANGE_KEYBOARD_EVENT)) +- DeepCopyKeyboardClasses(from, to); ++ /* We need to copy to MASTER_KEYBOARD. Didn't worked with 'to'. */ ++ DeepCopyKeyboardClasses(from, GetMaster(from, MASTER_KEYBOARD)); + if ((dce->flags & DEVCHANGE_POINTER_EVENT)) + DeepCopyPointerClasses(from, to); + } +--- b/dix/getevents.c 2013-12-27 19:38:52.000000000 +0200 ++++ a/dix/getevents.c 2014-03-04 19:46:50.126336327 +0200 +@@ -706,12 +706,19 @@ + { + DeviceIntPtr master; + +- master = +- GetMaster(dev, +- (type & DEVCHANGE_POINTER_EVENT) ? MASTER_POINTER : +- MASTER_KEYBOARD); ++ /* Don't guess the master upon the event type. Use MASTER_ATTACHED, ++ * otherwise we'll never get a DeviceChangedEvent(reason:SlaveSwith). */ ++ master = GetMaster(dev, MASTER_ATTACHED); ++ /* Need to track the slave event type. Other we'le never get a ++ * DeviceChangedEvent(reason:SlaveSwith) for the 'keyboard' if the ++ * 'pointer' has been touched before. */ ++ int slave_type = (type & DEVCHANGE_KEYBOARD_EVENT) | ++ (type & DEVCHANGE_POINTER_EVENT); + +- if (master && master->last.slave != dev) { ++ if (master && ++ ((master->last.slave != dev) || ++ (master->last.slave == dev && master->last.slave_type != slave_type))) { ++ master->last.slave_type = slave_type; + CreateClassesChangedEvent(events, master, dev, + type | DEVCHANGE_SLAVE_SWITCH); + if (IsPointerDevice(master)) { +--- b/include/inputstr.h 2013-12-27 19:38:52.000000000 +0200 ++++ a/include/inputstr.h 2014-03-04 19:47:28.074051116 +0200 +@@ -577,6 +577,7 @@ + double valuators[MAX_VALUATORS]; + int numValuators; + DeviceIntPtr slave; ++ int slave_type; + ValuatorMask *scroll; + int num_touches; /* size of the touches array */ + DDXTouchPointInfoPtr touches; |