[PATCH v2] mi: don't process events from disabled devices (#77884)

Peter Hutterer peter.hutterer at who-t.net
Tue May 20 17:07:31 PDT 2014


Once a device is disabled, it doesn't have a sprite pointer anymore. If an
event is still in the queue and processed after DisableDevice finished, a
dereference causes a crash. Example backtrace (crash forced by injecting an
event at the right time):

(EE) 0: /opt/xorg/bin/Xorg (OsSigHandler+0x3c) [0x48d334]
(EE) 1: /lib64/libpthread.so.0 (__restore_rt+0x0) [0x37fcc0f74f]
(EE) 2: /opt/xorg/bin/Xorg (mieqMoveToNewScreen+0x38) [0x609240]
(EE) 3: /opt/xorg/bin/Xorg (mieqProcessDeviceEvent+0xd4) [0x609389]
(EE) 4: /opt/xorg/bin/Xorg (mieqProcessInputEvents+0x206) [0x609720]
(EE) 5: /opt/xorg/bin/Xorg (ProcessInputEvents+0xd) [0x4aeb58]
(EE) 6: /opt/xorg/bin/Xorg (xf86VTSwitch+0x1a6) [0x4af457]
(EE) 7: /opt/xorg/bin/Xorg (xf86Wakeup+0x2bf) [0x4af0a7]
(EE) 8: /opt/xorg/bin/Xorg (WakeupHandler+0x83) [0x4445cb]
(EE) 9: /opt/xorg/bin/Xorg (WaitForSomething+0x3fe) [0x491bf6]
(EE) 10: /opt/xorg/bin/Xorg (Dispatch+0x97) [0x435748]
(EE) 11: /opt/xorg/bin/Xorg (dix_main+0x61d) [0x4438a9]
(EE) 12: /opt/xorg/bin/Xorg (main+0x28) [0x49ba28]
(EE) 13: /lib64/libc.so.6 (__libc_start_main+0xf5) [0x37fc821d65]
(EE) 14: /opt/xorg/bin/Xorg (_start+0x29) [0x425e69]
(EE) 15: ? (?+0x29) [0x29]

xf86VTSwitch() calls ProcessInputEvents() before disabling a device, and
DisableDevice() calls mieqProcessInputEvents() again when flushing touches and
button events. Between that and disabling the device (which causes new events
to be refused) there is a window where events may be triggered and enqueued.
On the next call to PIE that event is processed on a now defunct device,
causing the crash.

The simplest fix to this is to discard events from disabled devices. We flush
the queue often enough before disabling that when we get here, we really don't
care about the events from this device.

X.Org Bug 77884 <http://bugs.freedesktop.org/show_bug.cgi?id=77884>

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
Reported-by: Maarten Lankhorst <maarten.lankhorst at canonical.com>
Tested-by: Maarten Lankhorst <maarten.lankhorst at canonical.com>
---
Changes to v1:
- fix test/input

 mi/mieq.c    |  4 ++++
 test/input.c | 14 +++++++++++++-
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/mi/mieq.c b/mi/mieq.c
index 4c07480..188a0b0 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -515,6 +515,10 @@ mieqProcessDeviceEvent(DeviceIntPtr dev, InternalEvent *event, ScreenPtr screen)
 
     verify_internal_event(event);
 
+    /* refuse events from disabled devices */
+    if (!dev->enabled)
+        return 0;
+
     /* Custom event handler */
     handler = miEventQueue.handlers[event->any.type];
 
diff --git a/test/input.c b/test/input.c
index df20f82..4603c60 100644
--- a/test/input.c
+++ b/test/input.c
@@ -1708,6 +1708,18 @@ mieq_test_event_handler(int screenNum, InternalEvent *ie, DeviceIntPtr dev)
 static void
 _mieq_test_generate_events(uint32_t start, uint32_t count)
 {
+    static DeviceIntRec dev;
+    static SpriteInfoRec spriteInfo;
+    static SpriteRec sprite;
+
+    memset(&dev, 0, sizeof(dev));
+    memset(&spriteInfo, 0, sizeof(spriteInfo));
+    memset(&sprite, 0, sizeof(sprite));
+    dev.spriteInfo = &spriteInfo;
+    spriteInfo.sprite = &sprite;
+
+    dev.enabled = 1;
+
     count += start;
     while (start < count) {
         RawDeviceEvent e = { 0 };
@@ -1717,7 +1729,7 @@ _mieq_test_generate_events(uint32_t start, uint32_t count)
         e.time = GetTimeInMillis();
         e.flags = start;
 
-        mieqEnqueue(NULL, (InternalEvent *) &e);
+        mieqEnqueue(&dev, (InternalEvent *) &e);
 
         start++;
     }
-- 
1.9.0



More information about the xorg-devel mailing list