From 7585ca0dc950583be7fc62099ca43a0c9551a875 Mon Sep 17 00:00:00 2001 From: "Wang, Xiaoming" Date: Fri, 1 Nov 2013 18:48:14 -0400 Subject: extcon: remove freed groups caused the panic or warning in unregister flow (edev->extcon_dev_type.groups) has been freed before device_unregister. extcon_dev_unregister -> kfree(edev->extcon_dev_type.groups) then device_unregister -> device_del -> device_remove_attrs -> device_remove_groups(dev, type->groups); panic because type->groups has been freed. This patch is move device_unregister ahead of groups free to avoid panic in extcon_dev_unregister. stack [ 22.847226] BUG: unable to handle kernel paging request at 5f39746e [ 22.847234] IP: [] sysfs_remove_group+0x2d/0xd0 [ 22.847238] *pdpt = 0000000000000000 *pde = 0000000000000000 [ 22.847241] Oops: 0000 [#1] PREEMPT SMP [ 22.847244] Modules linked in: [ 22.847249] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G W 3.10.16-261140-g6533774 #1 [ 22.847251] task: f3078000 ti: f3072000 task.ti: f3072000 [ 22.847254] EIP: 0060:[] EFLAGS: 00010206 CPU: 0 [ 22.847257] EIP is at sysfs_remove_group+0x2d/0xd0 [ 22.847259] EAX: 00000004 EBX: 5f39746e ECX: 00000000 EDX: f2773560 [ 22.847261] ESI: f2653b80 EDI: f2773560 EBP: f3073c90 ESP: f3073c70 [ 22.847263] DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068 [ 22.847264] CR0: 8005003b CR2: 5f39746e CR3: 020e5000 CR4: 001007f0 [ 22.847266] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 [ 22.847268] DR6: ffff0ff0 DR7: 00000400 [ 22.847269] Stack: [ 22.847276] c13848c9 c1ae3805 f3073c80 f24ddc4c 00000246 f2773e88 f1c44408 f2531340 [ 22.847283] f3073ca0 c16935ca f1c44400 f27d3340 f3073cb4 c1693858 f24ddc44 f1c44400 [ 22.847289] f1c4420c f3073cc8 c1693f76 f1c44400 00000001 00000000 f3073ce8 c1694011 [ 22.847290] Call Trace: [ 22.847295] [] ? sysfs_hash_and_remove+0x49/0xa0 [ 22.847300] [] ? sub_preempt_count+0x55/0xe0 [ 22.847306] [] device_remove_groups+0x2a/0x40 [ 22.847309] [] device_remove_attrs+0x38/0x60 [ 22.847313] [] device_del+0xd6/0x150 [ 22.847316] [] device_unregister+0x21/0x60 [ 22.847320] [] ? sysfs_remove_link+0x18/0x30 [ 22.847323] [] ? class_compat_remove_link+0x34/0x50 [ 22.847329] [] extcon_dev_unregister+0xf9/0x130 [ 22.847333] [] pwrsrc_extcon_dev_reg_callback+0x7f/0xa0 [ 22.847337] [] notifier_call_chain+0x43/0x60 [ 22.847343] [] __blocking_notifier_call_chain+0x41/0x80 [ 22.847347] [] blocking_notifier_call_chain+0x1f/0x30 [ 22.847351] [] extcon_dev_notify_add_device+0x19/0x20 [ 22.847354] [] extcon_dev_register+0x134/0x580 [ 22.847358] [] ? sub_preempt_count+0x55/0xe0 [ 22.847363] [] ? gpiod_request+0x6a/0x1d0 [ 22.847368] [] ? kmem_cache_alloc_trace+0xaa/0x170 [ 22.847372] [] ? fsa9285_probe+0x99/0x3f0 [ 22.847375] [] ? fsa9285_irq_handler+0xf0/0xf0 [ 22.847379] [] fsa9285_probe+0xbf/0x3f0 [ 22.847383] [] ? fsa9285_irq_handler+0xf0/0xf0 [ 22.847388] [] i2c_device_probe+0x7e/0xf0 [ 22.847392] [] ? sysfs_create_link+0x22/0x40 [ 22.847395] [] ? driver_sysfs_add+0x72/0xa0 [ 22.847399] [] driver_probe_device+0x79/0x360 [ 22.847403] [] __driver_attach+0x91/0xa0 [ 22.847407] [] ? driver_probe_device+0x360/0x360 [ 22.847410] [] bus_for_each_dev+0x42/0x80 [ 22.847414] [] driver_attach+0x1e/0x20 [ 22.847417] [] ? driver_probe_device+0x360/0x360 [ 22.847420] [] bus_add_driver+0xef/0x270 [ 22.847425] [] ? i2c_device_probe+0xf0/0xf0 [ 22.847428] [] ? i2c_device_probe+0xf0/0xf0 [ 22.847432] [] driver_register+0x6a/0x160 [ 22.847436] [] ? mutex_unlock+0xd/0x10 [ 22.847440] [] ? __create_file+0x122/0x2a0 [ 22.847446] [] ? extcon_class_init+0x15/0x15 [ 22.847450] [] i2c_register_driver+0x2b/0xd0 [ 22.847454] [] ? debugfs_create_file+0x35/0x40 [ 22.847458] [] ? extcon_class_init+0x15/0x15 [ 22.847461] [] fsa9285_extcon_init+0x11/0x29 [ 22.847465] [] do_one_initcall+0xba/0x170 [ 22.847471] [] kernel_init_freeable+0x119/0x1b8 [ 22.847475] [] ? do_early_param+0x7a/0x7a [ 22.847480] [] kernel_init+0x10/0xd0 [ 22.847485] [] ret_from_kernel_thread+0x1b/0x28 [ 22.847488] [] ? rest_init+0x80/0x80 Tested-by: Liu, Chuansheng Reviewed-by: Liu, Chuansheng Signed-off-by: xiaoming wang Signed-off-by: Zhang Dongxing Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-class.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/extcon') diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index 15443d3b6be1..76322330cbd7 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c @@ -792,6 +792,8 @@ void extcon_dev_unregister(struct extcon_dev *edev) return; } + device_unregister(&edev->dev); + if (edev->mutually_exclusive && edev->max_supported) { for (index = 0; edev->mutually_exclusive[index]; index++) @@ -812,7 +814,6 @@ void extcon_dev_unregister(struct extcon_dev *edev) if (switch_class) class_compat_remove_link(switch_class, &edev->dev, NULL); #endif - device_unregister(&edev->dev); put_device(&edev->dev); } EXPORT_SYMBOL_GPL(extcon_dev_unregister); -- cgit v1.2.3