Skip to content

Commit 2105a92

Browse files
author
Peter Zijlstra
committed
static_call,x86: Robustify trampoline patching
Add a few signature bytes after the static call trampoline and verify those bytes match before patching the trampoline. This avoids patching random other JMPs (such as CFI jump-table entries) instead. These bytes decode as: d: 53 push %rbx e: 43 54 rex.XB push %r12 And happen to spell "SCT". Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent debe436 commit 2105a92

File tree

3 files changed

+14
-4
lines changed

3 files changed

+14
-4
lines changed

arch/x86/include/asm/static_call.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
".globl " STATIC_CALL_TRAMP_STR(name) " \n" \
2828
STATIC_CALL_TRAMP_STR(name) ": \n" \
2929
insns " \n" \
30+
".byte 0x53, 0x43, 0x54 \n" \
3031
".type " STATIC_CALL_TRAMP_STR(name) ", @function \n" \
3132
".size " STATIC_CALL_TRAMP_STR(name) ", . - " STATIC_CALL_TRAMP_STR(name) " \n" \
3233
".popsection \n")

arch/x86/kernel/static_call.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,15 @@ static void __ref __static_call_transform(void *insn, enum insn_type type, void
5656
text_poke_bp(insn, code, size, emulate);
5757
}
5858

59-
static void __static_call_validate(void *insn, bool tail)
59+
static void __static_call_validate(void *insn, bool tail, bool tramp)
6060
{
6161
u8 opcode = *(u8 *)insn;
6262

63+
if (tramp && memcmp(insn+5, "SCT", 3)) {
64+
pr_err("trampoline signature fail");
65+
BUG();
66+
}
67+
6368
if (tail) {
6469
if (opcode == JMP32_INSN_OPCODE ||
6570
opcode == RET_INSN_OPCODE)
@@ -74,7 +79,8 @@ static void __static_call_validate(void *insn, bool tail)
7479
/*
7580
* If we ever trigger this, our text is corrupt, we'll probably not live long.
7681
*/
77-
WARN_ONCE(1, "unexpected static_call insn opcode 0x%x at %pS\n", opcode, insn);
82+
pr_err("unexpected static_call insn opcode 0x%x at %pS\n", opcode, insn);
83+
BUG();
7884
}
7985

8086
static inline enum insn_type __sc_insn(bool null, bool tail)
@@ -97,12 +103,12 @@ void arch_static_call_transform(void *site, void *tramp, void *func, bool tail)
97103
mutex_lock(&text_mutex);
98104

99105
if (tramp) {
100-
__static_call_validate(tramp, true);
106+
__static_call_validate(tramp, true, true);
101107
__static_call_transform(tramp, __sc_insn(!func, true), func);
102108
}
103109

104110
if (IS_ENABLED(CONFIG_HAVE_STATIC_CALL_INLINE) && site) {
105-
__static_call_validate(site, tail);
111+
__static_call_validate(site, tail, false);
106112
__static_call_transform(site, __sc_insn(!func, tail), func);
107113
}
108114

tools/objtool/check.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3310,6 +3310,9 @@ static bool ignore_unreachable_insn(struct objtool_file *file, struct instructio
33103310
if (!insn->func)
33113311
return false;
33123312

3313+
if (insn->func->static_call_tramp)
3314+
return true;
3315+
33133316
/*
33143317
* CONFIG_UBSAN_TRAP inserts a UD2 when it sees
33153318
* __builtin_unreachable(). The BUG() macro has an unreachable() after

0 commit comments

Comments
 (0)