]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
dtrace: ensure SDT module probes work with NORX
authorKris Van Hees <kris.van.hees@oracle.com>
Thu, 13 Aug 2015 16:23:54 +0000 (12:23 -0400)
committerNick Alcock <nick.alcock@oracle.com>
Fri, 14 Aug 2015 10:13:08 +0000 (11:13 +0100)
When the CONFIG_DEBUG_SET_MODULE_RONX option is enabled in the kernel,
the executable code of the module is marked read-only prior to calling
the module notifier.  This causes the patching of NOPs in the probe
locations to fail with a system crash.

Because patching of SDT probe locations should happen upon module load
for DTrace-enabled kernels regardless of whether or not DTrace will be
used, it is both cleaner and more correct to make a direct call to the
code that handles the patching rather than using the notifier mechanism.
The new call takes place prior to marking the pages read-only, avoiding
the problem altogether.

Orabug: 21630297
Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
Acked-by: Nick Alcock <nick.alcock@oracle.com>
include/linux/dtrace_sdt.h [moved from kernel/dtrace/dtrace_sdt.h with 91% similarity]
kernel/dtrace/dtrace_os.c
kernel/dtrace/dtrace_sdt_core.c
kernel/module.c

similarity index 91%
rename from kernel/dtrace/dtrace_sdt.h
rename to include/linux/dtrace_sdt.h
index 18a745fc1fc7c01d233928ef38010ad2b51b575f..90ca2f5c74fe940012edac2de6a4d322eccbf27f 100644 (file)
@@ -3,6 +3,7 @@
 #ifndef _DTRACE_SDT_H_
 #define        _DTRACE_SDT_H_
 
+#include <linux/module.h>
 #include <asm/dtrace_arch.h>
 
 /*
@@ -21,6 +22,7 @@ extern void *dtrace_sdt_probes __attribute__((weak));
 
 extern void dtrace_sdt_init(void);
 extern void dtrace_sdt_register(struct module *);
+extern void dtrace_sdt_register_module(struct module *);
 extern void dtrace_sdt_exit(void);
 
 /*
index 415967fd56808450d3bb8d4c6cbbd728f6f8cd50..c8076468d7094d9af63cd4bf52a841a4f1171935 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/binfmts.h>
 #include <linux/dtrace_cpu.h>
 #include <linux/dtrace_os.h>
+#include <linux/dtrace_sdt.h>
 #include <linux/fs.h>
 #include <linux/hardirq.h>
 #include <linux/interrupt.h>
@@ -22,7 +23,6 @@
 #include <linux/workqueue.h>
 #include <linux/mm.h>
 #include <asm/ptrace.h>
-#include "dtrace_sdt.h"
 
 #if defined(CONFIG_DT_FASTTRAP) || defined(CONFIG_DT_FASTTRAP_MODULE)
 # include <linux/uprobes.h>
index ce953b85df8e557928ca5302d0619e7e2ad98067..5e4f189df1572c03a5c06b88fbcf8b0f22519df5 100644 (file)
@@ -9,13 +9,13 @@
 #include <linux/memory.h>
 #include <linux/module.h>
 #include <linux/dtrace_os.h>
+#include <linux/dtrace_sdt.h>
 #include <linux/sdt.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/vmalloc.h>
 #include <asm-generic/bitsperlong.h>
 #include <asm-generic/sections.h>
-#include "dtrace_sdt.h"
 
 const char             *sdt_prefix = "__dtrace_probe_";
 
@@ -125,25 +125,14 @@ static int __init nosdt(char *str)
 
 early_param("nosdt", nosdt);
 
-static int dtrace_mod_notifier(struct notifier_block *nb, unsigned long val,
-                              void *args)
+void dtrace_sdt_register_module(struct module *mp)
 {
-       struct module           *mp = args;
        int                     i, cnt;
        sdt_probedesc_t         *sdp;
        asm_instr_t             **addrs;
 
-       /*
-        * We only need to capture modules in the COMING state, we need a valid
-        * module structure as argument, and the module needs to actually have
-        * SDT probes.  If not, ignore...
-        */
-       if (val != MODULE_STATE_COMING)
-               return NOTIFY_DONE;
-       if (!mp)
-               return NOTIFY_DONE;
        if (mp->sdt_probec == 0 || mp->sdt_probes == NULL)
-               return NOTIFY_DONE;
+               return;
 
        /*
         * Create a list of addresses (SDT probe locations) that need to be
@@ -154,7 +143,7 @@ static int dtrace_mod_notifier(struct notifier_block *nb, unsigned long val,
        if (addrs == NULL) {
                pr_warning("%s: cannot allocate SDT probe address list (%s)\n",
                           __func__, mp->name);
-               return NOTIFY_DONE;
+               return;
        }
 
        for (i = cnt = 0, sdp = mp->sdt_probes; i < mp->sdt_probec;
@@ -178,18 +167,11 @@ static int dtrace_mod_notifier(struct notifier_block *nb, unsigned long val,
        dtrace_sdt_nop_multi(addrs, cnt);
 
        vfree(addrs);
-
-       return NOTIFY_DONE;
 }
 
-static struct notifier_block   dtrace_modfix = {
-       .notifier_call = dtrace_mod_notifier,
-};
-
 void dtrace_sdt_init(void)
 {
        dtrace_sdt_init_arch();
-       register_module_notifier(&dtrace_modfix);
 }
 
 #if defined(CONFIG_DT_DT_PERF) || defined(CONFIG_DT_DT_PERF_MODULE)
index be8c504975e83b1439f0e50175617b2329347228..fb4149f42423b2ae455f844e45d99590fc629295 100644 (file)
@@ -51,6 +51,7 @@
 #include <asm/mmu_context.h>
 #include <linux/license.h>
 #include <asm/sections.h>
+#include <linux/dtrace_sdt.h>
 #include <linux/tracepoint.h>
 #include <linux/ftrace.h>
 #include <linux/async.h>
@@ -3201,6 +3202,8 @@ static int complete_formation(struct module *mod, struct load_info *info)
 {
        int err;
 
+       dtrace_sdt_register_module(mod);
+
        mutex_lock(&module_mutex);
 
        /* Find duplicate symbols (must be called under lock). */