Bug 38313

Summary: xorg-server crashes on keyboard BTN events
Product: xorg Reporter: David Herrmann <dh.herrmann>
Component: Server/Input/CoreAssignee: Peter Hutterer <peter.hutterer>
Status: RESOLVED FIXED QA Contact: Xorg Project Team <xorg-team>
Severity: major    
Priority: medium CC: dgbaley27, freedesktop, peter.hutterer
Version: 7.6 (2010.12)Keywords: regression
Hardware: x86-64 (AMD64)   
OS: Linux (All)   
Whiteboard: 2011BRB_Reviewed
i915 platform: i915 features:
Bug Depends on:    
Bug Blocks: 40982    
Attachments:
Description Flags
Xorg.0.log
none
Xorg.0.log crash with evdev keyboard and mouse
none
0001-dix-don-t-XWarpPointer-through-the-last-slave-anymor.patch
none
0001-input-store-the-highest-valuator-in-DeviceEvents-and.patch
none
0002-mi-only-dequeue-the-current-screen-if-we-have-valuat.patch
none
Evemu device
none
Evemu record
none
cwiid config file none

Description David Herrmann 2011-06-14 12:34:20 UTC
Created attachment 47968 [details]
Xorg.0.log

I have a input device which reports BTN_1 and BTN_2 events (because it has a button labeled "1" and "2") via /dev/input/eventX.
If I now press BTN_1 followed by alt+tab to switch applications, then the x-server crashes with:

[344937.430] 
Backtrace:
[344937.430] 0: X (xorg_backtrace+0x26) [0x49f556]
[344937.431] 1: X (0x400000+0x60cf9) [0x460cf9]
[344937.431] 2: /lib/libpthread.so.0 (0x7fe800161000+0xf750) [0x7fe800170750]
[344937.431] 3: X (GetPointerEvents+0xc55) [0x442bf5]
[344937.431] 4: X (miPointerWarpCursor+0x130) [0x459030]
[344937.431] 5: X (0x400000+0x122111) [0x522111]
[344937.431] 6: X (0x400000+0x59582) [0x459582]
[344937.431] 7: X (0x400000+0x163a23) [0x563a23]
[344937.431] 8: X (ProcWarpPointer+0x422) [0x43ac92]
[344937.431] 9: X (0x400000+0x2e8d9) [0x42e8d9]
[344937.432] 10: X (0x400000+0x22b7e) [0x422b7e]
[344937.432] 11: /lib/libc.so.6 (__libc_start_main+0xed) [0x7fe7ff0e1f6d]
[344937.432] 12: X (0x400000+0x22e6d) [0x422e6d]
[344937.432] Segmentation fault at address 0x20
[344937.432] 
Fatal server error:
[344937.432] Caught signal 11 (Segmentation fault). Server aborting
[344937.432] 
[344937.432] 
Please consult the The X.Org Foundation support 
         at http://wiki.x.org
 for help. 
[344937.432] Please also check the log file at "/var/log/Xorg.1.log" for additional information.


I don't have a binary with debug symbols since my distro doesn't provide one, sadly...
One more thing:
The segfault occurs when switching applications, however, only if no other mouse-event is between the BTN_1 and window-switch. If I move then mouse or press another mouse button between BTN_1 and alt+tab, then the bug doesn't occur.


Regards 
David
Comment 1 David Herrmann 2011-06-14 12:42:01 UTC
I have narrowed it down. My device (The Nintendo Wiimote as listed in the xorg-log) has the following xorg-config:


Section "InputClass"
        Identifier "Nintendo Wiiremote Blacklist"
        MatchProduct "Nintendo Wii Remote"
        Option "IgnoreAbsoluteAxes" "true"
EndSection


If I remove the "IgnoreAbsoluteAxes" line, then the bug does not occur. So I think that some input-handling code tries to read absolute Axes on BTN_1 events although they are disabled.

Regards
David
Comment 2 Chris Humbert 2011-07-15 06:32:39 UTC
Created attachment 49149 [details]
Xorg.0.log crash with evdev keyboard and mouse

