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>
This commit is contained in:
Arjan van de Ven 2008-08-15 15:29:38 -07:00 committed by Ingo Molnar
parent b09c3e3f17
commit 1b2439dbb7
2 changed files with 26 additions and 0 deletions

View File

@ -21,6 +21,10 @@ BLOCKING_NOTIFIER_HEAD(reboot_notifier_list);
static int notifier_chain_register(struct notifier_block **nl,
struct notifier_block *n)
{
if (!kernel_text_address((unsigned long)n->notifier_call)) {
WARN(1, "Invalid notifier registered!");
return 0;
}
while ((*nl) != NULL) {
if (n->priority > (*nl)->priority)
break;
@ -34,6 +38,10 @@ static int notifier_chain_register(struct notifier_block **nl,
static int notifier_chain_cond_register(struct notifier_block **nl,
struct notifier_block *n)
{
if (!kernel_text_address((unsigned long)n->notifier_call)) {
WARN(1, "Invalid notifier registered!");
return 0;
}
while ((*nl) != NULL) {
if ((*nl) == n)
return 0;
@ -82,6 +90,14 @@ static int __kprobes notifier_call_chain(struct notifier_block **nl,
while (nb && nr_to_call) {
next_nb = rcu_dereference(nb->next);
#ifdef CONFIG_DEBUG_NOTIFIERS
if (!kernel_text_address((unsigned long)nb->notifier_call)) {
WARN(1, "Invalid notifier called!");
nb = next_nb;
continue;
}
#endif
ret = nb->notifier_call(nb, val, v);
if (nr_calls)

View File

@ -536,6 +536,16 @@ config DEBUG_SG
If unsure, say N.
config DEBUG_NOTIFIERS
bool "Debug notifier call chains"
depends on DEBUG_KERNEL
help
Enable this to turn on sanity checking for notifier call chains.
This is most useful for kernel developers to make sure that
modules properly unregister themselves from notifier chains.
This is a relatively cheap check but if you care about maximum
performance, say N.
config FRAME_POINTER
bool "Compile the kernel with frame pointers"
depends on DEBUG_KERNEL && \