History

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

Steven Rostedt (Red Hat) committed 12 years ago

Commit a949ae51 parent a798c103 files · +9 −23Browse files

Showing the changes to kernel/module.c (1 of 3 files). Show all

Unified · Split

kernel/module.c+3−0
@@ -3271,6 +3271,9 @@ static int load_module(struct load_info *info, const char __user *uargs, · 3270 unmodified lines
32713271
32723272 dynamic_debug_setup(info->debug, info->num_debug);
32733273
3274+ /* Ftrace init must be called in the MODULE_STATE_UNFORMED state */
3275+ ftrace_module_init(mod);
3276+
32743277 /* Finally it's fully formed, ready to start executing. */
32753278 err = complete_formation(mod, info);
32763279 if (err)