ARM: entry: provide uaccess assembly macro hooks
authorRussell King <rmk+kernel@arm.linux.org.uk>
Thu, 20 Aug 2015 09:32:02 +0000 (10:32 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Wed, 26 Aug 2015 19:27:02 +0000 (20:27 +0100)
Provide hooks into the kernel entry and exit paths to permit control
of userspace visibility to the kernel.  The intended use is:

- on entry to kernel from user, uaccess_disable will be called to
  disable userspace visibility
- on exit from kernel to user, uaccess_enable will be called to
  enable userspace visibility
- on entry from a kernel exception, uaccess_save_and_disable will be
  called to save the current userspace visibility setting, and disable
  access
- on exit from a kernel exception, uaccess_restore will be called to
  restore the userspace visibility as it was before the exception
  occurred.

These hooks allows us to keep userspace visibility disabled for the
vast majority of the kernel, except for localised regions where we
want to explicitly access userspace.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/include/asm/assembler.h
arch/arm/kernel/entry-armv.S
arch/arm/kernel/entry-common.S
arch/arm/kernel/entry-header.S
arch/arm/mm/abort-ev4.S
arch/arm/mm/abort-ev5t.S
arch/arm/mm/abort-ev5tj.S
arch/arm/mm/abort-ev6.S
arch/arm/mm/abort-ev7.S
arch/arm/mm/abort-lv4t.S
arch/arm/mm/abort-macro.S

index 4abe57279c66f0ecf2c96c116ae7ce839e646b4c..a9117704346739b21cc0241d7952ab302e1f8eb9 100644 (file)
@@ -445,6 +445,23 @@ THUMB(     orr     \reg , \reg , #PSR_T_BIT        )
 #endif
        .endm
 
+       .macro  uaccess_disable, tmp, isb=1
+       .endm
+
+       .macro  uaccess_enable, tmp, isb=1
+       .endm
+
+       .macro  uaccess_save, tmp
+       .endm
+
+       .macro  uaccess_restore
+       .endm
+
+       .macro  uaccess_save_and_disable, tmp
+       uaccess_save \tmp
+       uaccess_disable \tmp
+       .endm
+
        .irp    c,,eq,ne,cs,cc,mi,pl,vs,vc,hi,ls,ge,lt,gt,le,hs,lo
        .macro  ret\c, reg
 #if __LINUX_ARM_ARCH__ < 6
index d19adcf6c580c4d1f7be7a909896490cca534e30..61f00a3f3047659fec0512f2a8d2328189f01a31 100644 (file)
@@ -149,10 +149,10 @@ ENDPROC(__und_invalid)
 #define SPFIX(code...)
 #endif
 
-       .macro  svc_entry, stack_hole=0, trace=1
+       .macro  svc_entry, stack_hole=0, trace=1, uaccess=1
  UNWIND(.fnstart               )
  UNWIND(.save {r0 - pc}                )
-       sub     sp, sp, #(S_FRAME_SIZE + \stack_hole - 4)
+       sub     sp, sp, #(S_FRAME_SIZE + 8 + \stack_hole - 4)
 #ifdef CONFIG_THUMB2_KERNEL
  SPFIX(        str     r0, [sp]        )       @ temporarily saved
  SPFIX(        mov     r0, sp          )
@@ -167,7 +167,7 @@ ENDPROC(__und_invalid)
        ldmia   r0, {r3 - r5}
        add     r7, sp, #S_SP - 4       @ here for interlock avoidance
        mov     r6, #-1                 @  ""  ""      ""       ""
-       add     r2, sp, #(S_FRAME_SIZE + \stack_hole - 4)
+       add     r2, sp, #(S_FRAME_SIZE + 8 + \stack_hole - 4)
  SPFIX(        addeq   r2, r2, #4      )
        str     r3, [sp, #-4]!          @ save the "real" r0 copied
                                        @ from the exception stack
@@ -185,6 +185,11 @@ ENDPROC(__und_invalid)
        @
        stmia   r7, {r2 - r6}
 
+       uaccess_save r0
+       .if \uaccess
+       uaccess_disable r0
+       .endif
+
        .if \trace
 #ifdef CONFIG_TRACE_IRQFLAGS
        bl      trace_hardirqs_off
@@ -194,7 +199,7 @@ ENDPROC(__und_invalid)
 
        .align  5
 __dabt_svc:
-       svc_entry
+       svc_entry uaccess=0
        mov     r2, sp
        dabt_helper
  THUMB(        ldr     r5, [sp, #S_PSR]        )       @ potentially updated CPSR
@@ -368,7 +373,7 @@ ENDPROC(__fiq_abt)
 #error "sizeof(struct pt_regs) must be a multiple of 8"
 #endif
 
-       .macro  usr_entry, trace=1
+       .macro  usr_entry, trace=1, uaccess=1
  UNWIND(.fnstart       )
  UNWIND(.cantunwind    )       @ don't unwind the user space
        sub     sp, sp, #S_FRAME_SIZE
@@ -400,6 +405,10 @@ ENDPROC(__fiq_abt)
  ARM(  stmdb   r0, {sp, lr}^                   )
  THUMB(        store_user_sp_lr r0, r1, S_SP - S_PC    )
 
+       .if \uaccess
+       uaccess_disable ip
+       .endif
+
        @ Enable the alignment trap while in kernel mode
  ATRAP(        teq     r8, r7)
  ATRAP( mcrne  p15, 0, r8, c1, c0, 0)
@@ -435,7 +444,7 @@ ENDPROC(__fiq_abt)
 
        .align  5
 __dabt_usr:
-       usr_entry
+       usr_entry uaccess=0
        kuser_cmpxchg_check
        mov     r2, sp
        dabt_helper
@@ -458,7 +467,7 @@ ENDPROC(__irq_usr)
 
        .align  5
 __und_usr:
-       usr_entry
+       usr_entry uaccess=0
 
        mov     r2, r4
        mov     r3, r5
@@ -484,6 +493,8 @@ __und_usr:
 1:     ldrt    r0, [r4]
  ARM_BE8(rev   r0, r0)                         @ little endian instruction
 
+       uaccess_disable ip
+
        @ r0 = 32-bit ARM instruction which caused the exception
        @ r2 = PC value for the following instruction (:= regs->ARM_pc)
        @ r4 = PC value for the faulting instruction
@@ -518,9 +529,10 @@ __und_usr_thumb:
 2:     ldrht   r5, [r4]
 ARM_BE8(rev16  r5, r5)                         @ little endian instruction
        cmp     r5, #0xe800                     @ 32bit instruction if xx != 0
-       blo     __und_usr_fault_16              @ 16bit undefined instruction
+       blo     __und_usr_fault_16_pan          @ 16bit undefined instruction
 3:     ldrht   r0, [r2]
 ARM_BE8(rev16  r0, r0)                         @ little endian instruction
+       uaccess_disable ip
        add     r2, r2, #2                      @ r2 is PC + 2, make it PC + 4
        str     r2, [sp, #S_PC]                 @ it's a 2x16bit instr, update
        orr     r0, r0, r5, lsl #16
@@ -715,6 +727,8 @@ ENDPROC(no_fp)
 __und_usr_fault_32:
        mov     r1, #4
        b       1f
+__und_usr_fault_16_pan:
+       uaccess_disable ip
 __und_usr_fault_16:
        mov     r1, #2
 1:     mov     r0, sp
index 92828a1dec80c1c33d051d9b76063727598495d5..1891549807036f934e8118c85a21f4a481ef8bd7 100644 (file)
@@ -173,6 +173,8 @@ ENTRY(vector_swi)
  USER( ldr     scno, [lr, #-4]         )       @ get SWI instruction
 #endif
 
+       uaccess_disable tbl
+
        adr     tbl, sys_call_table             @ load syscall table pointer
 
 #if defined(CONFIG_OABI_COMPAT)
index d47b5161b029e12070888e63032249c44546c28b..0d22ad206d5230ba05a40b4101bb1dd2e4addd10 100644 (file)
        blne    trace_hardirqs_off
 #endif
        .endif
+       uaccess_restore
 
 #ifndef CONFIG_THUMB2_KERNEL
        @ ARM mode SVC restore
        @ on the stack remains correct).
        @
        .macro  svc_exit_via_fiq
+       uaccess_restore
 #ifndef CONFIG_THUMB2_KERNEL
        @ ARM mode restore
        mov     r0, sp
 
 
        .macro  restore_user_regs, fast = 0, offset = 0
+       uaccess_enable r1, isb=0
 #ifndef CONFIG_THUMB2_KERNEL
        @ ARM mode restore
        mov     r2, sp
index 54473cd4aba951c793f25df8f3e9fb17be7f0160..b3b31e30cadd207f98991841b42f60f91d2a8097 100644 (file)
@@ -19,6 +19,7 @@ ENTRY(v4_early_abort)
        mrc     p15, 0, r1, c5, c0, 0           @ get FSR
        mrc     p15, 0, r0, c6, c0, 0           @ get FAR
        ldr     r3, [r4]                        @ read aborted ARM instruction
+       uaccess_disable ip                      @ disable userspace access
        bic     r1, r1, #1 << 11 | 1 << 10      @ clear bits 11 and 10 of FSR
        tst     r3, #1 << 20                    @ L = 1 -> write?
        orreq   r1, r1, #1 << 11                @ yes.
index c913031b79ccba32d12b75d684210c44c5247133..a6a381a6caa5a32f6b4ad018ab10e702b01920cc 100644 (file)
@@ -21,6 +21,7 @@ ENTRY(v5t_early_abort)
        mrc     p15, 0, r0, c6, c0, 0           @ get FAR
        do_thumb_abort fsr=r1, pc=r4, psr=r5, tmp=r3
        ldreq   r3, [r4]                        @ read aborted ARM instruction
+       uaccess_disable ip                      @ disable user access
        bic     r1, r1, #1 << 11                @ clear bits 11 of FSR
        teq_ldrd tmp=ip, insn=r3                @ insn was LDRD?
        beq     do_DataAbort                    @ yes
index 1b80d71adb0ff15283a44c5f51d0480487298196..00ab011bef5848cbcc750d8aa51770cea7ac9934 100644 (file)
@@ -24,6 +24,7 @@ ENTRY(v5tj_early_abort)
        bne     do_DataAbort
        do_thumb_abort fsr=r1, pc=r4, psr=r5, tmp=r3
        ldreq   r3, [r4]                        @ read aborted ARM instruction
+       uaccess_disable ip                      @ disable userspace access
        teq_ldrd tmp=ip, insn=r3                @ insn was LDRD?
        beq     do_DataAbort                    @ yes
        tst     r3, #1 << 20                    @ L = 0 -> write
index 113704f30e9f8825b624b9c01f115464c4b9998a..8801a15aa10595a9288edaeca03ed434d33e86b1 100644 (file)
@@ -26,17 +26,18 @@ ENTRY(v6_early_abort)
        ldr     ip, =0x4107b36
        mrc     p15, 0, r3, c0, c0, 0           @ get processor id
        teq     ip, r3, lsr #4                  @ r0 ARM1136?
-       bne     do_DataAbort
+       bne     1f
        tst     r5, #PSR_J_BIT                  @ Java?
        tsteq   r5, #PSR_T_BIT                  @ Thumb?
-       bne     do_DataAbort
+       bne     1f
        bic     r1, r1, #1 << 11                @ clear bit 11 of FSR
        ldr     r3, [r4]                        @ read aborted ARM instruction
  ARM_BE8(rev   r3, r3)
 
        teq_ldrd tmp=ip, insn=r3                @ insn was LDRD?
-       beq     do_DataAbort                    @ yes
+       beq     1f                              @ yes
        tst     r3, #1 << 20                    @ L = 0 -> write
        orreq   r1, r1, #1 << 11                @ yes.
 #endif
+1:     uaccess_disable ip                      @ disable userspace access
        b       do_DataAbort
index 4812ad054214572ba6e7198247e2c190e469897d..e8d0e08c227fc5f36d864378bf5cf75dfbb00e10 100644 (file)
@@ -15,6 +15,7 @@
 ENTRY(v7_early_abort)
        mrc     p15, 0, r1, c5, c0, 0           @ get FSR
        mrc     p15, 0, r0, c6, c0, 0           @ get FAR
+       uaccess_disable ip                      @ disable userspace access
 
        /*
         * V6 code adjusts the returned DFSR.
index f3982580c273057b89a1c025cb52f0f54093014f..6d8e8e3365d17321f03b37fa67ab04a65b29f4ca 100644 (file)
@@ -26,6 +26,7 @@ ENTRY(v4t_late_abort)
 #endif
        bne     .data_thumb_abort
        ldr     r8, [r4]                        @ read arm instruction
+       uaccess_disable ip                      @ disable userspace access
        tst     r8, #1 << 20                    @ L = 1 -> write?
        orreq   r1, r1, #1 << 11                @ yes.
        and     r7, r8, #15 << 24
@@ -155,6 +156,7 @@ ENTRY(v4t_late_abort)
 
 .data_thumb_abort:
        ldrh    r8, [r4]                        @ read instruction
+       uaccess_disable ip                      @ disable userspace access
        tst     r8, #1 << 11                    @ L = 1 -> write?
        orreq   r1, r1, #1 << 8                 @ yes
        and     r7, r8, #15 << 12
index 50d6c0a900b14d900d40d64a0961ddf15f752e14..4509bee4e081ce78f95bcd99cd890468d97a5d8c 100644 (file)
@@ -13,6 +13,7 @@
        tst     \psr, #PSR_T_BIT
        beq     not_thumb
        ldrh    \tmp, [\pc]                     @ Read aborted Thumb instruction
+       uaccess_disable ip                      @ disable userspace access
        and     \tmp, \tmp, # 0xfe00            @ Mask opcode field
        cmp     \tmp, # 0x5600                  @ Is it ldrsb?
        orreq   \tmp, \tmp, #1 << 11            @ Set L-bit if yes