Commit 2aafe1a4d451866e3e7b476e2fa0813b69b313c1

Authored by Linus Torvalds

Merge tag 'trace-fixes-v3.15-rc2' of git://git.kernel.org/pub/scm/linux/kernel/g…

…it/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()

Showing 3 changed files Side-by-side Diff

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