I'm encountering the same bug in the standard evdev keyboard and mouse configuration while playing ioquake3. Calling GetPointerEvents with pDev->valuator == NULL causes the crash. In my case, this happens sporadically within 1-30 minutes.

Program received signal SIGSEGV, Segmentation fault.
0x0000000000445c96 in GetPointerEvents (events=<value optimized out>, pDev=0x2993cb0, type=6, buttons=<value optimized out>, flags=16, mask_in=<value optimized out>) at ../../xorg-server-1.10.3/dix/getevents.c:1156
1156 scaled = rescaleValuatorAxis(valuator_mask_get(&mask, 0),
1157                              0.0, &x_frac, NULL,
1158                              pDev->valuator->axes + 0,
1159                              scr->width);

(gdb) backtrace
#0  0x0000000000445c96 in GetPointerEvents (events=<value optimized out>, pDev=0x2993cb0, type=6, buttons=<value optimized out>, flags=16, mask_in=<value optimized out>) at ../../xorg-server-1.10.3/dix/getevents.c:1156
#1  0x000000000045d41b in miPointerMove (pDev=0x2993cb0, pScreen=0x243a980, x=0, y=0) at ../../xorg-server-1.10.3/mi/mipointer.c:576
#2  miPointerWarpCursor (pDev=0x2993cb0, pScreen=0x243a980, x=0, y=0) at ../../xorg-server-1.10.3/mi/mipointer.c:310
#3  0x0000000000525e71 in xf86WarpCursor (pDev=0x2993cb0, pScreen=0x243a980, x=0, y=0) at ../../../../xorg-server-1.10.3/hw/xfree86/common/xf86Cursor.c:473
#4  0x000000000045dd3f in miPointerSetCursorPosition (pDev=0x2993cb0, pScreen=0x0, x=37988736, y=0, generateEvent=1) at ../../xorg-server-1.10.3/mi/mipointer.c:233
#5  0x00000000005679df in AnimCurSetCursorPosition (pDev=0x7fffe0127360, pScreen=0x243a980, x=37988736, y=0, generateEvent=0) at ../../xorg-server-1.10.3/render/animcur.c:261
#6  0x000000000043ab56 in CheckPhysLimits (pDev=0x2993cb0, cursor=<value optimized out>, generateEvents=1, confineToScreen=0, pScreen=0x0) at ../../xorg-server-1.10.3/dix/events.c:744
#7  0x000000000043b16d in NewCurrentScreen (pDev=0x2993cb0, newScreen=<value optimized out>, x=<value optimized out>, y=<value optimized out>) at ../../xorg-server-1.10.3/dix/events.c:3083
#8  0x000000000045b252 in mieqProcessDeviceEvent (dev=0x2993cb0, event=0x2a08690, screen=0x24a5e10) at ../../xorg-server-1.10.3/mi/mieq.c:394
#9  0x000000000045b320 in mieqProcessInputEvents () at ../../xorg-server-1.10.3/mi/mieq.c:481
#10 0x000000000046e9b9 in ProcessInputEvents () at ../../../../xorg-server-1.10.3/hw/xfree86/common/xf86Events.c:165
#11 0x0000000000431ae3 in Dispatch () at ../../xorg-server-1.10.3/dix/dispatch.c:363
#12 0x0000000000425b0a in main (argc=6, argv=0x7fffe0127fe8, envp=<value optimized out>) at ../../xorg-server-1.10.3/dix/main.c:287

(gdb) disas
=> 0x0000000000445c96 <+3062>:	mov    0x20(%rax),%r14

(gdb) i r rax
rax            0x0	0
Comment 3 Chris Humbert 2011-07-15 11:59:09 UTC
--- What's happening:

1. A pointer event moves the pointer outside of its confined area.
2. mieqProcessDeviceEvent starts processing a KeyPress event from a keyboard.
3. NewCurrentScreen determines the pointer is outside of its confined area.
4. miPointerMove warps the pointer back into its confined area, generating a
   MotionNotify event from the keyboard.
6. GetPointerEvents attempts to use the keyboard's NULL DeviceIntPtr->valuator
   to scale, transform, and clip the MotionNotify event.

--- What's the best way to fix this?

