Segfault (NULL deref) during RandR mode switch with multiple QXL devices
Submitted by Peter Wu
Assigned to Søren Sandmann Pedersen
Description
Situation: QEMU VM with a QXL display device. When changing the screen resolution, Xorg crashes.
Steps to reproduce:
- Start QEMU with an Arch Linux guest. qemu-system-x86_64 -machine pc,accel=kvm ... -vga qxl -device qxl -spice port=$port,disable-ticketing
- Connect with: spicy -h $ip -p $port
- Install packages: pacman -S xorg-server xorg-xrandr xterm xorg-xinit.
- From a tty, startx
- In xterm: xrandr --output Virtual-0 --mode 1920x1200
Expected result: Screen resolution changes, window resizes.
Actual result: Xorg segfaults. See bottom for Xorg.0.log and gdb output. Note that
Package versions: qemu-system-x86_64 2.0.0+dfsg-2ubuntu1.15 (host, Ubuntu 14.04LTS) Guest: Arch Linux x86_64 xf86-video-qxl 0.1.4 xorg-server 1.17.2 spice 0.12.5 spice-vdagent 0.16.0 (vdagent does not seem to affect result)
Additional information: [ 970.996] qxl_kms_surface_create: Bad bpp: 1 (1) [ 971.001] (EE) [ 971.001] (EE) Backtrace: [ 971.001] (EE) 0: /usr/lib/xorg-server/Xorg (OsLookupColor+0x139) [0x596d09] [ 971.002] (EE) 1: /usr/lib/libc.so.6 (__restore_rt+0x0) [0x7fc7793955af] [ 971.002] (EE) 2: /usr/lib/xorg-server/Xorg (RRTellChanged+0x2ca) [0x4f632a] [ 971.002] (EE) 3: /usr/lib/xorg-server/Xorg (ProcRRSetOutputPrimary+0x103) [0x4fc7c3] [ 971.002] (EE) 4: /usr/lib/xorg-server/Xorg (SendErrorToClient+0x2ff) [0x438e4f] [ 971.002] (EE) 5: /usr/lib/xorg-server/Xorg (remove_fs_handlers+0x41b) [0x43cf4b] [ 971.002] (EE) 6: /usr/lib/libc.so.6 (__libc_start_main+0xf0) [0x7fc779382790] [ 971.002] (EE) 7: /usr/lib/xorg-server/Xorg (_start+0x29) [0x427319] [ 971.003] (EE) 8: ? (?+0x29) [0x29] [ 971.003] (EE) [ 971.003] (EE) Segmentation fault at address 0x34
(gdb) bt
#0 0x00007fd83343e528 in raise () from /usr/lib/libc.so.6
#1 0x00007fd83343f93a in abort () from /usr/lib/libc.so.6
#2 0x000000000063a94a in OsAbort () at utils.c:1342
#3 0x000000000049d411 in ddxGiveUp (error=EXIT_ERR_ABORT) at xf86Init.c:1065
#4 0x000000000049d53a in AbortDDX (error=EXIT_ERR_ABORT) at xf86Init.c:1109
#5 0x00000000006447b2 in AbortServer () at log.c:804
#6 0x0000000000644cf6 in FatalError (f=0x672a20 "Caught signal %d (%s). Server aborting\n") at log.c:945
#7 0x0000000000637538 in OsSigHandler (signo=11, sip=0x7ffeb068c7b0, unused=0x7ffeb068c680) at osinit.c:147
#8 <signal handler called>
#9 0x000000000054b1d2 in RRTellChanged (pScreen=0x12817e0) at randr.c:615
#10 0x000000000055a064 in RRScreenSizeNotify (pScreen=0x12817e0) at rrscreen.c:149
#11 0x00000000004f2796 in xf86RandR12ScreenSetSize (pScreen=0x12817e0, width=1920, height=1200, mmWidth=507, mmHeight=317) at xf86RandR12.c:734
#12 0x000000000055a101 in RRScreenSizeSet (pScreen=0x12817e0, width=1920, height=1200, mmWidth=507, mmHeight=317) at rrscreen.c:171
#13 0x000000000055a599 in ProcRRSetScreenSize (client=0x155f460) at rrscreen.c:286
#14 0x000000000054b40f in ProcRRDispatch (client=0x155f460) at randr.c:675
#15 0x000000000043393d in Dispatch () at dispatch.c:432
#16 0x0000000000442977 in dix_main (argc=7, argv=0x7ffeb068cf98, envp=0x7ffeb068cfd8) at main.c:298
#17 0x0000000000423a8e in main (argc=7, argv=0x7ffeb068cf98, envp=0x7ffeb068cfd8) at stubmain.c:34
(gdb) frame 9
#9 0x000000000054b1d2 in RRTellChanged (pScreen=0x12817e0) at randr.c:615
615 pSlaveScrPriv->provider->changed = FALSE;
(gdb) l
610 pSlaveScrPriv = rrGetScrPriv(iter);
611 pSlaveScrPriv->provider->changed = FALSE;
612 }
613 xorg_list_for_each_entry(iter, &master->unattached_list, unattached_head) {
614 pSlaveScrPriv = rrGetScrPriv(iter);
615 pSlaveScrPriv->provider->changed = FALSE;
616 }
617
618 if (mastersp->layoutChanged) {
619 pScrPriv->layoutChanged = FALSE;
(gdb) p pSlaveScrPriv->provider
$1 = (RRProviderPtr) 0x0
By skipping the provider indirection the crash is avoided: break randr.c:615 if !pSlaveScrPriv->provider commands j +1 c end
unattached_list
break randr.c:619 if !pSlaveScrPriv->provider commands j +1 c end