Commit 705d43db authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/livepatching

Pull livepatching fixes from Jiri Kosina:

 - regression (from 4.4) fix for ordering issue, introduced by an
   earlier ftrace change, that broke live patching of modules.

   The fix replaces the ftrace module notifier by direct call in order
   to make the ordering guaranteed and well-defined.  The patch, from
   Jessica Yu, has been acked both by Steven and Rusty

 - error message fix from Miroslav Benes

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/livepatching:
  ftrace/module: remove ftrace module notifier
  livepatch: change the error message in asm/livepatch.h header files
parents dd8fc10e 7dcd182b
...@@ -37,7 +37,7 @@ static inline void klp_arch_set_pc(struct pt_regs *regs, unsigned long ip) ...@@ -37,7 +37,7 @@ static inline void klp_arch_set_pc(struct pt_regs *regs, unsigned long ip)
regs->psw.addr = ip; regs->psw.addr = ip;
} }
#else #else
#error Live patching support is disabled; check CONFIG_LIVEPATCH #error Include linux/livepatch.h, not asm/livepatch.h
#endif #endif
#endif #endif
...@@ -41,7 +41,7 @@ static inline void klp_arch_set_pc(struct pt_regs *regs, unsigned long ip) ...@@ -41,7 +41,7 @@ static inline void klp_arch_set_pc(struct pt_regs *regs, unsigned long ip)
regs->ip = ip; regs->ip = ip;
} }
#else #else
#error Live patching support is disabled; check CONFIG_LIVEPATCH #error Include linux/livepatch.h, not asm/livepatch.h
#endif #endif
#endif /* _ASM_X86_LIVEPATCH_H */ #endif /* _ASM_X86_LIVEPATCH_H */
...@@ -603,6 +603,7 @@ extern int ftrace_arch_read_dyn_info(char *buf, int size); ...@@ -603,6 +603,7 @@ extern int ftrace_arch_read_dyn_info(char *buf, int size);
extern int skip_trace(unsigned long ip); extern int skip_trace(unsigned long ip);
extern void ftrace_module_init(struct module *mod); extern void ftrace_module_init(struct module *mod);
extern void ftrace_module_enable(struct module *mod);
extern void ftrace_release_mod(struct module *mod); extern void ftrace_release_mod(struct module *mod);
extern void ftrace_disable_daemon(void); extern void ftrace_disable_daemon(void);
...@@ -612,8 +613,9 @@ static inline int skip_trace(unsigned long ip) { return 0; } ...@@ -612,8 +613,9 @@ static inline int skip_trace(unsigned long ip) { return 0; }
static inline int ftrace_force_update(void) { return 0; } static inline int ftrace_force_update(void) { return 0; }
static inline void ftrace_disable_daemon(void) { } static inline void ftrace_disable_daemon(void) { }
static inline void ftrace_enable_daemon(void) { } static inline void ftrace_enable_daemon(void) { }
static inline void ftrace_release_mod(struct module *mod) {} static inline void ftrace_module_init(struct module *mod) { }
static inline void ftrace_module_init(struct module *mod) {} static inline void ftrace_module_enable(struct module *mod) { }
static inline void ftrace_release_mod(struct module *mod) { }
static inline __init int register_ftrace_command(struct ftrace_func_command *cmd) static inline __init int register_ftrace_command(struct ftrace_func_command *cmd)
{ {
return -EINVAL; return -EINVAL;
......
...@@ -984,6 +984,8 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user, ...@@ -984,6 +984,8 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
mod->exit(); mod->exit();
blocking_notifier_call_chain(&module_notify_list, blocking_notifier_call_chain(&module_notify_list,
MODULE_STATE_GOING, mod); MODULE_STATE_GOING, mod);
ftrace_release_mod(mod);
async_synchronize_full(); async_synchronize_full();
/* Store the name of the last unloaded module for diagnostic purposes */ /* Store the name of the last unloaded module for diagnostic purposes */
...@@ -3313,6 +3315,7 @@ static noinline int do_init_module(struct module *mod) ...@@ -3313,6 +3315,7 @@ static noinline int do_init_module(struct module *mod)
module_put(mod); module_put(mod);
blocking_notifier_call_chain(&module_notify_list, blocking_notifier_call_chain(&module_notify_list,
MODULE_STATE_GOING, mod); MODULE_STATE_GOING, mod);
ftrace_release_mod(mod);
free_module(mod); free_module(mod);
wake_up_all(&module_wq); wake_up_all(&module_wq);
return ret; return ret;
...@@ -3389,6 +3392,7 @@ static int complete_formation(struct module *mod, struct load_info *info) ...@@ -3389,6 +3392,7 @@ static int complete_formation(struct module *mod, struct load_info *info)
mod->state = MODULE_STATE_COMING; mod->state = MODULE_STATE_COMING;
mutex_unlock(&module_mutex); mutex_unlock(&module_mutex);
ftrace_module_enable(mod);
blocking_notifier_call_chain(&module_notify_list, blocking_notifier_call_chain(&module_notify_list,
MODULE_STATE_COMING, mod); MODULE_STATE_COMING, mod);
return 0; return 0;
......
...@@ -4961,7 +4961,7 @@ void ftrace_release_mod(struct module *mod) ...@@ -4961,7 +4961,7 @@ void ftrace_release_mod(struct module *mod)
mutex_unlock(&ftrace_lock); mutex_unlock(&ftrace_lock);
} }
static void ftrace_module_enable(struct module *mod) void ftrace_module_enable(struct module *mod)
{ {
struct dyn_ftrace *rec; struct dyn_ftrace *rec;
struct ftrace_page *pg; struct ftrace_page *pg;
...@@ -5038,38 +5038,8 @@ void ftrace_module_init(struct module *mod) ...@@ -5038,38 +5038,8 @@ void ftrace_module_init(struct module *mod)
ftrace_process_locs(mod, mod->ftrace_callsites, ftrace_process_locs(mod, mod->ftrace_callsites,
mod->ftrace_callsites + mod->num_ftrace_callsites); mod->ftrace_callsites + mod->num_ftrace_callsites);
} }
static int ftrace_module_notify(struct notifier_block *self,
unsigned long val, void *data)
{
struct module *mod = data;
switch (val) {
case MODULE_STATE_COMING:
ftrace_module_enable(mod);
break;
case MODULE_STATE_GOING:
ftrace_release_mod(mod);
break;
default:
break;
}
return 0;
}
#else
static int ftrace_module_notify(struct notifier_block *self,
unsigned long val, void *data)
{
return 0;
}
#endif /* CONFIG_MODULES */ #endif /* CONFIG_MODULES */
struct notifier_block ftrace_module_nb = {
.notifier_call = ftrace_module_notify,
.priority = INT_MIN, /* Run after anything that can remove kprobes */
};
void __init ftrace_init(void) void __init ftrace_init(void)
{ {
extern unsigned long __start_mcount_loc[]; extern unsigned long __start_mcount_loc[];
...@@ -5098,10 +5068,6 @@ void __init ftrace_init(void) ...@@ -5098,10 +5068,6 @@ void __init ftrace_init(void)
__start_mcount_loc, __start_mcount_loc,
__stop_mcount_loc); __stop_mcount_loc);
ret = register_module_notifier(&ftrace_module_nb);
if (ret)
pr_warning("Failed to register trace ftrace module exit notifier\n");
set_ftrace_early_filters(); set_ftrace_early_filters();
return; return;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment