diff options
author | Gabriel Krisman Bertazi <krisman@collabora.co.uk> | 2017-03-24 01:54:44 -0300 |
---|---|---|
committer | Gerd Hoffmann <kraxel@redhat.com> | 2017-03-27 10:34:52 +0200 |
commit | c0411316ab93e35a671aafcab82d1eefed449a4f (patch) | |
tree | 9f510e6ab9a162592634c9fa002aed54c628f5d7 | |
parent | 18dddadc78c91a91b546acc48506c24f5f840c4f (diff) |
drm: bochs: Prevent double-free of fb helper
If fbdev registration fails for whatever reason, the error path of
bochs_fbdev_init() will call bochs_fbdev_fini(), but since an fbdev
initialization error is not fatal to the probe function, a subsequent
device removal will try to call bochs_fbdev_fini() again, hitting the
Oops below.
This was detected by 0-day with a failing framebuffer registration and
CONFIG_DEBUG_TEST_DRIVER_REMOVE=y. This reproduces the scenario I
mentioned above at insmod time, because the test attempts to remove the
device right after probing.
root@debian:~# insmod bochs-drm.ko
[ 17.609635] [drm] Found bochs VGA, ID 0xb0c0.
[ 17.612974] [drm] Framebuffer size 16384 kB @ 0xfa000000, mmio @ 0xfebf2000.
[ 17.613938] [TTM] Zone kernel: Available graphics memory: 1022244 kiB
[ 17.614701] [TTM] Initializing pool allocator
[ 17.615427] [TTM] Initializing DMA pool allocator
[ 17.619143] fbcon: bochsdrmfb (fb0) is primary device
[ 17.619428] Console: switching to colour frame buffer device 128x48
[ 17.621047] bochs-drm 0000:00:02.0: fb0: bochsdrmfb frame buffer device
[ 17.641111] [drm] Initialized bochs-drm 1.0.0 20130925 for 0000:00:02.0 on minor 0
[ 17.642380] general protection fault: 0000 [#1] SMP
[ 17.642985] Modules linked in: bochs_drm(+)
[ 17.643259] CPU: 4 PID: 3279 Comm: insmod Tainted: G W 4.11.0-rc1+ #119
[ 17.643259] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.9.3-20161025_171302-gandalf 04/01/2014
[ 17.643259] task: ffff88007af35e00 task.stack: ffffc90000d84000
[ 17.643259] RIP: 0010:drm_fb_helper_fini+0x8e/0x110
[ 17.643259] RSP: 0018:ffffc90000d87ad0 EFLAGS: 00010202
[ 17.643259] RAX: dead000000000200 RBX: ffff8800790d5770 RCX: 0000000000000000
[ 17.652101] RDX: dead000000000100 RSI: 000000007fffffff RDI: ffffffff81eaf820
[ 17.652101] RBP: ffffc90000d87ae0 R08: 0000000000000000 R09: ffff88007271d918
[ 17.652101] R10: ffffc90000d87a88 R11: 0000000000000000 R12: 0000000000000000
[ 17.652101] R13: ffff8800790d56d0 R14: 0000000000000000 R15: 0000000000000000
[ 17.652101] FS: 00007f9285995700(0000) GS:ffff88007cf00000(0000) knlGS:0000000000000000
[ 17.652101] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 17.652101] CR2: 0000564f1cf9f1e8 CR3: 0000000079686000 CR4: 00000000000006e0
[ 17.652101] Call Trace:
[ 17.652101] bochs_fbdev_fini+0x24/0x90 [bochs_drm]
[ 17.652101] bochs_unload+0x16/0x50 [bochs_drm]
[ 17.652101] drm_dev_unregister+0x37/0xd0
[ 17.652101] drm_put_dev+0x31/0x60
[ 17.652101] bochs_pci_remove+0x10/0x20 [bochs_drm]
[ 17.652101] pci_device_remove+0x34/0xb0
[ 17.652101] driver_probe_device+0xd0/0x370
[ 17.652101] __driver_attach+0x96/0xa0
[ 17.652101] ? driver_probe_device+0x370/0x370
[ 17.652101] bus_for_each_dev+0x5b/0x90
[ 17.652101] driver_attach+0x19/0x20
[ 17.652101] bus_add_driver+0x11c/0x220
[ 17.652101] driver_register+0x5b/0xd0
[ 17.652101] ? 0xffffffffa0006000
[ 17.652101] __pci_register_driver+0x47/0x50
[ 17.652101] drm_pci_init+0xe1/0xf0
[ 17.652101] ? 0xffffffffa0006000
[ 17.652101] bochs_init+0x3c/0x1000 [bochs_drm]
[ 17.652101] do_one_initcall+0x3e/0x180
[ 17.652101] ? kmem_cache_alloc_trace+0x33/0x150
[ 17.652101] do_init_module+0x5a/0x1eb
[ 17.652101] load_module+0x1ea0/0x2650
[ 17.652101] ? __symbol_put+0x40/0x40
[ 17.652101] ? kernel_read_file+0x19e/0x1c0
[ 17.652101] ? kernel_read_file_from_fd+0x44/0x70
[ 17.652101] SYSC_finit_module+0xba/0xc0
[ 17.652101] SyS_finit_module+0x9/0x10
[ 17.652101] entry_SYSCALL_64_fastpath+0x1a/0xa9
[ 17.652101] RIP: 0033:0x7f92854da119
[ 17.652101] RSP: 002b:00007ffcd0390498 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
[ 17.652101] RAX: ffffffffffffffda RBX: 00007f928578eb58 RCX: 00007f92854da119
[ 17.652101] RDX: 0000000000000000 RSI: 0000564f1c8bd638 RDI: 0000000000000003
[ 17.652101] RBP: 000000000000270e R08: 0000000000000000 R09: 00007f9285790ea0
[ 17.652101] R10: 0000000000000003 R11: 0000000000000246 R12: 00007f928578eb58
[ 17.652101] R13: 0000000000001020 R14: 0000564f1cf9e1c0 R15: 00007f928578eb00
[ 17.652101] Code: c7 20 f8 ea 81 e8 b3 3e 50 00 48 8b 83 d0 00 00 00 48 8d 93 d0 00 00 00 48 39 c2 74 46 48 8b 83 d8 00 00 00 48 8b 93 d0 00 00 00 <48> 89 42 08 48 89 10 48 b8 00 01 00 00 0000 ad de 48 89 83 d0
[ 17.652101] RIP: drm_fb_helper_fini+0x8e/0x110 RSP: ffffc90000d87ad0
[ 17.653331] ---[ end trace 542fd75a2e60a6a4 ]---
Signed-off-by: Gabriel Krisman Bertazi <krisman@collabora.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/20170324045444.11912-1-krisman@collabora.co.uk
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
-rw-r--r-- | drivers/gpu/drm/bochs/bochs_fbdev.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/drivers/gpu/drm/bochs/bochs_fbdev.c b/drivers/gpu/drm/bochs/bochs_fbdev.c index 471bd588550b..c38deffa14de 100644 --- a/drivers/gpu/drm/bochs/bochs_fbdev.c +++ b/drivers/gpu/drm/bochs/bochs_fbdev.c @@ -192,6 +192,8 @@ void bochs_fbdev_fini(struct bochs_device *bochs) if (bochs->fb.initialized) bochs_fbdev_destroy(bochs); - drm_fb_helper_fini(&bochs->fb.helper); + if (bochs->fb.helper.fbdev) + drm_fb_helper_fini(&bochs->fb.helper); + bochs->fb.initialized = false; } |