On Wed, Mar 02, 2022 at 02:47:16PM -0500, Steven Rostedt wrote:
Note, I just pulled this patch, and I hit this warning:
WARNING: CPU: 0 PID: 6965 at arch/x86/kernel/kprobes/core.c:205 recover_probed_instruction+0x8f/0xa0
static unsigned long
__recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr)
{
struct kprobe *kp;
unsigned long faddr;
kp = get_kprobe((void *)addr);
faddr = ftrace_location(addr);
/*
* Addresses inside the ftrace location are refused by
* arch_check_ftrace_location(). Something went terribly wrong
* if such an address is checked here.
*/
if (WARN_ON(faddr && faddr != addr)) <<---- HERE
return 0UL;
Ha! so a bunch of IRC later I figured out how it is possible you hit
this with just the patch on and how I legitimately hit this and what to
do about it.
Your problem seems to be that we got ftrace_location() wrong in that
lookup_rec()'s end argument is inclusive, hence we need:
lookup_rec(ip, ip + size - 1)
Now, the above thing asserts that:
ftrace_location(x) == {0, x}
and that is genuinely false in my case, I get x+4 as additional possible
output. So I think I need the below change to go on top of all I have:
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index 7f0ce42f8ff9..4c13406e0bc4 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -198,13 +198,14 @@ __recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr)
kp = get_kprobe((void *)addr);
faddr = ftrace_location(addr);
+
/*
- * Addresses inside the ftrace location are refused by
- * arch_check_ftrace_location(). Something went terribly wrong
- * if such an address is checked here.
+ * In case addr maps to sym+0 ftrace_location() might return something
+ * other than faddr. In that case consider it the same as !faddr.
*/
- if (WARN_ON(faddr && faddr != addr))
- return 0UL;
+ if (faddr && faddr != addr)
+ faddr = 0;
+
/*
* Use the current code if it is not modified by Kprobe
* and it cannot be modified by ftrace.