diff mbox series

ftrace: x86: Fix a compile error about get_kernel_nofault()

Message ID 173881156244.211648.1242168038709680511.stgit@devnote2 (mailing list archive)
State New
Headers show
Series ftrace: x86: Fix a compile error about get_kernel_nofault() | expand

Commit Message

Masami Hiramatsu (Google) Feb. 6, 2025, 3:12 a.m. UTC
From: Masami Hiramatsu (Google) <mhiramat@kernel.org>

Fix a compile error about get_kernel_nofault() which is defined in the
linux/uaccess.h. Since asm/ftrace.h is widely used, including
linux/uaccess.h in asm/ftrace.h caused another error. Thus this
moves arch_ftrace_get_symaddr() into arch/x86/kernel/ftrace.c.

The original errors look like:

In file included from ./arch/x86/include/asm/asm-prototypes.h:2,
                 from <stdin>:3:
./arch/x86/include/asm/ftrace.h: In function 'arch_ftrace_get_symaddr':
./arch/x86/include/asm/ftrace.h:46:21: error: implicit declaration of function 'get_kernel_nofault' [-Werror=implicit-function-declaration]
   46 |                 if (get_kernel_nofault(instr, (u32 *)(fentry_ip - ENDBR_INSN_SIZE)))
      |                     ^~~~~~~~~~~~~~~~~~

This also makes ftrace_get_symaddr() available only when
CONFIG_HAVE_FENTRY=y on x86.

Reported-by: Gabriel de Perthuis <g2p.code@gmail.com>
Closes: https://lore.kernel.org/all/a87f98bf-45b1-4ef5-aa77-02f7e61203f4@gmail.com/
Reported-by: Haiyue Wang <haiyuewa@163.com>
Closes: https://lore.kernel.org/all/20250205180116.88644-1-haiyuewa@163.com/
Fixes: 2bc56fdae1ba ("ftrace: Add ftrace_get_symaddr to convert fentry_ip to symaddr")
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
 arch/x86/include/asm/ftrace.h |   23 ++++-------------------
 arch/x86/kernel/ftrace.c      |   26 +++++++++++++++++++++++++-
 2 files changed, 29 insertions(+), 20 deletions(-)

Comments

Peter Zijlstra Feb. 6, 2025, 8:12 a.m. UTC | #1
On Thu, Feb 06, 2025 at 12:12:42PM +0900, Masami Hiramatsu (Google) wrote:

> +#ifdef CONFIG_HAVE_FENTRY
> +/* Convert fentry address to the symbol address. */
> +unsigned long arch_ftrace_get_symaddr(unsigned long fentry_ip)
> +{
> +#ifdef CONFIG_X86_KERNEL_IBT
> +	u32 instr;
> +
> +	/* We want to be extra safe in case entry ip is on the page edge,
> +	 * but otherwise we need to avoid get_kernel_nofault()'s overhead.
> +	 */
> +	if ((fentry_ip & ~PAGE_MASK) < ENDBR_INSN_SIZE) {
> +		if (get_kernel_nofault(instr, (u32 *)(fentry_ip - ENDBR_INSN_SIZE)))
> +			return fentry_ip;
> +	} else {
> +		instr = *(u32 *)(fentry_ip - ENDBR_INSN_SIZE);
> +	}
> +	if (is_endbr(instr))
> +		fentry_ip -= ENDBR_INSN_SIZE;
> +#endif
> +	return fentry_ip;
> +}
> +#endif

Urgh, that reminds, me. I have a pile of patches cleaning up this mess.
Let me go find them.
Masami Hiramatsu (Google) Feb. 6, 2025, 11:54 a.m. UTC | #2
On Thu, 6 Feb 2025 09:12:25 +0100
Peter Zijlstra <peterz@infradead.org> wrote:

> 
> > +#ifdef CONFIG_HAVE_FENTRY
> > +/* Convert fentry address to the symbol address. */
> > +unsigned long arch_ftrace_get_symaddr(unsigned long fentry_ip)
> > +{
> > +#ifdef CONFIG_X86_KERNEL_IBT
> > +	u32 instr;
> > +
> > +	/* We want to be extra safe in case entry ip is on the page edge,
> > +	 * but otherwise we need to avoid get_kernel_nofault()'s overhead.
> > +	 */
> > +	if ((fentry_ip & ~PAGE_MASK) < ENDBR_INSN_SIZE) {
> > +		if (get_kernel_nofault(instr, (u32 *)(fentry_ip - ENDBR_INSN_SIZE)))
> > +			return fentry_ip;
> > +	} else {
> > +		instr = *(u32 *)(fentry_ip - ENDBR_INSN_SIZE);
> > +	}
> > +	if (is_endbr(instr))
> > +		fentry_ip -= ENDBR_INSN_SIZE;
> > +#endif
> > +	return fentry_ip;
> > +}
> > +#endif
> 
> Urgh, that reminds, me. I have a pile of patches cleaning up this mess.
> Let me go find them.

Thanks for cleaning up! So would it change the location of ENDBR and
symbol address?

Thanks,
Peter Zijlstra Feb. 6, 2025, 12:13 p.m. UTC | #3
On Thu, Feb 06, 2025 at 08:54:49PM +0900, Masami Hiramatsu wrote:
> On Thu, 6 Feb 2025 09:12:25 +0100
> Peter Zijlstra <peterz@infradead.org> wrote:
> 
> > 
> > > +#ifdef CONFIG_HAVE_FENTRY
> > > +/* Convert fentry address to the symbol address. */
> > > +unsigned long arch_ftrace_get_symaddr(unsigned long fentry_ip)
> > > +{
> > > +#ifdef CONFIG_X86_KERNEL_IBT
> > > +	u32 instr;
> > > +
> > > +	/* We want to be extra safe in case entry ip is on the page edge,
> > > +	 * but otherwise we need to avoid get_kernel_nofault()'s overhead.
> > > +	 */
> > > +	if ((fentry_ip & ~PAGE_MASK) < ENDBR_INSN_SIZE) {
> > > +		if (get_kernel_nofault(instr, (u32 *)(fentry_ip - ENDBR_INSN_SIZE)))
> > > +			return fentry_ip;
> > > +	} else {
> > > +		instr = *(u32 *)(fentry_ip - ENDBR_INSN_SIZE);
> > > +	}
> > > +	if (is_endbr(instr))
> > > +		fentry_ip -= ENDBR_INSN_SIZE;
> > > +#endif
> > > +	return fentry_ip;
> > > +}
> > > +#endif
> > 
> > Urgh, that reminds, me. I have a pile of patches cleaning up this mess.
> > Let me go find them.
> 
> Thanks for cleaning up! So would it change the location of ENDBR and
> symbol address?

No, it just cleans up this utter trainwreck. I also noticed this is a
second (new) copy of this garbage. Clearly I didn't yell loud enough
last time and people didn't think to vomit when doing the copy/paste :/

Function will look something like:

unsigned long arch_ftrace_get_symaddr(unsigned long fentry_ip)
{
	if (is_endbr(fentry_ip - ENDBR_INSN_SIZE))
		fentry_op -= ENDBR_INSN_SIZE;
	return fentry_ip;
}

