[PATCHv2] idr: always do slow path when hint is uninitialized

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



In case of PMU-less systems we have got the following traceback.

[    7.720687] BUG: unable to handle kernel NULL pointer dereference at   (null)
[    7.727743] IP: [<c10ae57c>] perf_init_event+0x5e/0x150
[    7.732961] *pdpt = 0000000035257001 *pde = 0000000000000000
[    7.738700] Oops: 0000 [#1] PREEMPT SMP

Entering kdb (current=0xf6c58000, pid 1) on processor 1 Oops: (null)
due to oops @ 0xc10ae57c
dPid: 1, comm: init Not tainted 3.8.0-next-20130220-00036-gbceb0e3-dirty #57
dEIP: 0060:[<c10ae57c>] EFLAGS: 00010246 CPU: 1
EIP is at perf_init_event+0x5e/0x150
dEAX: 00000000 EBX: 00000000 ECX: c17efaa4 EDX: 00000005
dESI: f52e44b0 EDI: 00000005 EBP: f6c61df8 ESP: f6c61de4
d DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
dCR0: 8005003b CR2: 00000000 CR3: 35256000 CR4: 000007f0
dDR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
dDR6: ffff0ff0 DR7: 00000400
0Process init (pid: 1, ti=f6c60000 task=f6c58000 task.ti=f6c60000)
0Stack:
 00000000 c104762b 00000001 f52e45f8 f52e4588 f6c61e24 c10ae8df f6c58405
 00000006 00000007 f6c58000 f6c61e84 f52e44b0 00000000 c18aed5c 00000000
 f6c61e4c c10aec35 f52e44b0 00000000 00000000 00000000 00000000 00000000
0Call Trace:
0 [<c104762b>] ? __mutex_init+0x3f/0x44
0 [<c10ae8df>] perf_event_alloc+0x271/0x39a
0 [<c10aec35>] perf_event_create_kernel_counter+0x1a/0xb3
0 [<c10b02d7>] register_wide_hw_breakpoint+0x56/0xd9
0 [<c101f20e>] kgdb_arch_late+0x7a/0x112
0 [<c101eaca>] ? kgdb_set_hw_break+0x15e/0x15e
0 [<c1086f13>] kgdb_register_io_module+0x9b/0x121
0 [<c12c4b50>] configure_kgdboc+0xf1/0x126
0 [<c12c4c0f>] param_set_kgdboc_var+0x8a/0x8f
0 [<c10434b0>] param_attr_store+0x2a/0x47
0 [<c1043486>] ? __kernel_param_lock+0x11/0x11
0 [<c10433c7>] module_attr_store+0x17/0x26
0 [<c112dfc9>] sysfs_write_file+0xab/0xe6
0 [<c112df1e>] ? sysfs_chmod_file+0x82/0x82
0 [<c10e1834>] vfs_write+0x66/0xa7
0 [<c10e19b0>] sys_write+0x37/0x60
0 [<c1547741>] sysenter_do_call+0x12/0x32
0Code: ff ff 8b 7e 78 8b 1d 94 12 e5 c1 e8 5c 49 f9 ff 83 c4 0c 85 c0 74 0e 80 3d 28 05 84 c1 00 75 05 e8 99 9c ff ff 89 f8 89 fa 30 c0 <3b> 03 75 26 81 e2 ff 00 00 00 83 c2 08 8b 5c 93 04 e8 2b 49 f9

The guilty commit is cc5b5f6 "events: convert to idr_alloc()" together with
f49318a "idr: implement lookup hint". In our case the idr_alloc is never
called, but idr_find is. The hint field is never initialized and therefore
should not be dereferenced.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx>
Reported-by: Kirill A. Shutemov <kirill.shutemov@xxxxxxxxxxxxxxx>
---
 include/linux/idr.h | 2 +-
 lib/idr.c           | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/idr.h b/include/linux/idr.h
index aed2a0c..a6f38b5 100644
--- a/include/linux/idr.h
+++ b/include/linux/idr.h
@@ -113,7 +113,7 @@ static inline void *idr_find(struct idr *idr, int id)
 {
 	struct idr_layer *hint = rcu_dereference_raw(idr->hint);
 
-	if ((id & ~IDR_MASK) == hint->prefix)
+	if (hint && (id & ~IDR_MASK) == hint->prefix)
 		return rcu_dereference_raw(hint->ary[id & IDR_MASK]);
 
 	return idr_find_slowpath(idr, id);
diff --git a/lib/idr.c b/lib/idr.c
index 5c772dc..1a30272 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -139,7 +139,7 @@ static void idr_layer_rcu_free(struct rcu_head *head)
 
 static inline void free_layer(struct idr *idr, struct idr_layer *p)
 {
-	if (idr->hint == p)
+	if (idr->hint && idr->hint == p)
 		RCU_INIT_POINTER(idr->hint, NULL);
 	call_rcu(&p->rcu_head, idr_layer_rcu_free);
 }
-- 
1.8.2.rc0.22.gb3600c3

--
To unsubscribe from this list: send the line "unsubscribe linux-next" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel]     [Linux USB Development]     [Yosemite News]     [Linux SCSI]

  Powered by Linux