summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMasami Hiramatsu <mhiramat@kernel.org>2019-07-25 02:24:37 -0400
committerSteven Rostedt (VMware) <rostedt@goodmis.org>2019-08-31 12:19:10 -0400
commit0bc11ed5ab60c135aa764a62c02cd5ea68289de4 (patch)
tree503be167bf756a0f32c4fbe11da3c41895697049
parentc68c9ec1c52e5bcd221eb09bc5344ad4f407b204 (diff)
kprobes: Allow kprobes coexist with livepatch
Allow kprobes which do not modify regs->ip, coexist with livepatch by dropping FTRACE_OPS_FL_IPMODIFY from ftrace_ops. User who wants to modify regs->ip (e.g. function fault injection) must set a dummy post_handler to its kprobes when registering. However, if such regs->ip modifying kprobes is set on a function, that function can not be livepatched. Link: http://lkml.kernel.org/r/156403587671.30117.5233558741694155985.stgit@devnote2 Acked-by: Joe Lawrence <joe.lawrence@redhat.com> Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
-rw-r--r--kernel/kprobes.c56
1 files changed, 40 insertions, 16 deletions
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index d9770a5393c8..f57deec96ba1 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -962,8 +962,15 @@ static struct kprobe *alloc_aggr_kprobe(struct kprobe *p)
962#ifdef CONFIG_KPROBES_ON_FTRACE 962#ifdef CONFIG_KPROBES_ON_FTRACE
963static struct ftrace_ops kprobe_ftrace_ops __read_mostly = { 963static struct ftrace_ops kprobe_ftrace_ops __read_mostly = {
964 .func = kprobe_ftrace_handler, 964 .func = kprobe_ftrace_handler,
965 .flags = FTRACE_OPS_FL_SAVE_REGS,
966};
967
968static struct ftrace_ops kprobe_ipmodify_ops __read_mostly = {
969 .func = kprobe_ftrace_handler,
965 .flags = FTRACE_OPS_FL_SAVE_REGS | FTRACE_OPS_FL_IPMODIFY, 970 .flags = FTRACE_OPS_FL_SAVE_REGS | FTRACE_OPS_FL_IPMODIFY,
966}; 971};
972
973static int kprobe_ipmodify_enabled;
967static int kprobe_ftrace_enabled; 974static int kprobe_ftrace_enabled;
968 975
969/* Must ensure p->addr is really on ftrace */ 976/* Must ensure p->addr is really on ftrace */
@@ -976,58 +983,75 @@ static int prepare_kprobe(struct kprobe *p)
976} 983}
977 984
978/* Caller must lock kprobe_mutex */ 985/* Caller must lock kprobe_mutex */
979static int arm_kprobe_ftrace(struct kprobe *p) 986static int __arm_kprobe_ftrace(struct kprobe *p, struct ftrace_ops *ops,
987 int *cnt)
980{ 988{
981 int ret = 0; 989 int ret = 0;
982 990
983 ret = ftrace_set_filter_ip(&kprobe_ftrace_ops, 991 ret = ftrace_set_filter_ip(ops, (unsigned long)p->addr, 0, 0);
984 (unsigned long)p->addr, 0, 0);
985 if (ret) { 992 if (ret) {
986 pr_debug("Failed to arm kprobe-ftrace at %pS (%d)\n", 993 pr_debug("Failed to arm kprobe-ftrace at %pS (%d)\n",
987 p->addr, ret); 994 p->addr, ret);
988 return ret; 995 return ret;
989 } 996 }
990 997
991 if (kprobe_ftrace_enabled == 0) { 998 if (*cnt == 0) {
992 ret = register_ftrace_function(&kprobe_ftrace_ops); 999 ret = register_ftrace_function(ops);
993 if (ret) { 1000 if (ret) {
994 pr_debug("Failed to init kprobe-ftrace (%d)\n", ret); 1001 pr_debug("Failed to init kprobe-ftrace (%d)\n", ret);
995 goto err_ftrace; 1002 goto err_ftrace;
996 } 1003 }
997 } 1004 }
998 1005
999 kprobe_ftrace_enabled++; 1006 (*cnt)++;
1000 return ret; 1007 return ret;
1001 1008
1002err_ftrace: 1009err_ftrace:
1003 /* 1010 /*
1004 * Note: Since kprobe_ftrace_ops has IPMODIFY set, and ftrace requires a 1011 * At this point, sinec ops is not registered, we should be sefe from
1005 * non-empty filter_hash for IPMODIFY ops, we're safe from an accidental 1012 * registering empty filter.
1006 * empty filter_hash which would undesirably trace all functions.
1007 */ 1013 */
1008 ftrace_set_filter_ip(&kprobe_ftrace_ops, (unsigned long)p->addr, 1, 0); 1014 ftrace_set_filter_ip(ops, (unsigned long)p->addr, 1, 0);
1009 return ret; 1015 return ret;
1010} 1016}
1011 1017
1018static int arm_kprobe_ftrace(struct kprobe *p)
1019{
1020 bool ipmodify = (p->post_handler != NULL);
1021
1022 return __arm_kprobe_ftrace(p,
1023 ipmodify ? &kprobe_ipmodify_ops : &kprobe_ftrace_ops,
1024 ipmodify ? &kprobe_ipmodify_enabled : &kprobe_ftrace_enabled);
1025}
1026
1012/* Caller must lock kprobe_mutex */ 1027/* Caller must lock kprobe_mutex */
1013static int disarm_kprobe_ftrace(struct kprobe *p) 1028static int __disarm_kprobe_ftrace(struct kprobe *p, struct ftrace_ops *ops,
1029 int *cnt)
1014{ 1030{
1015 int ret = 0; 1031 int ret = 0;
1016 1032
1017 if (kprobe_ftrace_enabled == 1) { 1033 if (*cnt == 1) {
1018 ret = unregister_ftrace_function(&kprobe_ftrace_ops); 1034 ret = unregister_ftrace_function(ops);
1019 if (WARN(ret < 0, "Failed to unregister kprobe-ftrace (%d)\n", ret)) 1035 if (WARN(ret < 0, "Failed to unregister kprobe-ftrace (%d)\n", ret))
1020 return ret; 1036 return ret;
1021 } 1037 }
1022 1038
1023 kprobe_ftrace_enabled--; 1039 (*cnt)--;
1024 1040
1025 ret = ftrace_set_filter_ip(&kprobe_ftrace_ops, 1041 ret = ftrace_set_filter_ip(ops, (unsigned long)p->addr, 1, 0);
1026 (unsigned long)p->addr, 1, 0);
1027 WARN_ONCE(ret < 0, "Failed to disarm kprobe-ftrace at %pS (%d)\n", 1042 WARN_ONCE(ret < 0, "Failed to disarm kprobe-ftrace at %pS (%d)\n",
1028 p->addr, ret); 1043 p->addr, ret);
1029 return ret; 1044 return ret;
1030} 1045}
1046
1047static int disarm_kprobe_ftrace(struct kprobe *p)
1048{
1049 bool ipmodify = (p->post_handler != NULL);
1050
1051 return __disarm_kprobe_ftrace(p,
1052 ipmodify ? &kprobe_ipmodify_ops : &kprobe_ftrace_ops,
1053 ipmodify ? &kprobe_ipmodify_enabled : &kprobe_ftrace_enabled);
1054}
1031#else /* !CONFIG_KPROBES_ON_FTRACE */ 1055#else /* !CONFIG_KPROBES_ON_FTRACE */
1032#define prepare_kprobe(p) arch_prepare_kprobe(p) 1056#define prepare_kprobe(p) arch_prepare_kprobe(p)
1033#define arm_kprobe_ftrace(p) (-ENODEV) 1057#define arm_kprobe_ftrace(p) (-ENODEV)