mirror of https://github.com/torvalds/linux.git
x86/alternative: Refactor INT3 call emulation selftest
The INT3 call emulation selftest is a bit fragile as it relies on the compiler not inserting any extra instructions before the int3_selftest_ip() definition. Also, the int3_selftest_ip() symbol overlaps with the int3_selftest symbol(), which can confuse objtool. Fix those issues by slightly reworking the functionality and moving int3_selftest_ip() to a separate asm function. While at it, improve the naming. Acked-by: Petr Mladek <pmladek@suse.com> Tested-by: Joe Lawrence <joe.lawrence@redhat.com> Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
This commit is contained in:
parent
4109043bff
commit
3049fc4b5f
|
|
@ -2244,21 +2244,34 @@ int alternatives_text_reserved(void *start, void *end)
|
||||||
* See entry_{32,64}.S for more details.
|
* See entry_{32,64}.S for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
extern void int3_selftest_asm(unsigned int *ptr);
|
||||||
* We define the int3_magic() function in assembly to control the calling
|
|
||||||
* convention such that we can 'call' it from assembly.
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern void int3_magic(unsigned int *ptr); /* defined in asm */
|
|
||||||
|
|
||||||
asm (
|
asm (
|
||||||
" .pushsection .init.text, \"ax\", @progbits\n"
|
" .pushsection .init.text, \"ax\", @progbits\n"
|
||||||
" .type int3_magic, @function\n"
|
" .type int3_selftest_asm, @function\n"
|
||||||
"int3_magic:\n"
|
"int3_selftest_asm:\n"
|
||||||
ANNOTATE_NOENDBR
|
ANNOTATE_NOENDBR
|
||||||
" movl $1, (%" _ASM_ARG1 ")\n"
|
/*
|
||||||
|
* INT3 padded with NOP to CALL_INSN_SIZE. The INT3 triggers an
|
||||||
|
* exception, then the int3_exception_nb notifier emulates a call to
|
||||||
|
* int3_selftest_callee().
|
||||||
|
*/
|
||||||
|
" int3; nop; nop; nop; nop\n"
|
||||||
ASM_RET
|
ASM_RET
|
||||||
" .size int3_magic, .-int3_magic\n"
|
" .size int3_selftest_asm, . - int3_selftest_asm\n"
|
||||||
|
" .popsection\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
extern void int3_selftest_callee(unsigned int *ptr);
|
||||||
|
|
||||||
|
asm (
|
||||||
|
" .pushsection .init.text, \"ax\", @progbits\n"
|
||||||
|
" .type int3_selftest_callee, @function\n"
|
||||||
|
"int3_selftest_callee:\n"
|
||||||
|
ANNOTATE_NOENDBR
|
||||||
|
" movl $0x1234, (%" _ASM_ARG1 ")\n"
|
||||||
|
ASM_RET
|
||||||
|
" .size int3_selftest_callee, . - int3_selftest_callee\n"
|
||||||
" .popsection\n"
|
" .popsection\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -2267,7 +2280,7 @@ extern void int3_selftest_ip(void); /* defined in asm below */
|
||||||
static int __init
|
static int __init
|
||||||
int3_exception_notify(struct notifier_block *self, unsigned long val, void *data)
|
int3_exception_notify(struct notifier_block *self, unsigned long val, void *data)
|
||||||
{
|
{
|
||||||
unsigned long selftest = (unsigned long)&int3_selftest_ip;
|
unsigned long selftest = (unsigned long)&int3_selftest_asm;
|
||||||
struct die_args *args = data;
|
struct die_args *args = data;
|
||||||
struct pt_regs *regs = args->regs;
|
struct pt_regs *regs = args->regs;
|
||||||
|
|
||||||
|
|
@ -2282,7 +2295,7 @@ int3_exception_notify(struct notifier_block *self, unsigned long val, void *data
|
||||||
if (regs->ip - INT3_INSN_SIZE != selftest)
|
if (regs->ip - INT3_INSN_SIZE != selftest)
|
||||||
return NOTIFY_DONE;
|
return NOTIFY_DONE;
|
||||||
|
|
||||||
int3_emulate_call(regs, (unsigned long)&int3_magic);
|
int3_emulate_call(regs, (unsigned long)&int3_selftest_callee);
|
||||||
return NOTIFY_STOP;
|
return NOTIFY_STOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2298,19 +2311,11 @@ static noinline void __init int3_selftest(void)
|
||||||
BUG_ON(register_die_notifier(&int3_exception_nb));
|
BUG_ON(register_die_notifier(&int3_exception_nb));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Basically: int3_magic(&val); but really complicated :-)
|
* Basically: int3_selftest_callee(&val); but really complicated :-)
|
||||||
*
|
|
||||||
* INT3 padded with NOP to CALL_INSN_SIZE. The int3_exception_nb
|
|
||||||
* notifier above will emulate CALL for us.
|
|
||||||
*/
|
*/
|
||||||
asm volatile ("int3_selftest_ip:\n\t"
|
int3_selftest_asm(&val);
|
||||||
ANNOTATE_NOENDBR
|
|
||||||
" int3; nop; nop; nop; nop\n\t"
|
|
||||||
: ASM_CALL_CONSTRAINT
|
|
||||||
: __ASM_SEL_RAW(a, D) (&val)
|
|
||||||
: "memory");
|
|
||||||
|
|
||||||
BUG_ON(val != 1);
|
BUG_ON(val != 0x1234);
|
||||||
|
|
||||||
unregister_die_notifier(&int3_exception_nb);
|
unregister_die_notifier(&int3_exception_nb);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue