]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge commit 'v2.6.28-rc6' into core/debug
authorIngo Molnar <mingo@elte.hu>
Wed, 26 Nov 2008 07:22:50 +0000 (08:22 +0100)
committerIngo Molnar <mingo@elte.hu>
Wed, 26 Nov 2008 07:22:50 +0000 (08:22 +0100)
include/linux/kernel.h
kernel/extable.c
kernel/notifier.c
kernel/softlockup.c
lib/Kconfig.debug

index dc7e0d0a6474448aba71b4c32d2045afc44e240e..f98b6e7d38dd0973a248c3c8e951abdd42dd4f5b 100644 (file)
@@ -188,6 +188,8 @@ extern unsigned long long memparse(const char *ptr, char **retptr);
 extern int core_kernel_text(unsigned long addr);
 extern int __kernel_text_address(unsigned long addr);
 extern int kernel_text_address(unsigned long addr);
+extern int func_ptr_is_kernel_text(void *ptr);
+
 struct pid;
 extern struct pid *session_of_pgrp(struct pid *pgrp);
 
index a26cb2e170237d849c9f87038a6def48ee948dd6..adf0cc9c02d6873d50c48edf4c34b44a32bf48b9 100644 (file)
@@ -66,3 +66,19 @@ int kernel_text_address(unsigned long addr)
                return 1;
        return module_text_address(addr) != NULL;
 }
+
+/*
+ * On some architectures (PPC64, IA64) function pointers
+ * are actually only tokens to some data that then holds the
+ * real function address. As a result, to find if a function
+ * pointer is part of the kernel text, we need to do some
+ * special dereferencing first.
+ */
+int func_ptr_is_kernel_text(void *ptr)
+{
+       unsigned long addr;
+       addr = (unsigned long) dereference_function_descriptor(ptr);
+       if (core_kernel_text(addr))
+               return 1;
+       return module_text_address(addr) != NULL;
+}
index 4282c0a40a57ada651b86c7dcce2389abf489448..61d5aa5eced3466393582e4f566b63c468ea7cc3 100644 (file)
@@ -82,6 +82,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 (unlikely(!func_ptr_is_kernel_text(nb->notifier_call))) {
+                       WARN(1, "Invalid notifier called!");
+                       nb = next_nb;
+                       continue;
+               }
+#endif
                ret = nb->notifier_call(nb, val, v);
 
                if (nr_calls)
index 3953e4aed733d32284f48ecfffa1fbff05e234c6..884e6cd2769c348a846d103122b6e49e20acae85 100644 (file)
@@ -164,7 +164,7 @@ unsigned long __read_mostly sysctl_hung_task_check_count = 1024;
 /*
  * Zero means infinite timeout - no checking done:
  */
-unsigned long __read_mostly sysctl_hung_task_timeout_secs = 120;
+unsigned long __read_mostly sysctl_hung_task_timeout_secs = 480;
 
 unsigned long __read_mostly sysctl_hung_task_warnings = 10;
 
index b0f239e443bc0fbb11a27ee98dbaf4e641d21971..1e3fd3e3436abf6e142c9f0b46cc6993cd19ec38 100644 (file)
@@ -545,6 +545,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 && \