From: Steven Rostedt Date: Mon, 23 May 2011 20:45:32 +0000 (-0400) Subject: st_kim: Handle case of no device found for ID 0 X-Git-Tag: v3.0-rc6~28^2~7 X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-kernel.git;a=commitdiff_plain;h=7316a9f2a94c14e66e9421a777dffc509a2fe0e3 st_kim: Handle case of no device found for ID 0 Running ktest.pl, I hit this bug: [ 19.780654] BUG: unable to handle kernel NULL pointer dereference at 0000000c [ 19.780660] IP: [] dev_get_drvdata+0xc/0x46 [ 19.780669] *pdpt = 0000000031daf001 *pde = 0000000000000000 [ 19.780673] Oops: 0000 [#1] SMP [ 19.780680] Dumping ftrace buffer:^M [ 19.780685] (ftrace buffer empty) [ 19.780687] Modules linked in: ide_pci_generic firewire_ohci firewire_core evbug crc_itu_t e1000 ide_core i2c_i801 iTCO_wdt [ 19.780697] [ 19.780700] Pid: 346, comm: v4l_id Not tainted 2.6.39-test-02740-gcaebc16-dirty #4 /DG965MQ [ 19.780706] EIP: 0060:[] EFLAGS: 00010202 CPU: 0 [ 19.780709] EIP is at dev_get_drvdata+0xc/0x46 [ 19.780712] EAX: 00000008 EBX: f1e37da4 ECX: 00000000 EDX: 00000000 [ 19.780715] ESI: f1c3f200 EDI: c33ec95c EBP: f1e37d80 ESP: f1e37d80 [ 19.780718] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 [ 19.780721] Process v4l_id (pid: 346, ti=f1e36000 task=f2bc2a60 task.ti=f1e36000) [ 19.780723] Stack: [ 19.780725] f1e37d8c c117d395 c33ec93c f1e37db4 c117a0f9 00000002 00000000 c1725e54 [ 19.780732] 00000001 00000007 f2918c90 f1c3f200 c33ec95c f1e37dd4 c1789d3d 22222222 [ 19.780740] 22222222 22222222 f2918c90 f1c3f200 f29194f4 f1e37de8 c178d5c4 c1725e54 [ 19.780747] Call Trace: [ 19.780752] [] st_kim_ref+0x28/0x41 [ 19.780756] [] st_register+0x29/0x562 [ 19.780761] [] ? v4l2_open+0x111/0x1e3 [ 19.780766] [] fmc_prepare+0x97/0x424 [ 19.780770] [] fm_v4l2_fops_open+0x70/0x106 [ 19.780773] [] ? v4l2_open+0x111/0x1e3 [ 19.780777] [] v4l2_open+0x158/0x1e3 [ 19.780782] [] chrdev_open+0x22c/0x276 [ 19.780787] [] __dentry_open+0x35c/0x581 [ 19.780792] [] nameidata_to_filp+0x7c/0x96 [ 19.780795] [] ? cdev_put+0x57/0x57 [ 19.780800] [] do_last+0x743/0x9d4 [ 19.780804] [] ? path_init+0x1ee/0x596 [ 19.780808] [] path_openat+0x10c/0x597 [ 19.780813] [] ? trace_hardirqs_off+0x27/0x37 [ 19.780817] [] ? local_clock+0x78/0xc7 [ 19.780821] [] do_filp_open+0x39/0xc2 [ 19.780827] [] ? _raw_spin_unlock+0x4c/0x5d^M [ 19.780831] [] ? alloc_fd+0x19e/0x1b7 [ 19.780836] [] do_sys_open+0xb7/0x1bd [ 19.780840] [] ? sys_munmap+0x78/0x8d [ 19.780844] [] sys_open+0x36/0x58 [ 19.780849] [] sysenter_do_call+0x12/0x38 [ 19.780852] Code: d8 2f 20 c3 01 83 15 dc 2f 20 c3 00 f0 ff 00 83 05 e0 2f 20 c3 01 83 15 e4 2f 20 c3 00 5d c3 55 89 e5 3e 8d 74 26 00 85 c0 74 28 <8b> 40 04 83 05 e8 2f 20 c3 01 83 15 ec 2f 20 c3 00 85 c0 74 13 ^M [ 19.780889] EIP: [] dev_get_drvdata+0xc/0x46 SS:ESP 0068:f1e37d80 [ 19.780894] CR2: 000000000000000c [ 19.780898] ---[ end trace e7d1d0f6a2d1d390 ]--- The id of 0 passed to st_kim_ref() found no device, keeping pdev null, and causing pdev->dev cause a NULL pointer dereference. After having st_kim_ref() check for NULL, the st_unregister() function needed to be updated to handle the case that st_gdata was not set by the st_kim_ref(). Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c index f91f82eabda7..54c91ffe4a91 100644 --- a/drivers/misc/ti-st/st_core.c +++ b/drivers/misc/ti-st/st_core.c @@ -605,7 +605,7 @@ long st_unregister(struct st_proto_s *proto) pr_debug("%s: %d ", __func__, proto->chnl_id); st_kim_ref(&st_gdata, 0); - if (proto->chnl_id >= ST_MAX_CHANNELS) { + if (!st_gdata || proto->chnl_id >= ST_MAX_CHANNELS) { pr_err(" chnl_id %d not supported", proto->chnl_id); return -EPROTONOSUPPORT; } diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index 5da93ee6f6be..3613c3bc4da3 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c @@ -604,6 +604,10 @@ void st_kim_ref(struct st_data_s **core_data, int id) struct kim_data_s *kim_gdata; /* get kim_gdata reference from platform device */ pdev = st_get_plat_device(id); + if (!pdev) { + *core_data = NULL; + return; + } kim_gdata = dev_get_drvdata(&pdev->dev); *core_data = kim_gdata->core_data; }