[PATCH 5/5] arm: Enable IRQs before attempting to read user space in __und_usr

Arun KS arunks.linux at gmail.com
Tue Apr 1 05:24:15 PDT 2014


Hi Catalin,

On Thu, Mar 13, 2014 at 11:45 PM, Catalin Marinas
<catalin.marinas at arm.com> wrote:
> The Undef abort handler in the kernel reads the undefined instruction
> from user space. If the page table was modified from another CPU, the
> user access could fail and do_page_fault() will be executed with
> interrupts disabled. This can potentially deadlock on ARM11MPCore or on
> Cortex-A15 with erratum 798181 workaround enabled (both implying IPI for
> TLB maintenance with page table lock held).
>
> This patch enables the IRQs in __und_usr before attempting to read the
> instruction from user space.
>
> Signed-off-by: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Hartley Sweeten <hsweeten at visionengravers.com>
> Cc: Ryan Mallon <rmallon at gmail.com>
> ---
>  arch/arm/kernel/entry-armv.S       | 11 +++++++----
>  arch/arm/kernel/iwmmxt.S           |  2 +-
>  arch/arm/mach-ep93xx/crunch-bits.S |  2 +-
>  arch/arm/vfp/entry.S               |  3 +--
>  4 files changed, 10 insertions(+), 8 deletions(-)
>
> diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
> index 1879e8dd2acc..5fc897cf409b 100644
> --- a/arch/arm/kernel/entry-armv.S
> +++ b/arch/arm/kernel/entry-armv.S
> @@ -413,6 +413,11 @@ __und_usr:
>         @
>         adr     r9, BSYM(ret_from_exception)
>
> +       @ IRQs must be enabled before attempting to read the instruction from
> +       @ user space since that could cause a page/translation fault if the
> +       @ page table was modified by another CPU.
> +       enable_irq
> +
>         tst     r3, #PSR_T_BIT                  @ Thumb mode?
>         bne     __und_usr_thumb
>         sub     r4, r2, #4                      @ ARM instr at LR - 4

As the data abort is now handled in normal way, can we remove the
fixup handler for ldrt?

/*
 * The out of line fixup for the ldrt instructions above.
 */
        .pushsection .fixup, "ax"
        .align  2
4:      mov     pc, r9
        .popsection
        .pushsection __ex_table,"a"
        .long   1b, 4b
#if CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7
        .long   2b, 4b
        .long   3b, 4b
#endif
        .popsection


Thanks,
Arun

> @@ -517,7 +522,7 @@ ENDPROC(__und_usr)
>   *  r9  = normal "successful" return address
>   *  r10 = this threads thread_info structure
>   *  lr  = unrecognised instruction return address
> - * IRQs disabled, FIQs enabled.
> + * IRQs enabled, FIQs enabled.
>   */
>         @
>         @ Fall-through from Thumb-2 __und_usr
> @@ -624,7 +629,6 @@ call_fpe:
>  #endif
>
>  do_fpe:
> -       enable_irq
>         ldr     r4, .LCfp
>         add     r10, r10, #TI_FPSTATE           @ r10 = workspace
>         ldr     pc, [r4]                        @ Call FP module USR entry point
> @@ -652,8 +656,7 @@ __und_usr_fault_32:
>         b       1f
>  __und_usr_fault_16:
>         mov     r1, #2
> -1:     enable_irq
> -       mov     r0, sp
> +1:     mov     r0, sp
>         adr     lr, BSYM(ret_from_exception)
>         b       __und_fault
>  ENDPROC(__und_usr_fault_32)
> diff --git a/arch/arm/kernel/iwmmxt.S b/arch/arm/kernel/iwmmxt.S
> index c52f3e225aeb..da3117054712 100644
> --- a/arch/arm/kernel/iwmmxt.S
> +++ b/arch/arm/kernel/iwmmxt.S
> @@ -61,7 +61,7 @@
>   * r9  = ret_from_exception
>   * lr  = undefined instr exit
>   *
> - * called from prefetch exception handler with interrupts disabled
> + * called from prefetch exception handler with interrupts enabled
>   */
>
>  ENTRY(iwmmxt_task_enable)
> diff --git a/arch/arm/mach-ep93xx/crunch-bits.S b/arch/arm/mach-ep93xx/crunch-bits.S
> index 890c5df2b4fe..85e765534003 100644
> --- a/arch/arm/mach-ep93xx/crunch-bits.S
> +++ b/arch/arm/mach-ep93xx/crunch-bits.S
> @@ -62,7 +62,7 @@
>   * r9  = ret_from_exception
>   * lr  = undefined instr exit
>   *
> - * called from prefetch exception handler with interrupts disabled
> + * called from prefetch exception handler with interrupts enabled
>   */
>  ENTRY(crunch_task_enable)
>         inc_preempt_count r10, r3
> diff --git a/arch/arm/vfp/entry.S b/arch/arm/vfp/entry.S
> index f0759e70fb86..fe6ca574d093 100644
> --- a/arch/arm/vfp/entry.S
> +++ b/arch/arm/vfp/entry.S
> @@ -22,11 +22,10 @@
>  @  r9  = normal "successful" return address
>  @  r10 = this threads thread_info structure
>  @  lr  = unrecognised instruction return address
> -@  IRQs disabled.
> +@  IRQs enabled.
>  @
>  ENTRY(do_vfp)
>         inc_preempt_count r10, r4
> -       enable_irq
>         ldr     r4, .LCvfp
>         ldr     r11, [r10, #TI_CPU]     @ CPU number
>         add     r10, r10, #TI_VFPSTATE  @ r10 = workspace
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel



More information about the linux-arm-kernel mailing list