Skip to content

Commit 7dcd182

Browse files
Jessica YuJiri Kosina
authored andcommitted
ftrace/module: remove ftrace module notifier
Remove the ftrace module notifier in favor of directly calling ftrace_module_enable() and ftrace_release_mod() in the module loader. Hard-coding the function calls directly in the module loader removes dependence on the module notifier call chain and provides better visibility and control over what gets called when, which is important to kernel utilities such as livepatch. This fixes a notifier ordering issue in which the ftrace module notifier (and hence ftrace_module_enable()) for coming modules was being called after klp_module_notify(), which caused livepatch modules to initialize incorrectly. This patch removes dependence on the module notifier call chain in favor of hard coding the corresponding function calls in the module loader. This ensures that ftrace and livepatch code get called in the correct order on patch module load and unload. Fixes: 5156dca ("ftrace: Fix the race between ftrace and insmod") Signed-off-by: Jessica Yu <jeyu@redhat.com> Reviewed-by: Steven Rostedt <rostedt@goodmis.org> Reviewed-by: Petr Mladek <pmladek@suse.cz> Acked-by: Rusty Russell <rusty@rustcorp.com.au> Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com> Reviewed-by: Miroslav Benes <mbenes@suse.cz> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
1 parent 383bf44 commit 7dcd182

File tree

3 files changed

+9
-37
lines changed

3 files changed

+9
-37
lines changed

include/linux/ftrace.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,7 @@ extern int ftrace_arch_read_dyn_info(char *buf, int size);
604604

605605
extern int skip_trace(unsigned long ip);
606606
extern void ftrace_module_init(struct module *mod);
607+
extern void ftrace_module_enable(struct module *mod);
607608
extern void ftrace_release_mod(struct module *mod);
608609

609610
extern void ftrace_disable_daemon(void);
@@ -613,8 +614,9 @@ static inline int skip_trace(unsigned long ip) { return 0; }
613614
static inline int ftrace_force_update(void) { return 0; }
614615
static inline void ftrace_disable_daemon(void) { }
615616
static inline void ftrace_enable_daemon(void) { }
616-
static inline void ftrace_release_mod(struct module *mod) {}
617-
static inline void ftrace_module_init(struct module *mod) {}
617+
static inline void ftrace_module_init(struct module *mod) { }
618+
static inline void ftrace_module_enable(struct module *mod) { }
619+
static inline void ftrace_release_mod(struct module *mod) { }
618620
static inline __init int register_ftrace_command(struct ftrace_func_command *cmd)
619621
{
620622
return -EINVAL;

kernel/module.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -981,6 +981,8 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
981981
mod->exit();
982982
blocking_notifier_call_chain(&module_notify_list,
983983
MODULE_STATE_GOING, mod);
984+
ftrace_release_mod(mod);
985+
984986
async_synchronize_full();
985987

986988
/* Store the name of the last unloaded module for diagnostic purposes */
@@ -3295,6 +3297,7 @@ static noinline int do_init_module(struct module *mod)
32953297
module_put(mod);
32963298
blocking_notifier_call_chain(&module_notify_list,
32973299
MODULE_STATE_GOING, mod);
3300+
ftrace_release_mod(mod);
32983301
free_module(mod);
32993302
wake_up_all(&module_wq);
33003303
return ret;
@@ -3371,6 +3374,7 @@ static int complete_formation(struct module *mod, struct load_info *info)
33713374
mod->state = MODULE_STATE_COMING;
33723375
mutex_unlock(&module_mutex);
33733376

3377+
ftrace_module_enable(mod);
33743378
blocking_notifier_call_chain(&module_notify_list,
33753379
MODULE_STATE_COMING, mod);
33763380
return 0;

kernel/trace/ftrace.c

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4961,7 +4961,7 @@ void ftrace_release_mod(struct module *mod)
49614961
mutex_unlock(&ftrace_lock);
49624962
}
49634963

4964-
static void ftrace_module_enable(struct module *mod)
4964+
void ftrace_module_enable(struct module *mod)
49654965
{
49664966
struct dyn_ftrace *rec;
49674967
struct ftrace_page *pg;
@@ -5038,38 +5038,8 @@ void ftrace_module_init(struct module *mod)
50385038
ftrace_process_locs(mod, mod->ftrace_callsites,
50395039
mod->ftrace_callsites + mod->num_ftrace_callsites);
50405040
}
5041-
5042-
static int ftrace_module_notify(struct notifier_block *self,
5043-
unsigned long val, void *data)
5044-
{
5045-
struct module *mod = data;
5046-
5047-
switch (val) {
5048-
case MODULE_STATE_COMING:
5049-
ftrace_module_enable(mod);
5050-
break;
5051-
case MODULE_STATE_GOING:
5052-
ftrace_release_mod(mod);
5053-
break;
5054-
default:
5055-
break;
5056-
}
5057-
5058-
return 0;
5059-
}
5060-
#else
5061-
static int ftrace_module_notify(struct notifier_block *self,
5062-
unsigned long val, void *data)
5063-
{
5064-
return 0;
5065-
}
50665041
#endif /* CONFIG_MODULES */
50675042

5068-
struct notifier_block ftrace_module_nb = {
5069-
.notifier_call = ftrace_module_notify,
5070-
.priority = INT_MIN, /* Run after anything that can remove kprobes */
5071-
};
5072-
50735043
void __init ftrace_init(void)
50745044
{
50755045
extern unsigned long __start_mcount_loc[];
@@ -5098,10 +5068,6 @@ void __init ftrace_init(void)
50985068
__start_mcount_loc,
50995069
__stop_mcount_loc);
51005070

5101-
ret = register_module_notifier(&ftrace_module_nb);
5102-
if (ret)
5103-
pr_warning("Failed to register trace ftrace module exit notifier\n");
5104-
51055071
set_ftrace_early_filters();
51065072

51075073
return;

0 commit comments

Comments
 (0)