Commit 1b2439dbb703ae8d95a9ce7ece6b7800b80f41f0
Committed by
Ingo Molnar
1 parent
b09c3e3f17
Exists in
master
and in
4 other branches
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>
Showing 2 changed files with 26 additions and 0 deletions Side-by-side Diff
kernel/notifier.c
... | ... | @@ -21,6 +21,10 @@ |
21 | 21 | static int notifier_chain_register(struct notifier_block **nl, |
22 | 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 | 28 | while ((*nl) != NULL) { |
25 | 29 | if (n->priority > (*nl)->priority) |
26 | 30 | break; |
... | ... | @@ -34,6 +38,10 @@ |
34 | 38 | static int notifier_chain_cond_register(struct notifier_block **nl, |
35 | 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 | 45 | while ((*nl) != NULL) { |
38 | 46 | if ((*nl) == n) |
39 | 47 | return 0; |
... | ... | @@ -82,6 +90,14 @@ |
82 | 90 | |
83 | 91 | while (nb && nr_to_call) { |
84 | 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 | 101 | ret = nb->notifier_call(nb, val, v); |
86 | 102 | |
87 | 103 | if (nr_calls) |
lib/Kconfig.debug
... | ... | @@ -536,6 +536,16 @@ |
536 | 536 | |
537 | 537 | If unsure, say N. |
538 | 538 | |
539 | +config 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 | + | |
539 | 549 | config FRAME_POINTER |
540 | 550 | bool "Compile the kernel with frame pointers" |
541 | 551 | depends on DEBUG_KERNEL && \ |