| 1 | Date: Tue, 20 May 2014 14:32:59 +1000 |
| 2 | From: Peter Hutterer <peter.hutterer@who-t.net> |
| 3 | Subject: [PATCH] mi: don't process events from disabled devices (#77884) |
| 4 | |
| 5 | Once a device is disabled, it doesn't have a sprite pointer anymore. If an |
| 6 | event is still in the queue and processed after DisableDevice finished, a |
| 7 | dereference causes a crash. Example backtrace (crash forced by injecting an |
| 8 | event at the right time): |
| 9 | |
| 10 | (EE) 0: /opt/xorg/bin/Xorg (OsSigHandler+0x3c) [0x48d334] |
| 11 | (EE) 1: /lib64/libpthread.so.0 (__restore_rt+0x0) [0x37fcc0f74f] |
| 12 | (EE) 2: /opt/xorg/bin/Xorg (mieqMoveToNewScreen+0x38) [0x609240] |
| 13 | (EE) 3: /opt/xorg/bin/Xorg (mieqProcessDeviceEvent+0xd4) [0x609389] |
| 14 | (EE) 4: /opt/xorg/bin/Xorg (mieqProcessInputEvents+0x206) [0x609720] |
| 15 | (EE) 5: /opt/xorg/bin/Xorg (ProcessInputEvents+0xd) [0x4aeb58] |
| 16 | (EE) 6: /opt/xorg/bin/Xorg (xf86VTSwitch+0x1a6) [0x4af457] |
| 17 | (EE) 7: /opt/xorg/bin/Xorg (xf86Wakeup+0x2bf) [0x4af0a7] |
| 18 | (EE) 8: /opt/xorg/bin/Xorg (WakeupHandler+0x83) [0x4445cb] |
| 19 | (EE) 9: /opt/xorg/bin/Xorg (WaitForSomething+0x3fe) [0x491bf6] |
| 20 | (EE) 10: /opt/xorg/bin/Xorg (Dispatch+0x97) [0x435748] |
| 21 | (EE) 11: /opt/xorg/bin/Xorg (dix_main+0x61d) [0x4438a9] |
| 22 | (EE) 12: /opt/xorg/bin/Xorg (main+0x28) [0x49ba28] |
| 23 | (EE) 13: /lib64/libc.so.6 (__libc_start_main+0xf5) [0x37fc821d65] |
| 24 | (EE) 14: /opt/xorg/bin/Xorg (_start+0x29) [0x425e69] |
| 25 | (EE) 15: ? (?+0x29) [0x29] |
| 26 | |
| 27 | xf86VTSwitch() calls ProcessInputEvents() before disabling a device, and |
| 28 | DisableDevice() calls mieqProcessInputEvents() again when flushing touches and |
| 29 | button events. Between that and disabling the device (which causes new events |
| 30 | to be refused) there is a window where events may be triggered and enqueued. |
| 31 | On the next call to PIE that event is processed on a now defunct device, |
| 32 | causing the crash. |
| 33 | |
| 34 | The simplest fix to this is to discard events from disabled devices. We flush |
| 35 | the queue often enough before disabling that when we get here, we really don't |
| 36 | care about the events from this device. |
| 37 | |
| 38 | X.Org Bug 77884 <http://bugs.freedesktop.org/show_bug.cgi?id=77884> |
| 39 | --- |
| 40 | Modified by Maarten Lankhorst to pass tests. |
| 41 | |
| 42 | mi/mieq.c | 4 ++++ |
| 43 | 1 file changed, 4 insertions(+) |
| 44 | |
| 45 | --- a/mi/mieq.c |
| 46 | +++ b/mi/mieq.c |
| 47 | @@ -515,6 +515,10 @@ mieqProcessDeviceEvent(DeviceIntPtr dev, |
| 48 | |
| 49 | verify_internal_event(event); |
| 50 | |
| 51 | + /* refuse events from disabled devices */ |
| 52 | + if (dev && !dev->enabled) |
| 53 | + return 0; |
| 54 | + |
| 55 | /* Custom event handler */ |
| 56 | handler = miEventQueue.handlers[event->any.type]; |
| 57 | |