Let me finish local build test before I push out.
Peter Zijlstra Feb. 6, 2025, 12:33 p.m. UTC | #4
On Thu, Feb 06, 2025 at 01:13:28PM +0100, Peter Zijlstra wrote:

> No, it just cleans up this utter trainwreck. I also noticed this is a
> second (new) copy of this garbage. Clearly I didn't yell loud enough
> last time and people didn't think to vomit when doing the copy/paste :/
> 
> Function will look something like:
> 
> unsigned long arch_ftrace_get_symaddr(unsigned long fentry_ip)
> {
> 	if (is_endbr(fentry_ip - ENDBR_INSN_SIZE))
> 		fentry_op -= ENDBR_INSN_SIZE;
> 	return fentry_ip;
> }
> 
> Let me finish local build test before I push out.

Bah, still waiting for a LLVM build, but patch should be here:

git://git.kernel.org/pub/scm/linux/kernel/git/peterz/queue.git x86/ibt

I was supposed to merge this last cycle, but then akpm shat all over
arch/x86/kernel/alternative.c and we had to clean that up :/

Notably, this patch, not sure it applies out of order.

---

Subject: x86/ibt: Clean up is_endbr()
From: Peter Zijlstra <peterz@infradead.org>
Date: Mon Nov 27 09:58:06 CET 2023

Pretty much every caller of is_endbr() actually wants to test something at an
address and ends up doing get_kernel_nofault(). Fold the lot into a more
convenient helper.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
---
 arch/x86/events/core.c         |    2 +-
 arch/x86/include/asm/ftrace.h  |   17 +++--------------
 arch/x86/include/asm/ibt.h     |    5 +++--
 arch/x86/kernel/alternative.c  |   20 ++++++++++++++------
 arch/x86/kernel/kprobes/core.c |   11 +----------
 arch/x86/net/bpf_jit_comp.c    |    4 ++--
 kernel/trace/bpf_trace.c       |   20 +++-----------------
 7 files changed, 27 insertions(+), 52 deletions(-)

--- a/arch/x86/events/core.c
+++ b/arch/x86/events/core.c
@@ -2857,7 +2857,7 @@ static bool is_uprobe_at_func_entry(stru
 		return true;
 
 	/* endbr64 (64-bit only) */
-	if (user_64bit_mode(regs) && is_endbr(*(u32 *)auprobe->insn))
+	if (user_64bit_mode(regs) && is_endbr((u32 *)auprobe->insn))
 		return true;
 
 	return false;
--- a/arch/x86/include/asm/ftrace.h
+++ b/arch/x86/include/asm/ftrace.h
@@ -2,6 +2,7 @@
 #ifndef _ASM_X86_FTRACE_H
 #define _ASM_X86_FTRACE_H
 
+#include "asm/ibt.h"
 #include <asm/ptrace.h>
 
 #ifdef CONFIG_FUNCTION_TRACER
@@ -36,21 +37,9 @@ static inline unsigned long ftrace_call_
 
 static inline unsigned long arch_ftrace_get_symaddr(unsigned long fentry_ip)
 {
-#ifdef CONFIG_X86_KERNEL_IBT
-	u32 instr;
+	if (is_endbr((void*)(fentry_ip - ENDBR_INSN_SIZE)))
+		fentry_ip -= ENDBENDBR_INSN_SIZE;
 
-	/* We want to be extra safe in case entry ip is on the page edge,
-	 * but otherwise we need to avoid get_kernel_nofault()'s overhead.
-	 */
-	if ((fentry_ip & ~PAGE_MASK) < ENDBR_INSN_SIZE) {
-		if (get_kernel_nofault(instr, (u32 *)(fentry_ip - ENDBR_INSN_SIZE)))
-			return fentry_ip;
-	} else {
-		instr = *(u32 *)(fentry_ip - ENDBR_INSN_SIZE);
-	}
-	if (is_endbr(instr))
-		fentry_ip -= ENDBR_INSN_SIZE;
-#endif
 	return fentry_ip;
 }
 #define ftrace_get_symaddr(fentry_ip)	arch_ftrace_get_symaddr(fentry_ip)
--- a/arch/x86/include/asm/ibt.h
+++ b/arch/x86/include/asm/ibt.h
@@ -65,7 +65,7 @@ static __always_inline __attribute_const
 	return 0x001f0f66; /* osp nopl (%rax) */
 }
 
-static inline bool is_endbr(u32 val)
+static inline bool __is_endbr(u32 val)
 {
 	if (val == gen_endbr_poison())
 		return true;
@@ -74,6 +74,7 @@ static inline bool is_endbr(u32 val)
 	return val == gen_endbr();
 }
 
+extern __noendbr bool is_endbr(u32 *val);
 extern __noendbr u64 ibt_save(bool disable);
 extern __noendbr void ibt_restore(u64 save);
 
