Skip to content

Commit 0ef6f5c

Browse files
Peter ZijlstraAlexei Starovoitov
authored andcommitted
x86,rethook: Fix arch_rethook_trampoline() to generate a complete pt_regs
Currently arch_rethook_trampoline() generates an almost complete pt_regs on-stack, everything except regs->ss that is, that currently points to the fake return address, which is not a valid segment descriptor. Since interpretation of regs->[sb]p should be done in the context of regs->ss, and we have code actually doing that (see arch/x86/lib/insn-eval.c for instance), complete the job by also pushing ss. This ensures that anybody who does do look at regs->ss doesn't mysteriously malfunction, avoiding much future pain. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org> Link: https://lore.kernel.org/bpf/164826164851.2455864.17272661073069737350.stgit@devnote2
1 parent f3a112c commit 0ef6f5c

1 file changed

Lines changed: 13 additions & 11 deletions

File tree

arch/x86/kernel/rethook.c

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,29 +29,31 @@ asm(
2929
/* Push a fake return address to tell the unwinder it's a rethook. */
3030
" pushq $arch_rethook_trampoline\n"
3131
UNWIND_HINT_FUNC
32-
/* Save the 'sp - 8', this will be fixed later. */
32+
" pushq $" __stringify(__KERNEL_DS) "\n"
33+
/* Save the 'sp - 16', this will be fixed later. */
3334
" pushq %rsp\n"
3435
" pushfq\n"
3536
SAVE_REGS_STRING
3637
" movq %rsp, %rdi\n"
3738
" call arch_rethook_trampoline_callback\n"
3839
RESTORE_REGS_STRING
39-
/* In the callback function, 'regs->flags' is copied to 'regs->sp'. */
40-
" addq $8, %rsp\n"
40+
/* In the callback function, 'regs->flags' is copied to 'regs->ss'. */
41+
" addq $16, %rsp\n"
4142
" popfq\n"
4243
#else
4344
/* Push a fake return address to tell the unwinder it's a rethook. */
4445
" pushl $arch_rethook_trampoline\n"
4546
UNWIND_HINT_FUNC
46-
/* Save the 'sp - 4', this will be fixed later. */
47+
" pushl %ss\n"
48+
/* Save the 'sp - 8', this will be fixed later. */
4749
" pushl %esp\n"
4850
" pushfl\n"
4951
SAVE_REGS_STRING
5052
" movl %esp, %eax\n"
5153
" call arch_rethook_trampoline_callback\n"
5254
RESTORE_REGS_STRING
53-
/* In the callback function, 'regs->flags' is copied to 'regs->sp'. */
54-
" addl $4, %esp\n"
55+
/* In the callback function, 'regs->flags' is copied to 'regs->ss'. */
56+
" addl $8, %esp\n"
5557
" popfl\n"
5658
#endif
5759
ASM_RET
@@ -73,8 +75,8 @@ __used __visible void arch_rethook_trampoline_callback(struct pt_regs *regs)
7375
#endif
7476
regs->ip = (unsigned long)&arch_rethook_trampoline;
7577
regs->orig_ax = ~0UL;
76-
regs->sp += sizeof(long);
77-
frame_pointer = &regs->sp + 1;
78+
regs->sp += 2*sizeof(long);
79+
frame_pointer = (long *)(regs + 1);
7880

7981
/*
8082
* The return address at 'frame_pointer' is recovered by the
@@ -84,10 +86,10 @@ __used __visible void arch_rethook_trampoline_callback(struct pt_regs *regs)
8486
rethook_trampoline_handler(regs, (unsigned long)frame_pointer);
8587

8688
/*
87-
* Copy FLAGS to 'pt_regs::sp' so that arch_rethook_trapmoline()
89+
* Copy FLAGS to 'pt_regs::ss' so that arch_rethook_trapmoline()
8890
* can do RET right after POPF.
8991
*/
90-
regs->sp = regs->flags;
92+
*(unsigned long *)&regs->ss = regs->flags;
9193
}
9294
NOKPROBE_SYMBOL(arch_rethook_trampoline_callback);
9395

@@ -105,7 +107,7 @@ STACK_FRAME_NON_STANDARD_FP(arch_rethook_trampoline);
105107
void arch_rethook_fixup_return(struct pt_regs *regs,
106108
unsigned long correct_ret_addr)
107109
{
108-
unsigned long *frame_pointer = &regs->sp + 1;
110+
unsigned long *frame_pointer = (void *)(regs + 1);
109111

110112
/* Replace fake return address with real one. */
111113
*frame_pointer = correct_ret_addr;

0 commit comments

Comments
 (0)