summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-04-28 16:57:51 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2014-04-28 16:57:51 -0700
commit2aafe1a4d451866e3e7b476e2fa0813b69b313c1 (patch)
tree71d6d128a9a54940d707a9534ff733e2c560d6f3 /kernel
parent87c7662bea584d5e495e97a59c20b9abaac4eee8 (diff)
parenta949ae560a511fe4e3adf48fa44fefded93e5c2b (diff)
downloadlwn-2aafe1a4d451866e3e7b476e2fa0813b69b313c1.tar.gz
lwn-2aafe1a4d451866e3e7b476e2fa0813b69b313c1.zip
Merge tag 'trace-fixes-v3.15-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace
Pull ftrace bugfix from Steven Rostedt: "Takao Indoh reported that he was able to cause a ftrace bug while loading a module and enabling function tracing at the same time. He uncovered a race where the module when loaded will convert the calls to mcount into nops, and expects the module's text to be RW. But when function tracing is enabled, it will convert all kernel text (core and module) from RO to RW to convert the nops to calls to ftrace to record the function. After the convertion, it will convert all the text back from RW to RO. The issue is, it will also convert the module's text that is loading. If it converts it to RO before ftrace does its conversion, it will cause ftrace to fail and require a reboot to fix it again. This patch moves the ftrace module update that converts calls to mcount into nops to be done when the module state is still MODULE_STATE_UNFORMED. This will ignore the module when the text is being converted from RW back to RO" * tag 'trace-fixes-v3.15-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace: ftrace/module: Hardcode ftrace_module_init() call into load_module()
Diffstat (limited to 'kernel')
-rw-r--r--kernel/module.c3
-rw-r--r--kernel/trace/ftrace.c27
2 files changed, 7 insertions, 23 deletions
diff --git a/kernel/module.c b/kernel/module.c
index 11869408f79b..5f14fec9f825 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -3271,6 +3271,9 @@ static int load_module(struct load_info *info, const char __user *uargs,
dynamic_debug_setup(info->debug, info->num_debug);
+ /* Ftrace init must be called in the MODULE_STATE_UNFORMED state */
+ ftrace_module_init(mod);
+
/* Finally it's fully formed, ready to start executing. */
err = complete_formation(mod, info);
if (err)
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 1fd4b9479210..4a54a25afa2f 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -4330,16 +4330,11 @@ static void ftrace_init_module(struct module *mod,
ftrace_process_locs(mod, start, end);
}
-static int ftrace_module_notify_enter(struct notifier_block *self,
- unsigned long val, void *data)
+void ftrace_module_init(struct module *mod)
{
- struct module *mod = data;
-
- if (val == MODULE_STATE_COMING)
- ftrace_init_module(mod, mod->ftrace_callsites,
- mod->ftrace_callsites +
- mod->num_ftrace_callsites);
- return 0;
+ ftrace_init_module(mod, mod->ftrace_callsites,
+ mod->ftrace_callsites +
+ mod->num_ftrace_callsites);
}
static int ftrace_module_notify_exit(struct notifier_block *self,
@@ -4353,11 +4348,6 @@ static int ftrace_module_notify_exit(struct notifier_block *self,
return 0;
}
#else
-static int ftrace_module_notify_enter(struct notifier_block *self,
- unsigned long val, void *data)
-{
- return 0;
-}
static int ftrace_module_notify_exit(struct notifier_block *self,
unsigned long val, void *data)
{
@@ -4365,11 +4355,6 @@ static int ftrace_module_notify_exit(struct notifier_block *self,
}
#endif /* CONFIG_MODULES */
-struct notifier_block ftrace_module_enter_nb = {
- .notifier_call = ftrace_module_notify_enter,
- .priority = INT_MAX, /* Run before anything that can use kprobes */
-};
-
struct notifier_block ftrace_module_exit_nb = {
.notifier_call = ftrace_module_notify_exit,
.priority = INT_MIN, /* Run after anything that can remove kprobes */
@@ -4403,10 +4388,6 @@ void __init ftrace_init(void)
__start_mcount_loc,
__stop_mcount_loc);
- ret = register_module_notifier(&ftrace_module_enter_nb);
- if (ret)
- pr_warning("Failed to register trace ftrace module enter notifier\n");
-
ret = register_module_notifier(&ftrace_module_exit_nb);
if (ret)
pr_warning("Failed to register trace ftrace module exit notifier\n");