aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-02-18 19:34:15 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-02-18 19:34:15 -0500
commit705d43dbe10d6e213a75187ac92b61f9bd00af0b (patch)
treeaf1d62843c7140eb6751f6fd75df5425820f6e8f
parentdd8fc10e606127e2dffdb6704e7ec203c86a214d (diff)
parent7dcd182bec271ab341b05b66b6006995795fc0e7 (diff)
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
-rw-r--r--arch/s390/include/asm/livepatch.h2
-rw-r--r--arch/x86/include/asm/livepatch.h2
-rw-r--r--include/linux/ftrace.h6
-rw-r--r--kernel/module.c4
-rw-r--r--kernel/trace/ftrace.c36
5 files changed, 11 insertions, 39 deletions
diff --git a/arch/s390/include/asm/livepatch.h b/arch/s390/include/asm/livepatch.h
index 7aa799134a11..a52b6cca873d 100644
--- a/arch/s390/include/asm/livepatch.h
+++ b/arch/s390/include/asm/livepatch.h
@@ -37,7 +37,7 @@ static inline void klp_arch_set_pc(struct pt_regs *regs, unsigned long ip)
37 regs->psw.addr = ip; 37 regs->psw.addr = ip;
38} 38}
39#else 39#else
40#error Live patching support is disabled; check CONFIG_LIVEPATCH 40#error Include linux/livepatch.h, not asm/livepatch.h
41#endif 41#endif
42 42
43#endif 43#endif
diff --git a/arch/x86/include/asm/livepatch.h b/arch/x86/include/asm/livepatch.h
index 19c099afa861..e795f5274217 100644
--- a/arch/x86/include/asm/livepatch.h
+++ b/arch/x86/include/asm/livepatch.h
@@ -41,7 +41,7 @@ static inline void klp_arch_set_pc(struct pt_regs *regs, unsigned long ip)
41 regs->ip = ip; 41 regs->ip = ip;
42} 42}
43#else 43#else
44#error Live patching support is disabled; check CONFIG_LIVEPATCH 44#error Include linux/livepatch.h, not asm/livepatch.h
45#endif 45#endif
46 46
47#endif /* _ASM_X86_LIVEPATCH_H */ 47#endif /* _ASM_X86_LIVEPATCH_H */
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 81de7123959d..c2b340e23f62 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -603,6 +603,7 @@ extern int ftrace_arch_read_dyn_info(char *buf, int size);
603 603
604extern int skip_trace(unsigned long ip); 604extern int skip_trace(unsigned long ip);
605extern void ftrace_module_init(struct module *mod); 605extern void ftrace_module_init(struct module *mod);
606extern void ftrace_module_enable(struct module *mod);
606extern void ftrace_release_mod(struct module *mod); 607extern void ftrace_release_mod(struct module *mod);
607 608
608extern void ftrace_disable_daemon(void); 609extern void ftrace_disable_daemon(void);
@@ -612,8 +613,9 @@ static inline int skip_trace(unsigned long ip) { return 0; }
612static inline int ftrace_force_update(void) { return 0; } 613static inline int ftrace_force_update(void) { return 0; }
613static inline void ftrace_disable_daemon(void) { } 614static inline void ftrace_disable_daemon(void) { }
614static inline void ftrace_enable_daemon(void) { } 615static inline void ftrace_enable_daemon(void) { }
615static inline void ftrace_release_mod(struct module *mod) {} 616static inline void ftrace_module_init(struct module *mod) { }
616static inline void ftrace_module_init(struct module *mod) {} 617static inline void ftrace_module_enable(struct module *mod) { }
618static inline void ftrace_release_mod(struct module *mod) { }
617static inline __init int register_ftrace_command(struct ftrace_func_command *cmd) 619static inline __init int register_ftrace_command(struct ftrace_func_command *cmd)
618{ 620{
619 return -EINVAL; 621 return -EINVAL;
diff --git a/kernel/module.c b/kernel/module.c
index 9537da37ce87..794ebe8e878d 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -984,6 +984,8 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
984 mod->exit(); 984 mod->exit();
985 blocking_notifier_call_chain(&module_notify_list, 985 blocking_notifier_call_chain(&module_notify_list,
986 MODULE_STATE_GOING, mod); 986 MODULE_STATE_GOING, mod);
987 ftrace_release_mod(mod);
988
987 async_synchronize_full(); 989 async_synchronize_full();
988 990
989 /* Store the name of the last unloaded module for diagnostic purposes */ 991 /* Store the name of the last unloaded module for diagnostic purposes */
@@ -3313,6 +3315,7 @@ fail:
3313 module_put(mod); 3315 module_put(mod);
3314 blocking_notifier_call_chain(&module_notify_list, 3316 blocking_notifier_call_chain(&module_notify_list,
3315 MODULE_STATE_GOING, mod); 3317 MODULE_STATE_GOING, mod);
3318 ftrace_release_mod(mod);
3316 free_module(mod); 3319 free_module(mod);
3317 wake_up_all(&module_wq); 3320 wake_up_all(&module_wq);
3318 return ret; 3321 return ret;
@@ -3389,6 +3392,7 @@ static int complete_formation(struct module *mod, struct load_info *info)
3389 mod->state = MODULE_STATE_COMING; 3392 mod->state = MODULE_STATE_COMING;
3390 mutex_unlock(&module_mutex); 3393 mutex_unlock(&module_mutex);
3391 3394
3395 ftrace_module_enable(mod);
3392 blocking_notifier_call_chain(&module_notify_list, 3396 blocking_notifier_call_chain(&module_notify_list,
3393 MODULE_STATE_COMING, mod); 3397 MODULE_STATE_COMING, mod);
3394 return 0; 3398 return 0;
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index eca592f977b2..57a6eea84694 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -4961,7 +4961,7 @@ void ftrace_release_mod(struct module *mod)
4961 mutex_unlock(&ftrace_lock); 4961 mutex_unlock(&ftrace_lock);
4962} 4962}
4963 4963
4964static void ftrace_module_enable(struct module *mod) 4964void ftrace_module_enable(struct module *mod)
4965{ 4965{
4966 struct dyn_ftrace *rec; 4966 struct dyn_ftrace *rec;
4967 struct ftrace_page *pg; 4967 struct ftrace_page *pg;
@@ -5038,38 +5038,8 @@ void ftrace_module_init(struct module *mod)
5038 ftrace_process_locs(mod, mod->ftrace_callsites, 5038 ftrace_process_locs(mod, mod->ftrace_callsites,
5039 mod->ftrace_callsites + mod->num_ftrace_callsites); 5039 mod->ftrace_callsites + mod->num_ftrace_callsites);
5040} 5040}
5041
5042static 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
5061static int ftrace_module_notify(struct notifier_block *self,
5062 unsigned long val, void *data)
5063{
5064 return 0;
5065}
5066#endif /* CONFIG_MODULES */ 5041#endif /* CONFIG_MODULES */
5067 5042
5068struct notifier_block ftrace_module_nb = {
5069 .notifier_call = ftrace_module_notify,
5070 .priority = INT_MIN, /* Run after anything that can remove kprobes */
5071};
5072
5073void __init ftrace_init(void) 5043void __init ftrace_init(void)
5074{ 5044{
5075 extern unsigned long __start_mcount_loc[]; 5045 extern unsigned long __start_mcount_loc[];
@@ -5098,10 +5068,6 @@ void __init ftrace_init(void)
5098 __start_mcount_loc, 5068 __start_mcount_loc,
5099 __stop_mcount_loc); 5069 __stop_mcount_loc);
5100 5070
5101 ret = register_module_notifier(&ftrace_module_nb);
5102 if (ret)
5103 pr_warning("Failed to register trace ftrace module exit notifier\n");
5104
5105 set_ftrace_early_filters(); 5071 set_ftrace_early_filters();
5106 5072
5107 return; 5073 return;