Re: [PATCH v2 12/39] x86/ibt,ftrace: Search for __fentry__ location

From: Naveen N. Rao
Date: Thu Mar 03 2022 - 09:40:26 EST


Peter Zijlstra wrote:
On Thu, Mar 03, 2022 at 03:15:14PM +0530, Naveen N. Rao wrote:

> 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.

I hit this issue yesterday in kprobe generic code in
check_ftrace_location().

What exactly where you running to trigger this? (so that I can extend my
test coverage etc..)

With the changes here, we always promote probes at +0 offset to the LEP at +8. So, we get the old behavior of ftrace_location(). But, we also have functions that do not have a GEP. For those, we allow probing at an offset of +0, resulting in ftrace_location() giving us the actual ftrace site, which on ppc64le will be at +4.

On ppc32, this will affect all probes since the ftrace site is usually at an offset of +8.

I don't think x86 has this issue since you will always have ftrace site at +0 if a function does not have the endbr instruction. And if you do have the endbr instruction, then you adjust the probe address so it won't be at an offset of 0 into the function.


In both these scenarios, we just want to check if a
particular instruction is reserved by ftrace. ftrace_location_range()
should still work for that purpose, so that may be the easier fix:

diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 066fa644e9dfa3..ee3cd035403ca2 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1596,7 +1596,7 @@ static int check_ftrace_location(struct kprobe *p)
{
unsigned long ftrace_addr;

- ftrace_addr = ftrace_location((unsigned long)p->addr);
+ ftrace_addr = ftrace_location_range((unsigned long)p->addr, (unsigned long)p->addr);

Yes, although perhaps a new helper. I'll go ponder during lunch.

Sure. We do have ftrace_text_reserved(), but that only returns a boolean. Masami wanted to ensure that the probe is at an instruction boundary, hence this check.


PS. I posted v3 but forgot to Cc you:

https://lkml.kernel.org/r/20220303112321.422525803@xxxxxxxxxxxxx

I think the above hunk ended up in the kprobe patch, but on second
thought I should've put it in the ftrace one. I'll go ammend and add
this other site you found.

Thanks, I'll take a look.

- Naveen