lkml.org 
[lkml]   [2021]   [Jan]   [31]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 08/11] x86/fault: Bypass no_context() for implicit kernel faults from usermode
    Date
    We can drop an indentation level and remove the last user_mode(regs) == true
    caller of no_context() by directly OOPSing for implicit kernel faults from
    usermode.

    Cc: Dave Hansen <dave.hansen@linux.intel.com>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Signed-off-by: Andy Lutomirski <luto@kernel.org>
    ---
    arch/x86/mm/fault.c | 59 ++++++++++++++++++++++++---------------------
    1 file changed, 32 insertions(+), 27 deletions(-)

    diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
    index 6f43d080e1e8..177b612c7f33 100644
    --- a/arch/x86/mm/fault.c
    +++ b/arch/x86/mm/fault.c
    @@ -789,44 +789,49 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
    {
    struct task_struct *tsk = current;

    - /* User mode accesses just cause a SIGSEGV */
    - if (user_mode(regs) && (error_code & X86_PF_USER)) {
    - /*
    - * It's possible to have interrupts off here:
    - */
    - local_irq_enable();
    + if (!user_mode(regs)) {
    + no_context(regs, error_code, address, pkey, si_code);
    + return;
    + }

    - /*
    - * Valid to do another page fault here because this one came
    - * from user space:
    - */
    - if (is_prefetch(regs, error_code, address))
    - return;
    + if (!(error_code & X86_PF_USER)) {
    + /* Implicit user access to kernel memory -- just oops */
    + page_fault_oops(regs, error_code, address);
    + return;
    + }

    - if (is_errata100(regs, address))
    - return;
    + /*
    + * User mode accesses just cause a SIGSEGV.
    + * It's possible to have interrupts off here:
    + */
    + local_irq_enable();

    - sanitize_error_code(address, &error_code);
    + /*
    + * Valid to do another page fault here because this one came
    + * from user space:
    + */
    + if (is_prefetch(regs, error_code, address))
    + return;

    - if (fixup_vdso_exception(regs, X86_TRAP_PF, error_code, address))
    - return;
    + if (is_errata100(regs, address))
    + return;

    - if (likely(show_unhandled_signals))
    - show_signal_msg(regs, error_code, address, tsk);
    + sanitize_error_code(address, &error_code);

    - set_signal_archinfo(address, error_code);
    + if (fixup_vdso_exception(regs, X86_TRAP_PF, error_code, address))
    + return;

    - if (si_code == SEGV_PKUERR)
    - force_sig_pkuerr((void __user *)address, pkey);
    + if (likely(show_unhandled_signals))
    + show_signal_msg(regs, error_code, address, tsk);

    - force_sig_fault(SIGSEGV, si_code, (void __user *)address);
    + set_signal_archinfo(address, error_code);

    - local_irq_disable();
    + if (si_code == SEGV_PKUERR)
    + force_sig_pkuerr((void __user *)address, pkey);

    - return;
    - }
    + force_sig_fault(SIGSEGV, si_code, (void __user *)address);

    - no_context(regs, error_code, address, SIGSEGV, si_code);
    + local_irq_disable();
    }

    static noinline void
    --
    2.29.2
    \
     
     \ /
      Last update: 2021-01-31 22:16    [W:6.143 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site