-
Notifications
You must be signed in to change notification settings - Fork 329
Description
When kprobes registers with ftrace before kpatch does for the same function, kprobes "wins", until the kprobe has been unregistered with ftrace. The kernel kprobe_ftrace_handler function changes regs->ip, which overwrites the value which kpatch had written.
Option 1:
diff --git a/arch/x86/kernel/kprobes/ftrace.c b/arch/x86/kernel/kprobes/ftrace.c
index 23ef5c5..5969176 100644
--- a/arch/x86/kernel/kprobes/ftrace.c
+++ b/arch/x86/kernel/kprobes/ftrace.c
@@ -57,6 +57,7 @@ void __kprobes kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
struct kprobe *p;
struct kprobe_ctlblk *kcb;
unsigned long flags;
+ unsigned long save_ip = regs->ip;
/* Disable irq for emulating a breakpoint and avoiding preempt */
local_irq_save(flags);
@@ -80,6 +81,8 @@ void __kprobes kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
* If pre_handler returns !0, it sets regs->ip and
* resets current kprobe.
*/
+ if (ip != save_ip)
+ regs->ip = save_ip;
}
end:
local_irq_restore(flags);
With this patch, if both kpatch and a kprobe handler try to modify the IP, kpatch always wins.
Option 2:
Create an FTRACE_OPS_FL_LAST
flag which ensures that kpatch is called last, so that any kprobes attempts to update regs->ip will be ignored.
This is another variation on option 1: if both kpatch and a kprobe handler try to modify the IP, kpatch always wins.
Option 3:
Create an FTRACE_OPS_FL_FIRST
flag which ensures that kpatch is called first. Then pass the updated regs->ip to the kprobes functions so they can set their breakpoint at the beginning of the replacement function. The downside here is that kprobes modules can override kpatch's redirecting of functions, but that may not be much of an issue.
So if both kpatch and a kprobe handler try to modify the IP, kprobes wins.
Option 4:
Create an FTRACE_OPS_FL_IPMODIFY
flag: first to register wins.