tools/objtool/arch/x86/decode.c | 11 +++++++---- tools/objtool/check.c | 24 ++++++++++++++++++++++-- tools/objtool/include/objtool/arch.h | 1 + tools/objtool/include/objtool/elf.h | 1 + 4 files changed, 31 insertions(+), 6 deletions(-)
The following commit has been merged into the x86/urgent branch of tip:
Commit-ID: 4ae68b26c3ab5a82aa271e6e9fc9b1a06e1d6b40
Gitweb: https://git.kernel.org/tip/4ae68b26c3ab5a82aa271e6e9fc9b1a06e1d6b40
Author: Peter Zijlstra <peterz@infradead.org>
AuthorDate: Mon, 14 Aug 2023 13:44:29 +02:00
Committer: Borislav Petkov (AMD) <bp@alien8.de>
CommitterDate: Wed, 16 Aug 2023 09:39:16 +02:00
objtool/x86: Fix SRSO mess
Objtool --rethunk does two things:
- it collects all (tail) call's of __x86_return_thunk and places them
into .return_sites. These are typically compiler generated, but
RET also emits this same.
- it fudges the validation of the __x86_return_thunk symbol; because
this symbol is inside another instruction, it can't actually find
the instruction pointed to by the symbol offset and gets upset.
Because these two things pertained to the same symbol, there was no
pressing need to separate these two separate things.
However, alas, along comes SRSO and more crazy things to deal with
appeared.
The SRSO patch itself added the following symbol names to identify as
rethunk:
'srso_untrain_ret', 'srso_safe_ret' and '__ret'
Where '__ret' is the old retbleed return thunk, 'srso_safe_ret' is a
new similarly embedded return thunk, and 'srso_untrain_ret' is
completely unrelated to anything the above does (and was only included
because of that INT3 vs UD2 issue fixed previous).
Clear things up by adding a second category for the embedded instruction
thing.
Fixes: fb3bd914b3ec ("x86/srso: Add a Speculative RAS Overflow mitigation")
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Link: https://lore.kernel.org/r/20230814121148.704502245@infradead.org
---
tools/objtool/arch/x86/decode.c | 11 +++++++----
tools/objtool/check.c | 24 ++++++++++++++++++++++--
tools/objtool/include/objtool/arch.h | 1 +
tools/objtool/include/objtool/elf.h | 1 +
4 files changed, 31 insertions(+), 6 deletions(-)
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index 2d51fa8..cba8a7b 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -824,8 +824,11 @@ bool arch_is_retpoline(struct symbol *sym)
bool arch_is_rethunk(struct symbol *sym)
{
- return !strcmp(sym->name, "__x86_return_thunk") ||
- !strcmp(sym->name, "srso_untrain_ret") ||
- !strcmp(sym->name, "srso_safe_ret") ||
- !strcmp(sym->name, "__ret");
+ return !strcmp(sym->name, "__x86_return_thunk");
+}
+
+bool arch_is_embedded_insn(struct symbol *sym)
+{
+ return !strcmp(sym->name, "__ret") ||
+ !strcmp(sym->name, "srso_safe_ret");
}
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index e2ee10c..191656e 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -455,7 +455,7 @@ static int decode_instructions(struct objtool_file *file)
return -1;
}
- if (func->return_thunk || func->alias != func)
+ if (func->embedded_insn || func->alias != func)
continue;
if (!find_insn(file, sec, func->offset)) {
@@ -1288,16 +1288,33 @@ static int add_ignore_alternatives(struct objtool_file *file)
return 0;
}
+/*
+ * Symbols that replace INSN_CALL_DYNAMIC, every (tail) call to such a symbol
+ * will be added to the .retpoline_sites section.
+ */
__weak bool arch_is_retpoline(struct symbol *sym)
{
return false;
}
+/*
+ * Symbols that replace INSN_RETURN, every (tail) call to such a symbol
+ * will be added to the .return_sites section.
+ */
__weak bool arch_is_rethunk(struct symbol *sym)
{
return false;
}
+/*
+ * Symbols that are embedded inside other instructions, because sometimes crazy
+ * code exists. These are mostly ignored for validation purposes.
+ */
+__weak bool arch_is_embedded_insn(struct symbol *sym)
+{
+ return false;
+}
+
static struct reloc *insn_reloc(struct objtool_file *file, struct instruction *insn)
{
struct reloc *reloc;
@@ -1583,7 +1600,7 @@ static int add_jump_destinations(struct objtool_file *file)
* middle of another instruction. Objtool only
* knows about the outer instruction.
*/
- if (sym && sym->return_thunk) {
+ if (sym && sym->embedded_insn) {
add_return_call(file, insn, false);
continue;
}
@@ -2502,6 +2519,9 @@ static int classify_symbols(struct objtool_file *file)
if (arch_is_rethunk(func))
func->return_thunk = true;
+ if (arch_is_embedded_insn(func))
+ func->embedded_insn = true;
+
if (arch_ftrace_match(func->name))
func->fentry = true;
diff --git a/tools/objtool/include/objtool/arch.h b/tools/objtool/include/objtool/arch.h
index 2b6d2ce..0b303eb 100644
--- a/tools/objtool/include/objtool/arch.h
+++ b/tools/objtool/include/objtool/arch.h
@@ -90,6 +90,7 @@ int arch_decode_hint_reg(u8 sp_reg, int *base);
bool arch_is_retpoline(struct symbol *sym);
bool arch_is_rethunk(struct symbol *sym);
+bool arch_is_embedded_insn(struct symbol *sym);
int arch_rewrite_retpolines(struct objtool_file *file);
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index c532d70..9f71e98 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -66,6 +66,7 @@ struct symbol {
u8 fentry : 1;
u8 profiling_func : 1;
u8 warned : 1;
+ u8 embedded_insn : 1;
struct list_head pv_target;
struct reloc *relocs;
};
On Wed, Aug 16, 2023 at 07:55:17AM -0000, tip-bot2 for Peter Zijlstra wrote:
> The following commit has been merged into the x86/urgent branch of tip:
>
> Commit-ID: 4ae68b26c3ab5a82aa271e6e9fc9b1a06e1d6b40
> Gitweb: https://git.kernel.org/tip/4ae68b26c3ab5a82aa271e6e9fc9b1a06e1d6b40
> Author: Peter Zijlstra <peterz@infradead.org>
> AuthorDate: Mon, 14 Aug 2023 13:44:29 +02:00
> Committer: Borislav Petkov (AMD) <bp@alien8.de>
> CommitterDate: Wed, 16 Aug 2023 09:39:16 +02:00
>
> objtool/x86: Fix SRSO mess
>
> Objtool --rethunk does two things:
>
> - it collects all (tail) call's of __x86_return_thunk and places them
> into .return_sites. These are typically compiler generated, but
> RET also emits this same.
>
> - it fudges the validation of the __x86_return_thunk symbol; because
> this symbol is inside another instruction, it can't actually find
> the instruction pointed to by the symbol offset and gets upset.
>
> Because these two things pertained to the same symbol, there was no
> pressing need to separate these two separate things.
>
> However, alas, along comes SRSO and more crazy things to deal with
> appeared.
>
> The SRSO patch itself added the following symbol names to identify as
> rethunk:
>
> 'srso_untrain_ret', 'srso_safe_ret' and '__ret'
>
> Where '__ret' is the old retbleed return thunk, 'srso_safe_ret' is a
> new similarly embedded return thunk, and 'srso_untrain_ret' is
> completely unrelated to anything the above does (and was only included
> because of that INT3 vs UD2 issue fixed previous).
>
> Clear things up by adding a second category for the embedded instruction
> thing.
>
> Fixes: fb3bd914b3ec ("x86/srso: Add a Speculative RAS Overflow mitigation")
> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
> Link: https://lore.kernel.org/r/20230814121148.704502245@infradead.org
Turns out I forgot to build with FRAME_POINTER=y, that still gives:
vmlinux.o: warning: objtool: srso_untrain_ret+0xd: call without frame pointer save/setup
the below seems to cure this.
---
tools/objtool/check.c | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 7a9aaf400873..1384090530db 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -2650,12 +2650,17 @@ static int decode_sections(struct objtool_file *file)
return 0;
}
-static bool is_fentry_call(struct instruction *insn)
+static bool is_special_call(struct instruction *insn)
{
- if (insn->type == INSN_CALL &&
- insn_call_dest(insn) &&
- insn_call_dest(insn)->fentry)
- return true;
+ if (insn->type == INSN_CALL) {
+ struct symbol *dest = insn_call_dest(insn);
+
+ if (!dest)
+ return false;
+
+ if (dest->fentry || dest->embedded_insn)
+ return true;
+ }
return false;
}
@@ -3656,7 +3661,7 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
if (ret)
return ret;
- if (opts.stackval && func && !is_fentry_call(insn) &&
+ if (opts.stackval && func && !is_special_call(insn) &&
!has_valid_stack_frame(&state)) {
WARN_INSN(insn, "call without frame pointer save/setup");
return 1;
On Wed, Aug 16, 2023 at 01:59:21PM +0200, Peter Zijlstra wrote: > Turns out I forgot to build with FRAME_POINTER=y, that still gives: > > vmlinux.o: warning: objtool: srso_untrain_ret+0xd: call without frame pointer save/setup > > the below seems to cure this. LGTM -- Josh
On Wed, Aug 16, 2023 at 01:31:52PM -0700, Josh Poimboeuf wrote:
> On Wed, Aug 16, 2023 at 01:59:21PM +0200, Peter Zijlstra wrote:
> > Turns out I forgot to build with FRAME_POINTER=y, that still gives:
> >
> > vmlinux.o: warning: objtool: srso_untrain_ret+0xd: call without frame pointer save/setup
> >
> > the below seems to cure this.
>
> LGTM
OK, with Changelog below.
---
Subject: objtool/x86: Fixup frame-pointer vs rethunk
From: Peter Zijlstra <peterz@infradead.org>
Date: Wed, 16 Aug 2023 13:59:21 +0200
For stack-validation of a frame-pointer build, objtool validates that
every CALL instructions is preceded by a frame-setup. The new SRSO
return thunks violate this with their RSB stuffing trickery.
Extend the __fentry__ exception to also cover the embedded_insn case
used for this. This cures:
vmlinux.o: warning: objtool: srso_untrain_ret+0xd: call without frame pointer save/setup
Fixes: 4ae68b26c3ab ("objtool/x86: Fix SRSO mess")
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
tools/objtool/check.c | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -2630,12 +2630,17 @@ static int decode_sections(struct objtoo
return 0;
}
-static bool is_fentry_call(struct instruction *insn)
+static bool is_special_call(struct instruction *insn)
{
- if (insn->type == INSN_CALL &&
- insn_call_dest(insn) &&
- insn_call_dest(insn)->fentry)
- return true;
+ if (insn->type == INSN_CALL) {
+ struct symbol *dest = insn_call_dest(insn);
+
+ if (!dest)
+ return false;
+
+ if (dest->fentry || dest->embedded_insn)
+ return true;
+ }
return false;
}
@@ -3636,7 +3641,7 @@ static int validate_branch(struct objtoo
if (ret)
return ret;
- if (opts.stackval && func && !is_fentry_call(insn) &&
+ if (opts.stackval && func && !is_special_call(insn) &&
!has_valid_stack_frame(&state)) {
WARN_INSN(insn, "call without frame pointer save/setup");
return 1;
On Thu, Aug 17, 2023 at 12:08:40AM +0200, Peter Zijlstra wrote:
> On Wed, Aug 16, 2023 at 01:31:52PM -0700, Josh Poimboeuf wrote:
> > On Wed, Aug 16, 2023 at 01:59:21PM +0200, Peter Zijlstra wrote:
> > > Turns out I forgot to build with FRAME_POINTER=y, that still gives:
> > >
> > > vmlinux.o: warning: objtool: srso_untrain_ret+0xd: call without frame pointer save/setup
> > >
> > > the below seems to cure this.
> >
> > LGTM
>
> OK, with Changelog below.
>
> ---
> Subject: objtool/x86: Fixup frame-pointer vs rethunk
> From: Peter Zijlstra <peterz@infradead.org>
> Date: Wed, 16 Aug 2023 13:59:21 +0200
>
> For stack-validation of a frame-pointer build, objtool validates that
> every CALL instructions is preceded by a frame-setup. The new SRSO
> return thunks violate this with their RSB stuffing trickery.
>
> Extend the __fentry__ exception to also cover the embedded_insn case
> used for this. This cures:
>
> vmlinux.o: warning: objtool: srso_untrain_ret+0xd: call without frame pointer save/setup
>
> Fixes: 4ae68b26c3ab ("objtool/x86: Fix SRSO mess")
> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Josh Poimboeuf <jpoimboe@kernel.org>
--
Josh
The following commit has been merged into the x86/urgent branch of tip:
Commit-ID: dbf46008775516f7f25c95b7760041c286299783
Gitweb: https://git.kernel.org/tip/dbf46008775516f7f25c95b7760041c286299783
Author: Peter Zijlstra <peterz@infradead.org>
AuthorDate: Wed, 16 Aug 2023 13:59:21 +02:00
Committer: Borislav Petkov (AMD) <bp@alien8.de>
CommitterDate: Thu, 17 Aug 2023 00:44:35 +02:00
objtool/x86: Fixup frame-pointer vs rethunk
For stack-validation of a frame-pointer build, objtool validates that
every CALL instruction is preceded by a frame-setup. The new SRSO
return thunks violate this with their RSB stuffing trickery.
Extend the __fentry__ exception to also cover the embedded_insn case
used for this. This cures:
vmlinux.o: warning: objtool: srso_untrain_ret+0xd: call without frame pointer save/setup
Fixes: 4ae68b26c3ab ("objtool/x86: Fix SRSO mess")
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Acked-by: Josh Poimboeuf <jpoimboe@kernel.org>
Link: https://lore.kernel.org/r/20230816115921.GH980931@hirez.programming.kicks-ass.net
---
tools/objtool/check.c | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 7a9aaf4..1384090 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -2650,12 +2650,17 @@ static int decode_sections(struct objtool_file *file)
return 0;
}
-static bool is_fentry_call(struct instruction *insn)
+static bool is_special_call(struct instruction *insn)
{
- if (insn->type == INSN_CALL &&
- insn_call_dest(insn) &&
- insn_call_dest(insn)->fentry)
- return true;
+ if (insn->type == INSN_CALL) {
+ struct symbol *dest = insn_call_dest(insn);
+
+ if (!dest)
+ return false;
+
+ if (dest->fentry || dest->embedded_insn)
+ return true;
+ }
return false;
}
@@ -3656,7 +3661,7 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
if (ret)
return ret;
- if (opts.stackval && func && !is_fentry_call(insn) &&
+ if (opts.stackval && func && !is_special_call(insn) &&
!has_valid_stack_frame(&state)) {
WARN_INSN(insn, "call without frame pointer save/setup");
return 1;
© 2016 - 2025 Red Hat, Inc.