@@ -98,7 +99,7 @@ extern __noendbr void ibt_restore(u64 sa
 
 #define __noendbr
 
-static inline bool is_endbr(u32 val) { return false; }
+static inline bool is_endbr(u32 *val) { return false; }
 
 static inline u64 ibt_save(bool disable) { return 0; }
 static inline void ibt_restore(u64 save) { }
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -852,16 +852,24 @@ void __init_or_module noinline apply_ret
 
 #ifdef CONFIG_X86_KERNEL_IBT
 
+__noendbr bool is_endbr(u32 *val)
+{
+	u32 endbr;
+
+	__get_kernel_nofault(&endbr, val, u32, Efault);
+	return __is_endbr(endbr);
+
+Efault:
+	return false;
+}
+
 static void poison_cfi(void *addr);
 
 static void __init_or_module poison_endbr(void *addr, bool warn)
 {
-	u32 endbr, poison = gen_endbr_poison();
-
-	if (WARN_ON_ONCE(get_kernel_nofault(endbr, addr)))
-		return;
+	u32 poison = gen_endbr_poison();
 
-	if (!is_endbr(endbr)) {
+	if (!is_endbr(addr)) {
 		WARN_ON_ONCE(warn);
 		return;
 	}
@@ -984,7 +992,7 @@ static u32  cfi_seed __ro_after_init;
 static u32 cfi_rehash(u32 hash)
 {
 	hash ^= cfi_seed;
-	while (unlikely(is_endbr(hash) || is_endbr(-hash))) {
+	while (unlikely(__is_endbr(hash) || __is_endbr(-hash))) {
 		bool lsb = hash & 1;
 		hash >>= 1;
 		if (lsb)
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -373,16 +373,7 @@ static bool can_probe(unsigned long padd
 kprobe_opcode_t *arch_adjust_kprobe_addr(unsigned long addr, unsigned long offset,
 					 bool *on_func_entry)
 {
-	u32 insn;
-
-	/*
-	 * Since 'addr' is not guaranteed to be safe to access, use
-	 * copy_from_kernel_nofault() to read the instruction:
-	 */
-	if (copy_from_kernel_nofault(&insn, (void *)addr, sizeof(u32)))
-		return NULL;
-
-	if (is_endbr(insn)) {
+	if (is_endbr((u32 *)addr)) {
 		*on_func_entry = !offset || offset == 4;
 		if (*on_func_entry)
 			offset = 4;
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -641,7 +641,7 @@ int bpf_arch_text_poke(void *ip, enum bp
 	 * See emit_prologue(), for IBT builds the trampoline hook is preceded
 	 * with an ENDBR instruction.
 	 */
-	if (is_endbr(*(u32 *)ip))
+	if (is_endbr(ip))
 		ip += ENDBR_INSN_SIZE;
 
 	return __bpf_arch_text_poke(ip, t, old_addr, new_addr);
@@ -3036,7 +3036,7 @@ static int __arch_prepare_bpf_trampoline
 		/* skip patched call instruction and point orig_call to actual
 		 * body of the kernel function.
 		 */
-		if (is_endbr(*(u32 *)orig_call))
+		if (is_endbr(orig_call))
 			orig_call += ENDBR_INSN_SIZE;
 		orig_call += X86_PATCH_SIZE;
 	}
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -1038,27 +1038,13 @@ static const struct bpf_func_proto bpf_g
 	.arg1_type	= ARG_PTR_TO_CTX,
 };
 
-#ifdef CONFIG_X86_KERNEL_IBT
-static unsigned long get_entry_ip(unsigned long fentry_ip)
+static inline unsigned long get_entry_ip(unsigned long fentry_ip)
 {
-	u32 instr;
-
-	/* We want to be extra safe in case entry ip is on the page edge,
-	 * but otherwise we need to avoid get_kernel_nofault()'s overhead.
-	 */
-	if ((fentry_ip & ~PAGE_MASK) < ENDBR_INSN_SIZE) {
-		if (get_kernel_nofault(instr, (u32 *)(fentry_ip - ENDBR_INSN_SIZE)))
-			return fentry_ip;
-	} else {
-		instr = *(u32 *)(fentry_ip - ENDBR_INSN_SIZE);
-	}
-	if (is_endbr(instr))
+	if (is_endbr((void *)(fentry_ip - ENDBR_INSN_SIZE)))
 		fentry_ip -= ENDBR_INSN_SIZE;
+
 	return fentry_ip;
 }
-#else
-#define get_entry_ip(fentry_ip) fentry_ip
-#endif
 
 BPF_CALL_1(bpf_get_func_ip_kprobe, struct pt_regs *, regs)
 {
Haiyue Wang Feb. 6, 2025, 1:25 p.m. UTC | #5
On 2025/2/6 20:33, Peter Zijlstra wrote:
> On Thu, Feb 06, 2025 at 01:13:28PM +0100, Peter Zijlstra wrote:
> 
>> No, it just cleans up this utter trainwreck. I also noticed this is a
>> second (new) copy of this garbage. Clearly I didn't yell loud enough
>> last time and people didn't think to vomit when doing the copy/paste :/
>>
>> Function will look something like:
>>
>> unsigned long arch_ftrace_get_symaddr(unsigned long fentry_ip)
>> {
>> 	if (is_endbr(fentry_ip - ENDBR_INSN_SIZE))
>> 		fentry_op -= ENDBR_INSN_SIZE;
>> 	return fentry_ip;
>> }
>>
>> Let me finish local build test before I push out.
> 
> Bah, still waiting for a LLVM build, but patch should be here:
> 
> git://git.kernel.org/pub/scm/linux/kernel/git/peterz/queue.git x86/ibt
> 
> I was supposed to merge this last cycle, but then akpm shat all over
> arch/x86/kernel/alternative.c and we had to clean that up :/
> 
> Notably, this patch, not sure it applies out of order.
> 
> ---
> 
> Subject: x86/ibt: Clean up is_endbr()
> From: Peter Zijlstra <peterz@infradead.org>
> Date: Mon Nov 27 09:58:06 CET 2023
> 
> Pretty much every caller of is_endbr() actually wants to test something at an
> address and ends up doing get_kernel_nofault(). Fold the lot into a more
> convenient helper.
> 
> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> Acked-by: Alexei Starovoitov <ast@kernel.org>
> Acked-by: Andrii Nakryiko <andrii@kernel.org>
> ---
>   arch/x86/events/core.c         |    2 +-
>   arch/x86/include/asm/ftrace.h  |   17 +++--------------
>   arch/x86/include/asm/ibt.h     |    5 +++--
>   arch/x86/kernel/alternative.c  |   20 ++++++++++++++------
>   arch/x86/kernel/kprobes/core.c |   11 +----------
>   arch/x86/net/bpf_jit_comp.c    |    4 ++--
>   kernel/trace/bpf_trace.c       |   20 +++-----------------
>   7 files changed, 27 insertions(+), 52 deletions(-)
> 
> --- a/arch/x86/events/core.c
> +++ b/arch/x86/events/core.c
> @@ -2857,7 +2857,7 @@ static bool is_uprobe_at_func_entry(stru
>   		return true;
>   
>   	/* endbr64 (64-bit only) */
> -	if (user_64bit_mode(regs) && is_endbr(*(u32 *)auprobe->insn))
> +	if (user_64bit_mode(regs) && is_endbr((u32 *)auprobe->insn))
>   		return true;
>   
>   	return false;
> --- a/arch/x86/include/asm/ftrace.h
> +++ b/arch/x86/include/asm/ftrace.h
> @@ -2,6 +2,7 @@
>   #ifndef _ASM_X86_FTRACE_H
>   #define _ASM_X86_FTRACE_H
>   
> +#include "asm/ibt.h"

Then 
https://git.kernel.org/pub/scm/linux/kernel/git/peterz/queue.git/tree/arch/x86/include/asm/ftrace.h?h=x86/ibt#n17

# include <asm/ibt.h> --> This line can be removed ?

>   #include <asm/ptrace.h>
>   
>   #ifdef CONFIG_FUNCTION_TRACER
> @@ -36,21 +37,9 @@ static inline unsigned long ftrace_call_
>   
>   static inline unsigned long arch_ftrace_get_symaddr(unsigned long fentry_ip)
>   {
Gabriel de Perthuis Feb. 6, 2025, 6:19 p.m. UTC | #6
Hello,
I can confirm this solves the build issue alongside gendwarfksyms;
much appreciated.

Le jeu. 6 févr. 2025 à 04:12, Masami Hiramatsu (Google)
<mhiramat@kernel.org> a écrit :
>
> From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
>
> Fix a compile error about get_kernel_nofault() which is defined in the
> linux/uaccess.h. Since asm/ftrace.h is widely used, including
> linux/uaccess.h in asm/ftrace.h caused another error. Thus this
> moves arch_ftrace_get_symaddr() into arch/x86/kernel/ftrace.c.
>
> The original errors look like:
>
> In file included from ./arch/x86/include/asm/asm-prototypes.h:2,
>                  from <stdin>:3:
> ./arch/x86/include/asm/ftrace.h: In function 'arch_ftrace_get_symaddr':
> ./arch/x86/include/asm/ftrace.h:46:21: error: implicit declaration of function 'get_kernel_nofault' [-Werror=implicit-function-declaration]
>    46 |                 if (get_kernel_nofault(instr, (u32 *)(fentry_ip - ENDBR_INSN_SIZE)))
>       |                     ^~~~~~~~~~~~~~~~~~
>
> This also makes ftrace_get_symaddr() available only when
> CONFIG_HAVE_FENTRY=y on x86.
>
> Reported-by: Gabriel de Perthuis <g2p.code@gmail.com>
> Closes: https://lore.kernel.org/all/a87f98bf-45b1-4ef5-aa77-02f7e61203f4@gmail.com/
> Reported-by: Haiyue Wang <haiyuewa@163.com>
> Closes: https://lore.kernel.org/all/20250205180116.88644-1-haiyuewa@163.com/
> Fixes: 2bc56fdae1ba ("ftrace: Add ftrace_get_symaddr to convert fentry_ip to symaddr")
> Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
> ---
>  arch/x86/include/asm/ftrace.h |   23 ++++-------------------
>  arch/x86/kernel/ftrace.c      |   26 +++++++++++++++++++++++++-
>  2 files changed, 29 insertions(+), 20 deletions(-)
>
> diff --git a/arch/x86/include/asm/ftrace.h b/arch/x86/include/asm/ftrace.h
> index f9cb4d07df58..1ed08f2de366 100644
> --- a/arch/x86/include/asm/ftrace.h
> +++ b/arch/x86/include/asm/ftrace.h
> @@ -34,26 +34,11 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
>         return addr;
>  }
>
> -static inline unsigned long arch_ftrace_get_symaddr(unsigned long fentry_ip)
> -{
> -#ifdef CONFIG_X86_KERNEL_IBT
> -       u32 instr;
> -
> -       /* We want to be extra safe in case entry ip is on the page edge,
> -        * but otherwise we need to avoid get_kernel_nofault()'s overhead.
> -        */
> -       if ((fentry_ip & ~PAGE_MASK) < ENDBR_INSN_SIZE) {
> -               if (get_kernel_nofault(instr, (u32 *)(fentry_ip - ENDBR_INSN_SIZE)))
> -                       return fentry_ip;
> -       } else {
> -               instr = *(u32 *)(fentry_ip - ENDBR_INSN_SIZE);
> -       }
> -       if (is_endbr(instr))
> -               fentry_ip -= ENDBR_INSN_SIZE;
> -#endif
> -       return fentry_ip;
> -}
> +/* This does not support mcount. */
> +#ifdef CONFIG_HAVE_FENTRY
> +unsigned long arch_ftrace_get_symaddr(unsigned long fentry_ip);
>  #define ftrace_get_symaddr(fentry_ip)  arch_ftrace_get_symaddr(fentry_ip)
> +#endif
>
>  #ifdef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS
>
> diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
> index 166bc0ea3bdf..7250118005fc 100644
> --- a/arch/x86/kernel/ftrace.c
> +++ b/arch/x86/kernel/ftrace.c
> @@ -29,11 +29,35 @@
>
>  #include <trace/syscall.h>
>
> -#include <asm/kprobes.h>
>  #include <asm/ftrace.h>
> +#include <asm/ibt.h>
> +#include <asm/kprobes.h>
>  #include <asm/nops.h>
>  #include <asm/text-patching.h>
>
> +#ifdef CONFIG_HAVE_FENTRY
> +/* Convert fentry address to the symbol address. */
> +unsigned long arch_ftrace_get_symaddr(unsigned long fentry_ip)
> +{
> +#ifdef CONFIG_X86_KERNEL_IBT
> +       u32 instr;
> +
> +       /* We want to be extra safe in case entry ip is on the page edge,
> +        * but otherwise we need to avoid get_kernel_nofault()'s overhead.
> +        */
> +       if ((fentry_ip & ~PAGE_MASK) < ENDBR_INSN_SIZE) {
> +               if (get_kernel_nofault(instr, (u32 *)(fentry_ip - ENDBR_INSN_SIZE)))
> +                       return fentry_ip;
> +       } else {
> +               instr = *(u32 *)(fentry_ip - ENDBR_INSN_SIZE);
> +       }
> +       if (is_endbr(instr))
> +               fentry_ip -= ENDBR_INSN_SIZE;
> +#endif
> +       return fentry_ip;
> +}
> +#endif
> +
>  #ifdef CONFIG_DYNAMIC_FTRACE
>
>  static int ftrace_poke_late = 0;
>
Masami Hiramatsu (Google) Feb. 6, 2025, 11:59 p.m. UTC | #7
On Thu, 6 Feb 2025 13:33:07 +0100
Peter Zijlstra <peterz@infradead.org> wrote:

> On Thu, Feb 06, 2025 at 01:13:28PM +0100, Peter Zijlstra wrote:
> 
> > No, it just cleans up this utter trainwreck. I also noticed this is a
> > second (new) copy of this garbage. Clearly I didn't yell loud enough
> > last time and people didn't think to vomit when doing the copy/paste :/
> > 
> > Function will look something like:
> > 
> > unsigned long arch_ftrace_get_symaddr(unsigned long fentry_ip)
> > {
> > 	if (is_endbr(fentry_ip - ENDBR_INSN_SIZE))
> > 		fentry_op -= ENDBR_INSN_SIZE;
> > 	return fentry_ip;
> > }
> > 
> > Let me finish local build test before I push out.
> 
> Bah, still waiting for a LLVM build, but patch should be here:
> 
> git://git.kernel.org/pub/scm/linux/kernel/git/peterz/queue.git x86/ibt
> 
> I was supposed to merge this last cycle, but then akpm shat all over
> arch/x86/kernel/alternative.c and we had to clean that up :/
> 
> Notably, this patch, not sure it applies out of order.
> 

Ah, this looks good to me except for the removing redundant asm/ibt.h
which Haiyue pointed.

Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>

Thanks,

> ---
> 
> Subject: x86/ibt: Clean up is_endbr()
> From: Peter Zijlstra <peterz@infradead.org>
> Date: Mon Nov 27 09:58:06 CET 2023
> 
> Pretty much every caller of is_endbr() actually wants to test something at an
> address and ends up doing get_kernel_nofault(). Fold the lot into a more
> convenient helper.
> 
> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> Acked-by: Alexei Starovoitov <ast@kernel.org>
> Acked-by: Andrii Nakryiko <andrii@kernel.org>
> ---
>  arch/x86/events/core.c         |    2 +-
>  arch/x86/include/asm/ftrace.h  |   17 +++--------------
>  arch/x86/include/asm/ibt.h     |    5 +++--
>  arch/x86/kernel/alternative.c  |   20 ++++++++++++++------
>  arch/x86/kernel/kprobes/core.c |   11 +----------
>  arch/x86/net/bpf_jit_comp.c    |    4 ++--
>  kernel/trace/bpf_trace.c       |   20 +++-----------------
>  7 files changed, 27 insertions(+), 52 deletions(-)
> 
> --- a/arch/x86/events/core.c
> +++ b/arch/x86/events/core.c
> @@ -2857,7 +2857,7 @@ static bool is_uprobe_at_func_entry(stru
>  		return true;
>  
>  	/* endbr64 (64-bit only) */
> -	if (user_64bit_mode(regs) && is_endbr(*(u32 *)auprobe->insn))
> +	if (user_64bit_mode(regs) && is_endbr((u32 *)auprobe->insn))
>  		return true;
>  
>  	return false;
> --- a/arch/x86/include/asm/ftrace.h
> +++ b/arch/x86/include/asm/ftrace.h
> @@ -2,6 +2,7 @@
>  #ifndef _ASM_X86_FTRACE_H
>  #define _ASM_X86_FTRACE_H
>  
> +#include "asm/ibt.h"
>  #include <asm/ptrace.h>
>  
>  #ifdef CONFIG_FUNCTION_TRACER
> @@ -36,21 +37,9 @@ static inline unsigned long ftrace_call_
>  
>  static inline unsigned long arch_ftrace_get_symaddr(unsigned long fentry_ip)
>  {
> -#ifdef CONFIG_X86_KERNEL_IBT
> -	u32 instr;
> +	if (is_endbr((void*)(fentry_ip - ENDBR_INSN_SIZE)))
> +		fentry_ip -= ENDBENDBR_INSN_SIZE;
>  
> -	/* We want to be extra safe in case entry ip is on the page edge,
> -	 * but otherwise we need to avoid get_kernel_nofault()'s overhead.
> -	 */
> -	if ((fentry_ip & ~PAGE_MASK) < ENDBR_INSN_SIZE) {
> -		if (get_kernel_nofault(instr, (u32 *)(fentry_ip - ENDBR_INSN_SIZE)))
> -			return fentry_ip;
> -	} else {
> -		instr = *(u32 *)(fentry_ip - ENDBR_INSN_SIZE);
> -	}
> -	if (is_endbr(instr))
> -		fentry_ip -= ENDBR_INSN_SIZE;
> -#endif
>  	return fentry_ip;
>  }
>  #define ftrace_get_symaddr(fentry_ip)	arch_ftrace_get_symaddr(fentry_ip)
> --- a/arch/x86/include/asm/ibt.h
> +++ b/arch/x86/include/asm/ibt.h
> @@ -65,7 +65,7 @@ static __always_inline __attribute_const
>  	return 0x001f0f66; /* osp nopl (%rax) */
>  }
>  
> -static inline bool is_endbr(u32 val)
> +static inline bool __is_endbr(u32 val)
>  {
>  	if (val == gen_endbr_poison())
>  		return true;
> @@ -74,6 +74,7 @@ static inline bool is_endbr(u32 val)
>  	return val == gen_endbr();
>  }
>  
> +extern __noendbr bool is_endbr(u32 *val);
>  extern __noendbr u64 ibt_save(bool disable);
>  extern __noendbr void ibt_restore(u64 save);
>  
> @@ -98,7 +99,7 @@ extern __noendbr void ibt_restore(u64 sa
>  
>  #define __noendbr
>  
> -static inline bool is_endbr(u32 val) { return false; }
> +static inline bool is_endbr(u32 *val) { return false; }
>  
>  static inline u64 ibt_save(bool disable) { return 0; }
>  static inline void ibt_restore(u64 save) { }
> --- a/arch/x86/kernel/alternative.c
> +++ b/arch/x86/kernel/alternative.c
> @@ -852,16 +852,24 @@ void __init_or_module noinline apply_ret
>  
>  #ifdef CONFIG_X86_KERNEL_IBT
>  
> +__noendbr bool is_endbr(u32 *val)
> +{
> +	u32 endbr;
> +
> +	__get_kernel_nofault(&endbr, val, u32, Efault);
> +	return __is_endbr(endbr);
> +
> +Efault:
> +	return false;
> +}
> +
>  static void poison_cfi(void *addr);
>  
>  static void __init_or_module poison_endbr(void *addr, bool warn)
>  {
> -	u32 endbr, poison = gen_endbr_poison();
> -
> -	if (WARN_ON_ONCE(get_kernel_nofault(endbr, addr)))
> -		return;
> +	u32 poison = gen_endbr_poison();
>  
> -	if (!is_endbr(endbr)) {
> +	if (!is_endbr(addr)) {
>  		WARN_ON_ONCE(warn);
>  		return;
>  	}
> @@ -984,7 +992,7 @@ static u32  cfi_seed __ro_after_init;
>  static u32 cfi_rehash(u32 hash)
>  {
>  	hash ^= cfi_seed;
> -	while (unlikely(is_endbr(hash) || is_endbr(-hash))) {
> +	while (unlikely(__is_endbr(hash) || __is_endbr(-hash))) {
>  		bool lsb = hash & 1;
>  		hash >>= 1;
>  		if (lsb)
> --- a/arch/x86/kernel/kprobes/core.c
> +++ b/arch/x86/kernel/kprobes/core.c
> @@ -373,16 +373,7 @@ static bool can_probe(unsigned long padd
>  kprobe_opcode_t *arch_adjust_kprobe_addr(unsigned long addr, unsigned long offset,
>  					 bool *on_func_entry)
>  {
> -	u32 insn;
> -
> -	/*
> -	 * Since 'addr' is not guaranteed to be safe to access, use
> -	 * copy_from_kernel_nofault() to read the instruction:
> -	 */
> -	if (copy_from_kernel_nofault(&insn, (void *)addr, sizeof(u32)))
> -		return NULL;
> -
> -	if (is_endbr(insn)) {
> +	if (is_endbr((u32 *)addr)) {
>  		*on_func_entry = !offset || offset == 4;
>  		if (*on_func_entry)
>  			offset = 4;
> --- a/arch/x86/net/bpf_jit_comp.c
> +++ b/arch/x86/net/bpf_jit_comp.c
> @@ -641,7 +641,7 @@ int bpf_arch_text_poke(void *ip, enum bp
>  	 * See emit_prologue(), for IBT builds the trampoline hook is preceded
>  	 * with an ENDBR instruction.
>  	 */
> -	if (is_endbr(*(u32 *)ip))
> +	if (is_endbr(ip))
>  		ip += ENDBR_INSN_SIZE;
>  
>  	return __bpf_arch_text_poke(ip, t, old_addr, new_addr);
> @@ -3036,7 +3036,7 @@ static int __arch_prepare_bpf_trampoline
>  		/* skip patched call instruction and point orig_call to actual
>  		 * body of the kernel function.
>  		 */
> -		if (is_endbr(*(u32 *)orig_call))
> +		if (is_endbr(orig_call))
>  			orig_call += ENDBR_INSN_SIZE;
>  		orig_call += X86_PATCH_SIZE;
>  	}
> --- a/kernel/trace/bpf_trace.c
> +++ b/kernel/trace/bpf_trace.c
> @@ -1038,27 +1038,13 @@ static const struct bpf_func_proto bpf_g
>  	.arg1_type	= ARG_PTR_TO_CTX,
>  };
>  
> -#ifdef CONFIG_X86_KERNEL_IBT
> -static unsigned long get_entry_ip(unsigned long fentry_ip)
> +static inline unsigned long get_entry_ip(unsigned long fentry_ip)
>  {
> -	u32 instr;
> -
> -	/* We want to be extra safe in case entry ip is on the page edge,
> -	 * but otherwise we need to avoid get_kernel_nofault()'s overhead.
> -	 */
> -	if ((fentry_ip & ~PAGE_MASK) < ENDBR_INSN_SIZE) {
> -		if (get_kernel_nofault(instr, (u32 *)(fentry_ip - ENDBR_INSN_SIZE)))
> -			return fentry_ip;
> -	} else {
> -		instr = *(u32 *)(fentry_ip - ENDBR_INSN_SIZE);
> -	}
> -	if (is_endbr(instr))
> +	if (is_endbr((void *)(fentry_ip - ENDBR_INSN_SIZE)))
>  		fentry_ip -= ENDBR_INSN_SIZE;
> +
>  	return fentry_ip;
>  }
> -#else
> -#define get_entry_ip(fentry_ip) fentry_ip
> -#endif
>  
>  BPF_CALL_1(bpf_get_func_ip_kprobe, struct pt_regs *, regs)
>  {
>
Peter Zijlstra Feb. 7, 2025, 10:09 a.m. UTC | #8
On Thu, Feb 06, 2025 at 09:25:37PM +0800, Haiyue Wang wrote:
> > --- a/arch/x86/include/asm/ftrace.h
> > +++ b/arch/x86/include/asm/ftrace.h
> > @@ -2,6 +2,7 @@
> >   #ifndef _ASM_X86_FTRACE_H
> >   #define _ASM_X86_FTRACE_H
> > +#include "asm/ibt.h"

Argh yes, I don't know where that came from. /me zaps
Steven Rostedt Feb. 10, 2025, 10:30 p.m. UTC | #9
On Fri, 7 Feb 2025 08:59:59 +0900
Masami Hiramatsu (Google) <mhiramat@kernel.org> wrote:

> Ah, this looks good to me except for the removing redundant asm/ibt.h
> which Haiyue pointed.
> 
> Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>

Cool, so Peter's going to fix this and I can drop the fixes that are in
patchwork?

-- Steve
Peter Zijlstra Feb. 11, 2025, 10:09 a.m. UTC | #10
On Mon, Feb 10, 2025 at 05:30:16PM -0500, Steven Rostedt wrote:
> On Fri, 7 Feb 2025 08:59:59 +0900
> Masami Hiramatsu (Google) <mhiramat@kernel.org> wrote:
> 
> > Ah, this looks good to me except for the removing redundant asm/ibt.h
> > which Haiyue pointed.
> > 
> > Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
> 
> Cool, so Peter's going to fix this and I can drop the fixes that are in
> patchwork?

I was aiming my patch for x86/core, but if there's a reason to expedite
them, I can stick it in x86/urgent I suppose.

Just need a reason -- what's this compile error nonsense about, my
kernels build just fine?
Steven Rostedt Feb. 11, 2025, 3:50 p.m. UTC | #11
On Tue, 11 Feb 2025 11:09:14 +0100
Peter Zijlstra <peterz@infradead.org> wrote:

> I was aiming my patch for x86/core, but if there's a reason to expedite
> them, I can stick it in x86/urgent I suppose.
> 
> Just need a reason -- what's this compile error nonsense about, my
> kernels build just fine?

Masami,

Do you have a config that fails to build without this fix? If so, can you
please reply with it, and then this can go in as a quick fix.

Thanks,

-- Steve
Sami Tolvanen Feb. 12, 2025, 4:52 p.m. UTC | #12
On Tue, Feb 11, 2025 at 7:49 AM Steven Rostedt <rostedt@goodmis.org> wrote:
>
> On Tue, 11 Feb 2025 11:09:14 +0100
> Peter Zijlstra <peterz@infradead.org> wrote:
>
> > I was aiming my patch for x86/core, but if there's a reason to expedite
> > them, I can stick it in x86/urgent I suppose.
> >
> > Just need a reason -- what's this compile error nonsense about, my
> > kernels build just fine?
>
> Masami,
>
> Do you have a config that fails to build without this fix? If so, can you
> please reply with it, and then this can go in as a quick fix.

x86 builds with both CONFIG_GENDWARFKSYMS and CONFIG_FUNCTION_TRACER
are broken without this fix. Here's how to reproduce:

$ make defconfig
$ ./scripts/config -e DEBUG_INFO -e DEBUG_INFO_DWARF5 -e MODVERSIONS
-e GENDWARFKSYMS -e FUNCTION_TRACER
$ make olddefconfig && make -j
...
In file included from ./arch/x86/include/asm/asm-prototypes.h:2,
                 from <stdin>:3:
./arch/x86/include/asm/ftrace.h: In function ‘arch_ftrace_get_symaddr’:
./arch/x86/include/asm/ftrace.h:46:21: error: implicit declaration of
function ‘get_kernel_nofault’ [-Wimplicit-function-declaration]
   46 |                 if (get_kernel_nofault(instr, (u32
*)(fentry_ip - ENDBR_INSN_SIZE)))
...

Sami
Masami Hiramatsu (Google) Feb. 13, 2025, 12:03 a.m. UTC | #13
On Tue, 11 Feb 2025 10:50:02 -0500
Steven Rostedt <rostedt@goodmis.org> wrote:

> On Tue, 11 Feb 2025 11:09:14 +0100
> Peter Zijlstra <peterz@infradead.org> wrote:
> 
> > I was aiming my patch for x86/core, but if there's a reason to expedite
> > them, I can stick it in x86/urgent I suppose.
> > 
> > Just need a reason -- what's this compile error nonsense about, my
> > kernels build just fine?
> 
> Masami,
> 
> Do you have a config that fails to build without this fix? If so, can you
> please reply with it, and then this can go in as a quick fix.

Let me share the config. But as Sami pointed, the combination of 
CONFIG_GENDWARFKSYMS and CONFIG_FUNCTION_TRACER caused this issue.

Thank you,

> 
> Thanks,
> 
> -- Steve
Peter Zijlstra Feb. 13, 2025, 10:08 a.m. UTC | #14
On Wed, Feb 12, 2025 at 08:52:27AM -0800, Sami Tolvanen wrote:
> On Tue, Feb 11, 2025 at 7:49 AM Steven Rostedt <rostedt@goodmis.org> wrote:
> >
> > On Tue, 11 Feb 2025 11:09:14 +0100
> > Peter Zijlstra <peterz@infradead.org> wrote:
> >
> > > I was aiming my patch for x86/core, but if there's a reason to expedite
> > > them, I can stick it in x86/urgent I suppose.
> > >
> > > Just need a reason -- what's this compile error nonsense about, my
> > > kernels build just fine?
> >
> > Masami,
> >
> > Do you have a config that fails to build without this fix? If so, can you
> > please reply with it, and then this can go in as a quick fix.
> 
> x86 builds with both CONFIG_GENDWARFKSYMS and CONFIG_FUNCTION_TRACER
> are broken without this fix. Here's how to reproduce:
> 
> $ make defconfig
> $ ./scripts/config -e DEBUG_INFO -e DEBUG_INFO_DWARF5 -e MODVERSIONS
> -e GENDWARFKSYMS -e FUNCTION_TRACER
> $ make olddefconfig && make -j
> ...
> In file included from ./arch/x86/include/asm/asm-prototypes.h:2,
>                  from <stdin>:3:
> ./arch/x86/include/asm/ftrace.h: In function ‘arch_ftrace_get_symaddr’:
> ./arch/x86/include/asm/ftrace.h:46:21: error: implicit declaration of
> function ‘get_kernel_nofault’ [-Wimplicit-function-declaration]
>    46 |                 if (get_kernel_nofault(instr, (u32
> *)(fentry_ip - ENDBR_INSN_SIZE)))
> ...

It breaks much sooner, complaining about not having dwarf.h.. let me go
figure out what package provides that :/

Anyway, thanks, I'll go see if my patch helps here.
Haiyue Wang Feb. 13, 2025, 10:25 a.m. UTC | #15
On 2025/2/13 18:08, Peter Zijlstra wrote:
> On Wed, Feb 12, 2025 at 08:52:27AM -0800, Sami Tolvanen wrote:
>> On Tue, Feb 11, 2025 at 7:49 AM Steven Rostedt <rostedt@goodmis.org> wrote:
>>>
>>> On Tue, 11 Feb 2025 11:09:14 +0100
>>> Peter Zijlstra <peterz@infradead.org> wrote:
>>>
>>>> I was aiming my patch for x86/core, but if there's a reason to expedite
>>>> them, I can stick it in x86/urgent I suppose.
>>>>
>>>> Just need a reason -- what's this compile error nonsense about, my
>>>> kernels build just fine?
>>>
>>> Masami,
>>>
>>> Do you have a config that fails to build without this fix? If so, can you
>>> please reply with it, and then this can go in as a quick fix.
>>
>> x86 builds with both CONFIG_GENDWARFKSYMS and CONFIG_FUNCTION_TRACER
>> are broken without this fix. Here's how to reproduce:
>>
>> $ make defconfig
>> $ ./scripts/config -e DEBUG_INFO -e DEBUG_INFO_DWARF5 -e MODVERSIONS
>> -e GENDWARFKSYMS -e FUNCTION_TRACER
>> $ make olddefconfig && make -j
>> ...
>> In file included from ./arch/x86/include/asm/asm-prototypes.h:2,
>>                   from <stdin>:3:
>> ./arch/x86/include/asm/ftrace.h: In function ‘arch_ftrace_get_symaddr’:
>> ./arch/x86/include/asm/ftrace.h:46:21: error: implicit declaration of
>> function ‘get_kernel_nofault’ [-Wimplicit-function-declaration]
>>     46 |                 if (get_kernel_nofault(instr, (u32
>> *)(fentry_ip - ENDBR_INSN_SIZE)))
>> ...
> 
> It breaks much sooner, complaining about not having dwarf.h.. let me go
> figure out what package provides that :/
> 
> Anyway, thanks, I'll go see if my patch helps here.

It is header file include indirect :-)

https://lore.kernel.org/linux-trace-kernel/20250206131711.ea536f165d5b5980b3909acd@kernel.org/T/#t

File "asm-prototypes.h" is added to entry.S by 'scripts/Makefile.build',
adding the missed declaration header file can also fix the error:

  getasmexports =                                                        \
     { echo "\#include <linux/kernel.h>" ;                               \
       echo "\#include <linux/string.h>" ;                               \
+     echo "\#include <linux/uaccess.h>";                               \
       echo "\#include <asm/asm-prototypes.h>" ;                         \
       $(call getexportsymbols,EXPORT_SYMBOL(\1);) ; }
Peter Zijlstra Feb. 13, 2025, 10:26 a.m. UTC | #16
On Thu, Feb 13, 2025 at 11:08:36AM +0100, Peter Zijlstra wrote:
> On Wed, Feb 12, 2025 at 08:52:27AM -0800, Sami Tolvanen wrote:
> > On Tue, Feb 11, 2025 at 7:49 AM Steven Rostedt <rostedt@goodmis.org> wrote:
> > >
> > > On Tue, 11 Feb 2025 11:09:14 +0100
> > > Peter Zijlstra <peterz@infradead.org> wrote:
> > >
> > > > I was aiming my patch for x86/core, but if there's a reason to expedite
> > > > them, I can stick it in x86/urgent I suppose.
> > > >
> > > > Just need a reason -- what's this compile error nonsense about, my
> > > > kernels build just fine?
> > >
> > > Masami,
> > >
> > > Do you have a config that fails to build without this fix? If so, can you
> > > please reply with it, and then this can go in as a quick fix.
> > 
> > x86 builds with both CONFIG_GENDWARFKSYMS and CONFIG_FUNCTION_TRACER
> > are broken without this fix. Here's how to reproduce:
> > 
> > $ make defconfig
> > $ ./scripts/config -e DEBUG_INFO -e DEBUG_INFO_DWARF5 -e MODVERSIONS
> > -e GENDWARFKSYMS -e FUNCTION_TRACER
> > $ make olddefconfig && make -j
> > ...
> > In file included from ./arch/x86/include/asm/asm-prototypes.h:2,
> >                  from <stdin>:3:
> > ./arch/x86/include/asm/ftrace.h: In function ‘arch_ftrace_get_symaddr’:
> > ./arch/x86/include/asm/ftrace.h:46:21: error: implicit declaration of
> > function ‘get_kernel_nofault’ [-Wimplicit-function-declaration]
> >    46 |                 if (get_kernel_nofault(instr, (u32
> > *)(fentry_ip - ENDBR_INSN_SIZE)))
> > ...
> 
> It breaks much sooner, complaining about not having dwarf.h.. let me go
> figure out what package provides that :/

Bah, ofcourse there's libdwarf-dev and libdw-dev, both providing
dwarf.h. Obviously I installed libdwarf-dev and instead I need libdw-dev
*hate*

Anyway, yes, compile now fails as advertised.

And patch fixes it -- now I need to figure out what to do about urgent,
because applying it on top of Linus' tree will create conflicts with
patches already in tip/x86/mm *sigh*.
Peter Zijlstra Feb. 13, 2025, 10:40 a.m. UTC | #17
On Thu, Feb 13, 2025 at 06:25:41PM +0800, Haiyue Wang wrote:

> It is header file include indirect :-)
> 
> https://lore.kernel.org/linux-trace-kernel/20250206131711.ea536f165d5b5980b3909acd@kernel.org/T/#t
> 
> File "asm-prototypes.h" is added to entry.S by 'scripts/Makefile.build',
> adding the missed declaration header file can also fix the error:
> 
>  getasmexports =                                                        \
>     { echo "\#include <linux/kernel.h>" ;                               \
>       echo "\#include <linux/string.h>" ;                               \
> +     echo "\#include <linux/uaccess.h>";                               \
>       echo "\#include <asm/asm-prototypes.h>" ;                         \
>       $(call getexportsymbols,EXPORT_SYMBOL(\1);) ; }
> 

So this is simple enough; but the thread you link to also has another
hunk, which makes the whole thing unfortunate.

I'm not entirely sure what this GENDWARFKSYMS nonsense is about, but it
should not clutter the code like that.
Haiyue Wang Feb. 13, 2025, 10:50 a.m. UTC | #18
On 2025/2/13 18:40, Peter Zijlstra wrote:
> On Thu, Feb 13, 2025 at 06:25:41PM +0800, Haiyue Wang wrote:
> 
>> It is header file include indirect :-)
>>
>> https://lore.kernel.org/linux-trace-kernel/20250206131711.ea536f165d5b5980b3909acd@kernel.org/T/#t
>>
>> File "asm-prototypes.h" is added to entry.S by 'scripts/Makefile.build',
>> adding the missed declaration header file can also fix the error:
>>
>>   getasmexports =                                                        \
>>      { echo "\#include <linux/kernel.h>" ;                               \
>>        echo "\#include <linux/string.h>" ;                               \
>> +     echo "\#include <linux/uaccess.h>";                               \
>>        echo "\#include <asm/asm-prototypes.h>" ;                         \
>>        $(call getexportsymbols,EXPORT_SYMBOL(\1);) ; }
>>
> 
> So this is simple enough; but the thread you link to also has another
> hunk, which makes the whole thing unfortunate.
> 
> I'm not entirely sure what this GENDWARFKSYMS nonsense is about, but it
> should not clutter the code like that.

By my understanding, the GENDWARFKSYMS design triggers the missing
header file, even this is inline function, but it will call another
function. It needs to "see" the header file firstly:

So this also fix the error:

--- a/arch/x86/include/asm/asm-prototypes.h
+++ b/arch/x86/include/asm/asm-prototypes.h
@@ -1,7 +1,7 @@
  /* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/ftrace.h>
  #include <linux/uaccess.h>
  #include <linux/pgtable.h>
+#include <asm/ftrace.h>
Masami Hiramatsu (Google) Feb. 13, 2025, 1:35 p.m. UTC | #19
On Thu, 13 Feb 2025 11:26:34 +0100
Peter Zijlstra <peterz@infradead.org> wrote:

> On Thu, Feb 13, 2025 at 11:08:36AM +0100, Peter Zijlstra wrote:
> > On Wed, Feb 12, 2025 at 08:52:27AM -0800, Sami Tolvanen wrote:
> > > On Tue, Feb 11, 2025 at 7:49 AM Steven Rostedt <rostedt@goodmis.org> wrote:
> > > >
> > > > On Tue, 11 Feb 2025 11:09:14 +0100
> > > > Peter Zijlstra <peterz@infradead.org> wrote:
> > > >
> > > > > I was aiming my patch for x86/core, but if there's a reason to expedite
> > > > > them, I can stick it in x86/urgent I suppose.
> > > > >
> > > > > Just need a reason -- what's this compile error nonsense about, my
> > > > > kernels build just fine?
> > > >
> > > > Masami,
> > > >
> > > > Do you have a config that fails to build without this fix? If so, can you
> > > > please reply with it, and then this can go in as a quick fix.
> > > 
> > > x86 builds with both CONFIG_GENDWARFKSYMS and CONFIG_FUNCTION_TRACER
> > > are broken without this fix. Here's how to reproduce:
> > > 
> > > $ make defconfig
> > > $ ./scripts/config -e DEBUG_INFO -e DEBUG_INFO_DWARF5 -e MODVERSIONS
> > > -e GENDWARFKSYMS -e FUNCTION_TRACER
> > > $ make olddefconfig && make -j
> > > ...
> > > In file included from ./arch/x86/include/asm/asm-prototypes.h:2,
> > >                  from <stdin>:3:
> > > ./arch/x86/include/asm/ftrace.h: In function ‘arch_ftrace_get_symaddr’:
> > > ./arch/x86/include/asm/ftrace.h:46:21: error: implicit declaration of
> > > function ‘get_kernel_nofault’ [-Wimplicit-function-declaration]
> > >    46 |                 if (get_kernel_nofault(instr, (u32
> > > *)(fentry_ip - ENDBR_INSN_SIZE)))
> > > ...
> > 
> > It breaks much sooner, complaining about not having dwarf.h.. let me go
> > figure out what package provides that :/
> 
> Bah, ofcourse there's libdwarf-dev and libdw-dev, both providing
> dwarf.h. Obviously I installed libdwarf-dev and instead I need libdw-dev
> *hate*

Agreed. :(

> 
> Anyway, yes, compile now fails as advertised.
> 
> And patch fixes it -- now I need to figure out what to do about urgent,
> because applying it on top of Linus' tree will create conflicts with
> patches already in tip/x86/mm *sigh*.

Hmm, if so, can you pick my patch [1], which does not introduce any
additional header including issue?

[1] https://lore.kernel.org/all/173881156244.211648.1242168038709680511.stgit@devnote2/


Thank you,

> 
>
diff mbox series

Patch

diff --git a/arch/x86/include/asm/ftrace.h b/arch/x86/include/asm/ftrace.h
index f9cb4d07df58..1ed08f2de366 100644
--- a/arch/x86/include/asm/ftrace.h
+++ b/arch/x86/include/asm/ftrace.h
@@ -34,26 +34,11 @@  static inline unsigned long ftrace_call_adjust(unsigned long addr)
 	return addr;
 }
 
-static inline unsigned long arch_ftrace_get_symaddr(unsigned long fentry_ip)
-{
-#ifdef CONFIG_X86_KERNEL_IBT
-	u32 instr;
-
-	/* We want to be extra safe in case entry ip is on the page edge,
-	 * but otherwise we need to avoid get_kernel_nofault()'s overhead.
-	 */
-	if ((fentry_ip & ~PAGE_MASK) < ENDBR_INSN_SIZE) {
-		if (get_kernel_nofault(instr, (u32 *)(fentry_ip - ENDBR_INSN_SIZE)))
-			return fentry_ip;
-	} else {
-		instr = *(u32 *)(fentry_ip - ENDBR_INSN_SIZE);
-	}
-	if (is_endbr(instr))
-		fentry_ip -= ENDBR_INSN_SIZE;
-#endif
-	return fentry_ip;
-}
+/* This does not support mcount. */
+#ifdef CONFIG_HAVE_FENTRY
+unsigned long arch_ftrace_get_symaddr(unsigned long fentry_ip);
 #define ftrace_get_symaddr(fentry_ip)	arch_ftrace_get_symaddr(fentry_ip)
+#endif
 
 #ifdef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS
 
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index 166bc0ea3bdf..7250118005fc 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -29,11 +29,35 @@ 
 
 #include <trace/syscall.h>
 
-#include <asm/kprobes.h>
 #include <asm/ftrace.h>
+#include <asm/ibt.h>
+#include <asm/kprobes.h>
 #include <asm/nops.h>
 #include <asm/text-patching.h>
 
+#ifdef CONFIG_HAVE_FENTRY
+/* Convert fentry address to the symbol address. */
+unsigned long arch_ftrace_get_symaddr(unsigned long fentry_ip)
+{
+#ifdef CONFIG_X86_KERNEL_IBT
+	u32 instr;
+
+	/* We want to be extra safe in case entry ip is on the page edge,
+	 * but otherwise we need to avoid get_kernel_nofault()'s overhead.
+	 */
+	if ((fentry_ip & ~PAGE_MASK) < ENDBR_INSN_SIZE) {
+		if (get_kernel_nofault(instr, (u32 *)(fentry_ip - ENDBR_INSN_SIZE)))
+			return fentry_ip;
+	} else {
+		instr = *(u32 *)(fentry_ip - ENDBR_INSN_SIZE);
+	}
+	if (is_endbr(instr))
+		fentry_ip -= ENDBR_INSN_SIZE;
+#endif
+	return fentry_ip;
+}
+#endif
+
 #ifdef CONFIG_DYNAMIC_FTRACE
 
 static int ftrace_poke_late = 0;