Attempt to modify device proximity field for non-proximity input device causes segmentation fault using Wacom tablet
Submitted by Steve Holland
Assigned to Xorg Project Team
Link to original bug (#100921)
Description
Observed on xorg-1.19.3-1 (Fedora 25):
Symptom: Occasional Xorg server crashes when using a Wacom tablet (Built into Lenovo Thinkpad S1 Yoga in my case). It seems to be a random issue that occurs roughly every hour of tablet use.
(Might be a dup of Bug #99556 -- but that report doesn't have enough detail to confirm)
I have been able to obtain a core dump and gdb backtrace:
(gdb) where
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:58
#1 0x00007f6ec04b851a in __GI_abort () at abort.c:89
#2 0x00000000005a16be in OsAbort () at utils.c:1355
#3 0x00000000005a7243 in AbortServer () at log.c:877
#4 0x00000000005a802d in FatalError (f=f@entry=0x5d57d0 "Caught signal %d (%s). Server aborting\n") at log.c:1015
#5 0x000000000059e95e in OsSigHandler (signo=11, sip=<optimized out>, unused=<optimized out>) at osinit.c:154
#6 <signal handler called>
#7 UpdateDeviceState (device=0x20fb4b0, event=0x7fff96551190) at exevents.c:931
#8 0x0000000000528ce0 in ProcessDeviceEvent (ev=ev@entry=0x7fff96551190, device=device@entry=0x20fb4b0) at exevents.c:1709
#9 0x000000000052948b in ProcessOtherEvent (ev=0x7fff96551190, device=0x20fb4b0) at exevents.c:1873
#10 0x000000000054e0d2 in ProcessPointerEvent (ev=0x7fff96551190, mouse=0x20fb4b0) at xkbAccessX.c:756
#11 0x000000000057d612 in mieqProcessDeviceEvent (dev=0x22fd630, event=0x7fff96551df0, screen=0x1eb8cb0) at mieq.c:496
#12 0x000000000057d749 in mieqProcessInputEvents () at mieq.c:551
#13 0x0000000000479289 in ProcessInputEvents () at xf86Events.c:165
#14 0x0000000000436e16 in Dispatch () at dispatch.c:418
#15 0x000000000043b078 in dix_main (argc=15, argv=0x7fff96552c08, envp=<optimized out>) at main.c:287
#16 0x00007f6ec04a1401 in __libc_start_main (main=0x424d20 <main>, argc=15, argv=0x7fff96552c08, init=<optimized out>, fini=<optimized out>,
rtld_fini=<optimized out>, stack_end=0x7fff96552bf8) at ../csu/libc-start.c:289
#17 0x0000000000424d5a in _start ()
The coredump occurs in exevents.c:UpdateDeviceState(): 930: else if (event->type == ET_ProximityOut) 931: device->proximity->in_proximity = FALSE; device->proximity is NULL hence attempting to set its in_proximity member causes a segmentation violation.
How did device->proximity turn out to be NULL for a ProximityOut event?
Let's go up a few levels and look at mieq.c:mieqProcessDeviceEvent():
490: /* process slave first, then master / 491: dev->public.processInputProc(event, dev); 492: 493: / Check for the SD's master in case the device got detached 494: * during event processing */ 495: if (master && !IsFloating(dev)) 496: master->public.processInputProc(&mevent, master);
dev->proximity is a valid pointer, but master->proximity is NULL So it is processed OK on line 491 but the processInputProc() call on line 496 provides an ET_ProximityOut event with a device where proximity is NULL. And after a few layers this turns into the call to UpdateDeviceState() above, which attempts to set the in_proximity field unconditionally.
Possible Fix: Perhaps check for device->proximity being NULL in UpdateDeviceState()?