Skip to content
Snippets Groups Projects
Commit 0aee080d authored by Waiman Long's avatar Waiman Long
Browse files

static_call,x86: Robustify trampoline patching

Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2090231



commit 2105a927
Author: Peter Zijlstra <peterz@infradead.org>
Date:   Sat, 30 Oct 2021 09:47:58 +0200

    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: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
    Link: https://lkml.kernel.org/r/20211030074758.GT174703@worktop.programming.kicks-ass.net



Signed-off-by: default avatarWaiman Long <longman@redhat.com>
parent 99bb09fb
No related merge requests found
......@@ -27,6 +27,7 @@
".globl " STATIC_CALL_TRAMP_STR(name) " \n" \
STATIC_CALL_TRAMP_STR(name) ": \n" \
insns " \n" \
".byte 0x53, 0x43, 0x54 \n" \
".type " STATIC_CALL_TRAMP_STR(name) ", @function \n" \
".size " STATIC_CALL_TRAMP_STR(name) ", . - " STATIC_CALL_TRAMP_STR(name) " \n" \
".popsection \n")
......
......@@ -56,10 +56,15 @@ static void __ref __static_call_transform(void *insn, enum insn_type type, void
text_poke_bp(insn, code, size, emulate);
}
static void __static_call_validate(void *insn, bool tail)
static void __static_call_validate(void *insn, bool tail, bool tramp)
{
u8 opcode = *(u8 *)insn;
if (tramp && memcmp(insn+5, "SCT", 3)) {
pr_err("trampoline signature fail");
BUG();
}
if (tail) {
if (opcode == JMP32_INSN_OPCODE ||
opcode == RET_INSN_OPCODE)
......@@ -74,7 +79,8 @@ static void __static_call_validate(void *insn, bool tail)
/*
* If we ever trigger this, our text is corrupt, we'll probably not live long.
*/
WARN_ONCE(1, "unexpected static_call insn opcode 0x%x at %pS\n", opcode, insn);
pr_err("unexpected static_call insn opcode 0x%x at %pS\n", opcode, insn);
BUG();
}
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)
mutex_lock(&text_mutex);
if (tramp) {
__static_call_validate(tramp, true);
__static_call_validate(tramp, true, true);
__static_call_transform(tramp, __sc_insn(!func, true), func);
}
if (IS_ENABLED(CONFIG_HAVE_STATIC_CALL_INLINE) && site) {
__static_call_validate(site, tail);
__static_call_validate(site, tail, false);
__static_call_transform(site, __sc_insn(!func, tail), func);
}
......
......@@ -3309,6 +3309,9 @@ static bool ignore_unreachable_insn(struct objtool_file *file, struct instructio
if (!insn->func)
return false;
if (insn->func->static_call_tramp)
return true;
/*
* CONFIG_UBSAN_TRAP inserts a UD2 when it sees
* __builtin_unreachable(). The BUG() macro has an unreachable() after
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment