summaryrefslogtreecommitdiff
path: root/tools/objtool
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2022-06-14 23:15:48 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-07-23 12:54:01 +0200
commita9c0926fc75468ccea0cf1f3b48b0d5a41291975 (patch)
treecf13a7cf175b0da2b35a08d2a098f3b290058f5e /tools/objtool
parent07f5c5e36236368ca761868ed82c8b654f58968a (diff)
downloadlinux-a9c0926fc75468ccea0cf1f3b48b0d5a41291975.tar.gz
linux-a9c0926fc75468ccea0cf1f3b48b0d5a41291975.tar.bz2
linux-a9c0926fc75468ccea0cf1f3b48b0d5a41291975.zip
x86: Add magic AMD return-thunk
commit a149180fbcf336e97ce4eb2cdc13672727feb94d upstream. 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> [cascardo: conflicts at arch/x86/entry/entry_64_compat.S] [cascardo: there is no ANNOTATE_NOENDBR] [cascardo: objtool commit 34c861e806478ac2ea4032721defbf1d6967df08 missing] [cascardo: conflict fixup] Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'tools/objtool')
-rw-r--r--tools/objtool/check.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index a955cf4cf932..a90f0d657716 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1145,7 +1145,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,
@@ -1155,7 +1155,7 @@ static void add_return_call(struct objtool_file *file, struct instruction *insn)
insn->retpoline_safe = true;
/* Skip the non-text sections, specially .discard ones */
- if (insn->sec->text)
+ if (add && insn->sec->text)
list_add_tail(&insn->call_node, &file->return_thunk_list);
}
@@ -1184,7 +1184,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) {
/* internal or external sibling call (with reloc) */
@@ -1201,6 +1201,7 @@ static int add_jump_destinations(struct objtool_file *file)
insn->jump_dest = find_insn(file, dest_sec, dest_off);
if (!insn->jump_dest) {
+ struct symbol *sym = find_symbol_by_offset(dest_sec, dest_off);
/*
* This is a special case where an alt instruction
@@ -1210,6 +1211,19 @@ static int add_jump_destinations(struct objtool_file *file)
if (!strcmp(insn->sec->name, ".altinstr_replacement"))
continue;
+ /*
+ * 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);