1. Check that the pointer is confined only after moving the pointer.
2. Check that the pointer is confined only during pointer events.
3. Only generate move events from pointer devices.
4. Ignore pointer events from non-pointer devices.
Comment 4 Peter Hutterer 2011-07-28 23:41:25 UTC
Created attachment 49702 [details] [review]
0001-dix-don-t-XWarpPointer-through-the-last-slave-anymor.patch

David: I believe this is the correct fix for your problem. Chris' problem is slightly different, needs a separate fix.
Comment 5 Peter Hutterer 2011-07-31 18:42:08 UTC
Created attachment 49765 [details] [review]
0001-input-store-the-highest-valuator-in-DeviceEvents-and.patch

patch required for the actual fix
Comment 6 Peter Hutterer 2011-07-31 18:44:00 UTC
Created attachment 49766 [details] [review]
0002-mi-only-dequeue-the-current-screen-if-we-have-valuat.patch

Events without valuators cannot change the screen. Check if the event does
actually include valuators before generating one to stop null-pointer dereferences.
Comment 7 Peter Hutterer 2011-09-01 20:34:06 UTC
(In reply to comment #4)
> Created an attachment (id=49702) [details]
> 0001-dix-don-t-XWarpPointer-through-the-last-slave-anymor.patch

this one is in my -next branch, will be upstream soon.

Chris, for your issue see the thread here: http://lists.freedesktop.org/archives/xorg-devel/2011-September/024801.html
Comment 8 Jeremy Huddleston Sequoia 2011-11-03 02:00:06 UTC
This introduces a regression:

http://xquartz.macosforge.org/trac/ticket/517#comment:10
Comment 9 Jeremy Huddleston Sequoia 2011-11-03 22:52:09 UTC
This change has been reverted from the 1.11 branch.

This change still exists in master and should be fixed or reverted before 1.12 is released.  Marking as a 1.12 blocker.
Comment 10 Matthew Monaco 2012-02-20 12:49:59 UTC
I'm unclear as to which patches are supposed to fix the issue. Is it all 3? Or just the latter of the 0001 and then 0002?

I'm currently running xorg 1.11.99.903 and evdev 2.6.99.901. The server picks up the main device from the hid-wiimote module which it considers a keyboard, but it has a mouse button. If I press it, the server crashes.

If instead I ignore those devices and use a userspace translator, the x server gets a device through uinput. If the uninput device has an axis and mouse button, no crash. If I disable the axis I get a crash when I press the mouse button. (the log still shows it is a keyboard and as a mouse even when the axis is disabled).
Comment 11 Peter Hutterer 2012-02-20 20:37:29 UTC
Please get evemu and record the device plus the event that makes the server crash, then attach both files here. Thanks.
Comment 12 Matthew Monaco 2012-02-21 12:11:02 UTC
Created attachment 57414 [details]
Evemu device

This is the uinput device which causes Xorg to crash.
Comment 13 Matthew Monaco 2012-02-21 12:12:42 UTC
Created attachment 57415 [details]
Evemu record

This is a record of the event leading to the crash. The only data there should be me pressing the wiimote button I have mapped to BTN_LEFT.
Comment 14 Matthew Monaco 2012-02-21 12:13:43 UTC
Created attachment 57416 [details]
cwiid config file

Just in case, these are the button mappings that the uinput device for the wiimote should have. It shouldn't have any other capabilities.
Comment 15 Peter Hutterer 2012-02-21 21:48:44 UTC
http://patchwork.freedesktop.org/patch/9199/
Comment 16 Matthew Monaco 2012-02-21 22:24:10 UTC
That did the trick. Thank you Peter.
Comment 17 David Herrmann 2012-02-22 02:10:25 UTC
Yes, that did it. Thanks Peter!
Comment 18 Peter Hutterer 2012-02-22 02:16:04 UTC
Please leave the bug open until the commit is upstream, we can close it once we have a commitid.
Comment 19 Peter Hutterer 2012-02-27 19:46:17 UTC
commit 2416ee4a015068359807a10f433e8c54192c78a9
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Wed Feb 22 15:32:56 2012 +1000

    dix: avoid NULL-pointer dereference on button-only devices (#38313)

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.