aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArjan van de Ven <arjan@linux.intel.com>2008-08-15 18:29:38 -0400
committerIngo Molnar <mingo@elte.hu>2008-09-10 03:08:50 -0400
commit1b2439dbb703ae8d95a9ce7ece6b7800b80f41f0 (patch)
tree63c6c105b86ce45ca010dca4bd501a924afd05d1
parentb09c3e3f1710b554348c98e78fbf4a661918779a (diff)
debug: add notifier chain debugging
during some development we suspected a case where we left something in a notifier chain that was from a module that was unloaded already... and that sort of thing is rather hard to track down. This patch adds a very simple sanity check (which isn't all that expensive) to make sure the notifier we're about to call is actually from either the kernel itself of from a still-loaded module, avoiding a hard-to-chase-down crash. Signed-off-by: Arjan van de Ven <arjan@linux.intel.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--kernel/notifier.c16
-rw-r--r--lib/Kconfig.debug10
2 files changed, 26 insertions, 0 deletions
diff --git a/kernel/notifier.c b/kernel/notifier.c
index 823be11584ef..143fdd77dbf7 100644
--- a/kernel/notifier.c
+++ b/kernel/notifier.c
@@ -21,6 +21,10 @@ BLOCKING_NOTIFIER_HEAD(reboot_notifier_list);
21static int notifier_chain_register(struct notifier_block **nl, 21static int notifier_chain_register(struct notifier_block **nl,
22 struct notifier_block *n) 22 struct notifier_block *n)
23{ 23{
24 if (!kernel_text_address((unsigned long)n->notifier_call)) {
25 WARN(1, "Invalid notifier registered!");
26 return 0;
27 }
24 while ((*nl) != NULL) { 28 while ((*nl) != NULL) {
25 if (n->priority > (*nl)->priority) 29 if (n->priority > (*nl)->priority)
26 break; 30 break;
@@ -34,6 +38,10 @@ static int notifier_chain_register(struct notifier_block **nl,
34static int notifier_chain_cond_register(struct notifier_block **nl, 38static int notifier_chain_cond_register(struct notifier_block **nl,
35 struct notifier_block *n) 39 struct notifier_block *n)
36{ 40{
41 if (!kernel_text_address((unsigned long)n->notifier_call)) {
42 WARN(1, "Invalid notifier registered!");
43 return 0;
44 }
37 while ((*nl) != NULL) { 45 while ((*nl) != NULL) {
38 if ((*nl) == n) 46 if ((*nl) == n)
39 return 0; 47 return 0;
@@ -82,6 +90,14 @@ static int __kprobes notifier_call_chain(struct notifier_block **nl,
82 90
83 while (nb && nr_to_call) { 91 while (nb && nr_to_call) {
84 next_nb = rcu_dereference(nb->next); 92 next_nb = rcu_dereference(nb->next);
93
94#ifdef CONFIG_DEBUG_NOTIFIERS
95 if (!kernel_text_address((unsigned long)nb->notifier_call)) {
96 WARN(1, "Invalid notifier called!");
97 nb = next_nb;
98 continue;
99 }
100#endif
85 ret = nb->notifier_call(nb, val, v); 101 ret = nb->notifier_call(nb, val, v);
86 102
87 if (nr_calls) 103 if (nr_calls)
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 8b5a7d304a5f..342858fbabbc 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -536,6 +536,16 @@ config DEBUG_SG
536 536
537 If unsure, say N. 537 If unsure, say N.
538 538
539config DEBUG_NOTIFIERS
540 bool "Debug notifier call chains"
541 depends on DEBUG_KERNEL
542 help
543 Enable this to turn on sanity checking for notifier call chains.
544 This is most useful for kernel developers to make sure that
545 modules properly unregister themselves from notifier chains.
546 This is a relatively cheap check but if you care about maximum
547 performance, say N.
548
539config FRAME_POINTER 549config FRAME_POINTER
540 bool "Compile the kernel with frame pointers" 550 bool "Compile the kernel with frame pointers"
541 depends on DEBUG_KERNEL && \ 551 depends on DEBUG_KERNEL && \