lkml.org 
[lkml]   [2021]   [Oct]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH V3 18/49] x86/traps: Move pt_regs only in fixup_bad_iret()
    Date
    From: Lai Jiangshan <laijs@linux.alibaba.com>

    Make fixup_bad_iret() works like sync_regs() which doesn't
    move the return address of error_entry().

    It is prepared later patch which implements the body of error_entry()
    in C code. The fixup_bad_iret() can't handle return address when it
    is called from C code.

    Signed-off-by: Lai Jiangshan <laijs@linux.alibaba.com>
    ---
    arch/x86/entry/entry_64.S | 5 ++++-
    arch/x86/include/asm/traps.h | 2 +-
    arch/x86/kernel/traps.c | 17 ++++++-----------
    3 files changed, 11 insertions(+), 13 deletions(-)

    diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
    index daaeeb8acd22..7f2338c3b676 100644
    --- a/arch/x86/entry/entry_64.S
    +++ b/arch/x86/entry/entry_64.S
    @@ -1047,9 +1047,12 @@ SYM_CODE_START_LOCAL(error_entry)
    * Pretend that the exception came from user mode: set up pt_regs
    * as if we faulted immediately after IRET.
    */
    - mov %rsp, %rdi
    + popq %r12 /* save return addr in %12 */
    + movq %rsp, %rdi /* arg0 = pt_regs pointer */
    call fixup_bad_iret
    mov %rax, %rsp
    + ENCODE_FRAME_POINTER
    + pushq %r12
    jmp .Lerror_entry_from_usermode_after_swapgs
    SYM_CODE_END(error_entry)

    diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h
    index 6221be7cafc3..1cdd7e8bcba7 100644
    --- a/arch/x86/include/asm/traps.h
    +++ b/arch/x86/include/asm/traps.h
    @@ -13,7 +13,7 @@
    #ifdef CONFIG_X86_64
    asmlinkage __visible notrace struct pt_regs *sync_regs(struct pt_regs *eregs);
    asmlinkage __visible notrace
    -struct bad_iret_stack *fixup_bad_iret(struct bad_iret_stack *s);
    +struct pt_regs *fixup_bad_iret(struct pt_regs *bad_regs);
    void __init trap_init(void);
    asmlinkage __visible noinstr struct pt_regs *vc_switch_off_ist(struct pt_regs *eregs);
    #endif
    diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
    index cf852b5e347f..0afa16ea3702 100644
    --- a/arch/x86/kernel/traps.c
    +++ b/arch/x86/kernel/traps.c
    @@ -759,13 +759,8 @@ asmlinkage __visible noinstr struct pt_regs *vc_switch_off_ist(struct pt_regs *r
    }
    #endif

    -struct bad_iret_stack {
    - void *error_entry_ret;
    - struct pt_regs regs;
    -};
    -
    asmlinkage __visible noinstr
    -struct bad_iret_stack *fixup_bad_iret(struct bad_iret_stack *s)
    +struct pt_regs *fixup_bad_iret(struct pt_regs *bad_regs)
    {
    /*
    * This is called from entry_64.S early in handling a fault
    @@ -775,19 +770,19 @@ struct bad_iret_stack *fixup_bad_iret(struct bad_iret_stack *s)
    * just below the IRET frame) and we want to pretend that the
    * exception came from the IRET target.
    */
    - struct bad_iret_stack tmp, *new_stack =
    - (struct bad_iret_stack *)__this_cpu_read(cpu_tss_rw.x86_tss.sp0) - 1;
    + struct pt_regs tmp, *new_stack =
    + (struct pt_regs *)__this_cpu_read(cpu_tss_rw.x86_tss.sp0) - 1;

    /* Copy the IRET target to the temporary storage. */
    - __memcpy(&tmp.regs.ip, (void *)s->regs.sp, 5*8);
    + __memcpy(&tmp.ip, (void *)bad_regs->sp, 5*8);

    /* Copy the remainder of the stack from the current stack. */
    - __memcpy(&tmp, s, offsetof(struct bad_iret_stack, regs.ip));
    + __memcpy(&tmp, bad_regs, offsetof(struct pt_regs, ip));

    /* Update the entry stack */
    __memcpy(new_stack, &tmp, sizeof(tmp));

    - BUG_ON(!user_mode(&new_stack->regs));
    + BUG_ON(!user_mode(new_stack));
    return new_stack;
    }
    #endif
    --
    2.19.1.6.gb485710b
    \
     
     \ /
      Last update: 2021-10-14 05:36    [W:3.330 / U:0.272 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site