summaryrefslogtreecommitdiffstats
path: root/tools/objtool
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2022-06-14 23:15:48 +0200
committerBorislav Petkov <bp@suse.de>2022-06-27 10:33:59 +0200
commita149180fbcf336e97ce4eb2cdc13672727feb94d (patch)
tree465e0b2ebf7a147d686abed224a732907c475c1b /tools/objtool
parentobjtool: Treat .text.__x86.* as noinstr (diff)
downloadlinux-a149180fbcf336e97ce4eb2cdc13672727feb94d.tar.xz
linux-a149180fbcf336e97ce4eb2cdc13672727feb94d.zip
x86: Add magic AMD return-thunk
Note: needs to be in a section distinct from Retpolines such that the Retpoline RET substitution cannot possibly use immediate jumps. ORC unwinding for zen_untrain_ret() and __x86_return_thunk() is a little tricky but works due to the fact that zen_untrain_ret() doesn't have any stack ops and as such will emit a single ORC entry at the start (+0x3f). Meanwhile, unwinding an IP, including the __x86_return_thunk() one (+0x40) will search for the largest ORC entry smaller or equal to the IP, these will find the one ORC entry (+0x3f) and all works. [ Alexandre: SVM part. ] [ bp: Build fix, massages. ] Suggested-by: Andrew Cooper <Andrew.Cooper3@citrix.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Borislav Petkov <bp@suse.de> Reviewed-by: Josh Poimboeuf <jpoimboe@kernel.org> Signed-off-by: Borislav Petkov <bp@suse.de>
Diffstat (limited to 'tools/objtool')
-rw-r--r--tools/objtool/check.c22
1 files changed, 19 insertions, 3 deletions
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index b98fd68013c3..4252cd05dfc4 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1302,7 +1302,7 @@ static void add_retpoline_call(struct objtool_file *file, struct instruction *in
annotate_call_site(file, insn, false);
}
-static void add_return_call(struct objtool_file *file, struct instruction *insn)
+static void add_return_call(struct objtool_file *file, struct instruction *insn, bool add)
{
/*
* Return thunk tail calls are really just returns in disguise,
@@ -1311,7 +1311,8 @@ static void add_return_call(struct objtool_file *file, struct instruction *insn)
insn->type = INSN_RETURN;
insn->retpoline_safe = true;
- list_add_tail(&insn->call_node, &file->return_thunk_list);
+ if (add)
+ list_add_tail(&insn->call_node, &file->return_thunk_list);
}
static bool same_function(struct instruction *insn1, struct instruction *insn2)
@@ -1367,7 +1368,7 @@ static int add_jump_destinations(struct objtool_file *file)
add_retpoline_call(file, insn);
continue;
} else if (reloc->sym->return_thunk) {
- add_return_call(file, insn);
+ add_return_call(file, insn, true);
continue;
} else if (insn->func) {
/*
@@ -1387,6 +1388,21 @@ static int add_jump_destinations(struct objtool_file *file)
jump_dest = find_insn(file, dest_sec, dest_off);
if (!jump_dest) {
+ struct symbol *sym = find_symbol_by_offset(dest_sec, dest_off);
+
+ /*
+ * This is a special case for zen_untrain_ret().
+ * It jumps to __x86_return_thunk(), but objtool
+ * can't find the thunk's starting RET
+ * instruction, because the RET is also in the
+ * middle of another instruction. Objtool only
+ * knows about the outer instruction.
+ */
+ if (sym && sym->return_thunk) {
+ add_return_call(file, insn, false);
+ continue;
+ }
+
WARN_FUNC("can't find jump dest instruction at %s+0x%lx",
insn->sec, insn->offset, dest_sec->name,
dest_off);