ftrace/module: Hardcode ftrace_module_init() call into load_module()

A race exists between module loading and enabling of function tracer.

CPU 1 CPU 2
----- -----
load_module()
module->state = MODULE_STATE_COMING

register_ftrace_function()
mutex_lock(&ftrace_lock);
ftrace_startup()
update_ftrace_function();
ftrace_arch_code_modify_prepare()
set_all_module_text_rw();
<enables-ftrace>
ftrace_arch_code_modify_post_process()
set_all_module_text_ro();

[ here all module text is set to RO,
including the module that is
loading!! ]

blocking_notifier_call_chain(MODULE_STATE_COMING);
ftrace_init_module()

[ tries to modify code, but it's RO, and fails!
ftrace_bug() is called]

When this race happens, ftrace_bug() will produces a nasty warning and
all of the function tracing features will be disabled until reboot.

The simple solution is to treate module load the same way the core
kernel is treated at boot. To hardcode the ftrace function modification
of converting calls to mcount into nops. This is done in init/main.c
there's no reason it could not be done in load_module(). This gives
a better control of the changes and doesn't tie the state of the
module to its notifiers as much. Ftrace is special, it needs to be
treated as such.

The reason this would work, is that the ftrace_module_init() would be
called while the module is in MODULE_STATE_UNFORMED, which is ignored
by the set_all_module_text_ro() call.

Link: http://lkml.kernel.org/r/1395637826-3312-1-git-send-email-indou.takao@jp.fujitsu.com

Reported-by: Takao Indoh <indou.takao@jp.fujitsu.com>
Acked-by: Rusty Russell <rusty@rustcorp.com.au>
Cc: stable@vger.kernel.org # 2.6.38+
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>

+9 -23
+2
include/linux/ftrace.h
··· 535 extern int ftrace_arch_read_dyn_info(char *buf, int size); 536 537 extern int skip_trace(unsigned long ip); 538 539 extern void ftrace_disable_daemon(void); 540 extern void ftrace_enable_daemon(void); ··· 545 static inline void ftrace_disable_daemon(void) { } 546 static inline void ftrace_enable_daemon(void) { } 547 static inline void ftrace_release_mod(struct module *mod) {} 548 static inline __init int register_ftrace_command(struct ftrace_func_command *cmd) 549 { 550 return -EINVAL;
··· 535 extern int ftrace_arch_read_dyn_info(char *buf, int size); 536 537 extern int skip_trace(unsigned long ip); 538 + extern void ftrace_module_init(struct module *mod); 539 540 extern void ftrace_disable_daemon(void); 541 extern void ftrace_enable_daemon(void); ··· 544 static inline void ftrace_disable_daemon(void) { } 545 static inline void ftrace_enable_daemon(void) { } 546 static inline void ftrace_release_mod(struct module *mod) {} 547 + static inline void ftrace_module_init(struct module *mod) {} 548 static inline __init int register_ftrace_command(struct ftrace_func_command *cmd) 549 { 550 return -EINVAL;
+3
kernel/module.c
··· 3271 3272 dynamic_debug_setup(info->debug, info->num_debug); 3273 3274 /* Finally it's fully formed, ready to start executing. */ 3275 err = complete_formation(mod, info); 3276 if (err)
··· 3271 3272 dynamic_debug_setup(info->debug, info->num_debug); 3273 3274 + /* Ftrace init must be called in the MODULE_STATE_UNFORMED state */ 3275 + ftrace_module_init(mod); 3276 + 3277 /* Finally it's fully formed, ready to start executing. */ 3278 err = complete_formation(mod, info); 3279 if (err)
+4 -23
kernel/trace/ftrace.c
··· 4330 ftrace_process_locs(mod, start, end); 4331 } 4332 4333 - static int ftrace_module_notify_enter(struct notifier_block *self, 4334 - unsigned long val, void *data) 4335 { 4336 - struct module *mod = data; 4337 - 4338 - if (val == MODULE_STATE_COMING) 4339 - ftrace_init_module(mod, mod->ftrace_callsites, 4340 - mod->ftrace_callsites + 4341 - mod->num_ftrace_callsites); 4342 - return 0; 4343 } 4344 4345 static int ftrace_module_notify_exit(struct notifier_block *self, ··· 4348 return 0; 4349 } 4350 #else 4351 - static int ftrace_module_notify_enter(struct notifier_block *self, 4352 - unsigned long val, void *data) 4353 - { 4354 - return 0; 4355 - } 4356 static int ftrace_module_notify_exit(struct notifier_block *self, 4357 unsigned long val, void *data) 4358 { 4359 return 0; 4360 } 4361 #endif /* CONFIG_MODULES */ 4362 - 4363 - struct notifier_block ftrace_module_enter_nb = { 4364 - .notifier_call = ftrace_module_notify_enter, 4365 - .priority = INT_MAX, /* Run before anything that can use kprobes */ 4366 - }; 4367 4368 struct notifier_block ftrace_module_exit_nb = { 4369 .notifier_call = ftrace_module_notify_exit, ··· 4387 ret = ftrace_process_locs(NULL, 4388 __start_mcount_loc, 4389 __stop_mcount_loc); 4390 - 4391 - ret = register_module_notifier(&ftrace_module_enter_nb); 4392 - if (ret) 4393 - pr_warning("Failed to register trace ftrace module enter notifier\n"); 4394 4395 ret = register_module_notifier(&ftrace_module_exit_nb); 4396 if (ret)
··· 4330 ftrace_process_locs(mod, start, end); 4331 } 4332 4333 + void ftrace_module_init(struct module *mod) 4334 { 4335 + ftrace_init_module(mod, mod->ftrace_callsites, 4336 + mod->ftrace_callsites + 4337 + mod->num_ftrace_callsites); 4338 } 4339 4340 static int ftrace_module_notify_exit(struct notifier_block *self, ··· 4353 return 0; 4354 } 4355 #else 4356 static int ftrace_module_notify_exit(struct notifier_block *self, 4357 unsigned long val, void *data) 4358 { 4359 return 0; 4360 } 4361 #endif /* CONFIG_MODULES */ 4362 4363 struct notifier_block ftrace_module_exit_nb = { 4364 .notifier_call = ftrace_module_notify_exit, ··· 4402 ret = ftrace_process_locs(NULL, 4403 __start_mcount_loc, 4404 __stop_mcount_loc); 4405 4406 ret = register_module_notifier(&ftrace_module_exit_nb); 4407 if (ret)