aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2015-08-20 05:32:02 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2015-08-26 15:27:02 -0400
commit2190fed67ba6f3e8129513929f2395843645e928 (patch)
tree45a4db5061c12e2926f7a1c89d56c7bbf47f0e61
parentaa06e5c1f9c2b466712be904cc5b56a813e24cfd (diff)
ARM: entry: provide uaccess assembly macro hooks
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>
-rw-r--r--arch/arm/include/asm/assembler.h17
-rw-r--r--arch/arm/kernel/entry-armv.S30
-rw-r--r--arch/arm/kernel/entry-common.S2
-rw-r--r--arch/arm/kernel/entry-header.S3
-rw-r--r--arch/arm/mm/abort-ev4.S1
-rw-r--r--arch/arm/mm/abort-ev5t.S1
-rw-r--r--arch/arm/mm/abort-ev5tj.S1
-rw-r--r--arch/arm/mm/abort-ev6.S7
-rw-r--r--arch/arm/mm/abort-ev7.S1
-rw-r--r--arch/arm/mm/abort-lv4t.S2
-rw-r--r--arch/arm/mm/abort-macro.S1
11 files changed, 55 insertions, 11 deletions
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 4abe57279c66..a91177043467 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -445,6 +445,23 @@ THUMB( orr \reg , \reg , #PSR_T_BIT )
445#endif 445#endif
446 .endm 446 .endm
447 447
448 .macro uaccess_disable, tmp, isb=1
449 .endm
450
451 .macro uaccess_enable, tmp, isb=1
452 .endm
453
454 .macro uaccess_save, tmp
455 .endm
456
457 .macro uaccess_restore
458 .endm
459
460 .macro uaccess_save_and_disable, tmp
461 uaccess_save \tmp
462 uaccess_disable \tmp
463 .endm
464
448 .irp c,,eq,ne,cs,cc,mi,pl,vs,vc,hi,ls,ge,lt,gt,le,hs,lo 465 .irp c,,eq,ne,cs,cc,mi,pl,vs,vc,hi,ls,ge,lt,gt,le,hs,lo
449 .macro ret\c, reg 466 .macro ret\c, reg
450#if __LINUX_ARM_ARCH__ < 6 467#if __LINUX_ARM_ARCH__ < 6
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index d19adcf6c580..61f00a3f3047 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -149,10 +149,10 @@ ENDPROC(__und_invalid)
149#define SPFIX(code...) 149#define SPFIX(code...)
150#endif 150#endif
151 151
152 .macro svc_entry, stack_hole=0, trace=1 152 .macro svc_entry, stack_hole=0, trace=1, uaccess=1
153 UNWIND(.fnstart ) 153 UNWIND(.fnstart )
154 UNWIND(.save {r0 - pc} ) 154 UNWIND(.save {r0 - pc} )
155 sub sp, sp, #(S_FRAME_SIZE + \stack_hole - 4) 155 sub sp, sp, #(S_FRAME_SIZE + 8 + \stack_hole - 4)
156#ifdef CONFIG_THUMB2_KERNEL 156#ifdef CONFIG_THUMB2_KERNEL
157 SPFIX( str r0, [sp] ) @ temporarily saved 157 SPFIX( str r0, [sp] ) @ temporarily saved
158 SPFIX( mov r0, sp ) 158 SPFIX( mov r0, sp )
@@ -167,7 +167,7 @@ ENDPROC(__und_invalid)
167 ldmia r0, {r3 - r5} 167 ldmia r0, {r3 - r5}
168 add r7, sp, #S_SP - 4 @ here for interlock avoidance 168 add r7, sp, #S_SP - 4 @ here for interlock avoidance
169 mov r6, #-1 @ "" "" "" "" 169 mov r6, #-1 @ "" "" "" ""
170 add r2, sp, #(S_FRAME_SIZE + \stack_hole - 4) 170 add r2, sp, #(S_FRAME_SIZE + 8 + \stack_hole - 4)
171 SPFIX( addeq r2, r2, #4 ) 171 SPFIX( addeq r2, r2, #4 )
172 str r3, [sp, #-4]! @ save the "real" r0 copied 172 str r3, [sp, #-4]! @ save the "real" r0 copied
173 @ from the exception stack 173 @ from the exception stack
@@ -185,6 +185,11 @@ ENDPROC(__und_invalid)
185 @ 185 @
186 stmia r7, {r2 - r6} 186 stmia r7, {r2 - r6}
187 187
188 uaccess_save r0
189 .if \uaccess
190 uaccess_disable r0
191 .endif
192
188 .if \trace 193 .if \trace
189#ifdef CONFIG_TRACE_IRQFLAGS 194#ifdef CONFIG_TRACE_IRQFLAGS
190 bl trace_hardirqs_off 195 bl trace_hardirqs_off
@@ -194,7 +199,7 @@ ENDPROC(__und_invalid)
194 199
195 .align 5 200 .align 5
196__dabt_svc: 201__dabt_svc:
197 svc_entry 202 svc_entry uaccess=0
198 mov r2, sp 203 mov r2, sp
199 dabt_helper 204 dabt_helper
200 THUMB( ldr r5, [sp, #S_PSR] ) @ potentially updated CPSR 205 THUMB( ldr r5, [sp, #S_PSR] ) @ potentially updated CPSR
@@ -368,7 +373,7 @@ ENDPROC(__fiq_abt)
368#error "sizeof(struct pt_regs) must be a multiple of 8" 373#error "sizeof(struct pt_regs) must be a multiple of 8"
369#endif 374#endif
370 375
371 .macro usr_entry, trace=1 376 .macro usr_entry, trace=1, uaccess=1
372 UNWIND(.fnstart ) 377 UNWIND(.fnstart )
373 UNWIND(.cantunwind ) @ don't unwind the user space 378 UNWIND(.cantunwind ) @ don't unwind the user space
374 sub sp, sp, #S_FRAME_SIZE 379 sub sp, sp, #S_FRAME_SIZE
@@ -400,6 +405,10 @@ ENDPROC(__fiq_abt)
400 ARM( stmdb r0, {sp, lr}^ ) 405 ARM( stmdb r0, {sp, lr}^ )
401 THUMB( store_user_sp_lr r0, r1, S_SP - S_PC ) 406 THUMB( store_user_sp_lr r0, r1, S_SP - S_PC )
402 407
408 .if \uaccess
409 uaccess_disable ip
410 .endif
411
403 @ Enable the alignment trap while in kernel mode 412 @ Enable the alignment trap while in kernel mode
404 ATRAP( teq r8, r7) 413 ATRAP( teq r8, r7)
405 ATRAP( mcrne p15, 0, r8, c1, c0, 0) 414 ATRAP( mcrne p15, 0, r8, c1, c0, 0)
@@ -435,7 +444,7 @@ ENDPROC(__fiq_abt)
435 444
436 .align 5 445 .align 5
437__dabt_usr: 446__dabt_usr:
438 usr_entry 447 usr_entry uaccess=0
439 kuser_cmpxchg_check 448 kuser_cmpxchg_check
440 mov r2, sp 449 mov r2, sp
441 dabt_helper 450 dabt_helper
@@ -458,7 +467,7 @@ ENDPROC(__irq_usr)
458 467
459 .align 5 468 .align 5
460__und_usr: 469__und_usr:
461 usr_entry 470 usr_entry uaccess=0
462 471
463 mov r2, r4 472 mov r2, r4
464 mov r3, r5 473 mov r3, r5
@@ -484,6 +493,8 @@ __und_usr:
4841: ldrt r0, [r4] 4931: ldrt r0, [r4]
485 ARM_BE8(rev r0, r0) @ little endian instruction 494 ARM_BE8(rev r0, r0) @ little endian instruction
486 495
496 uaccess_disable ip
497
487 @ r0 = 32-bit ARM instruction which caused the exception 498 @ r0 = 32-bit ARM instruction which caused the exception
488 @ r2 = PC value for the following instruction (:= regs->ARM_pc) 499 @ r2 = PC value for the following instruction (:= regs->ARM_pc)
489 @ r4 = PC value for the faulting instruction 500 @ r4 = PC value for the faulting instruction
@@ -518,9 +529,10 @@ __und_usr_thumb:
5182: ldrht r5, [r4] 5292: ldrht r5, [r4]
519ARM_BE8(rev16 r5, r5) @ little endian instruction 530ARM_BE8(rev16 r5, r5) @ little endian instruction
520 cmp r5, #0xe800 @ 32bit instruction if xx != 0 531 cmp r5, #0xe800 @ 32bit instruction if xx != 0
521 blo __und_usr_fault_16 @ 16bit undefined instruction 532 blo __und_usr_fault_16_pan @ 16bit undefined instruction
5223: ldrht r0, [r2] 5333: ldrht r0, [r2]
523ARM_BE8(rev16 r0, r0) @ little endian instruction 534ARM_BE8(rev16 r0, r0) @ little endian instruction
535 uaccess_disable ip
524 add r2, r2, #2 @ r2 is PC + 2, make it PC + 4 536 add r2, r2, #2 @ r2 is PC + 2, make it PC + 4
525 str r2, [sp, #S_PC] @ it's a 2x16bit instr, update 537 str r2, [sp, #S_PC] @ it's a 2x16bit instr, update
526 orr r0, r0, r5, lsl #16 538 orr r0, r0, r5, lsl #16
@@ -715,6 +727,8 @@ ENDPROC(no_fp)
715__und_usr_fault_32: 727__und_usr_fault_32:
716 mov r1, #4 728 mov r1, #4
717 b 1f 729 b 1f
730__und_usr_fault_16_pan:
731 uaccess_disable ip
718__und_usr_fault_16: 732__und_usr_fault_16:
719 mov r1, #2 733 mov r1, #2
7201: mov r0, sp 7341: mov r0, sp
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 92828a1dec80..189154980703 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -173,6 +173,8 @@ ENTRY(vector_swi)
173 USER( ldr scno, [lr, #-4] ) @ get SWI instruction 173 USER( ldr scno, [lr, #-4] ) @ get SWI instruction
174#endif 174#endif
175 175
176 uaccess_disable tbl
177
176 adr tbl, sys_call_table @ load syscall table pointer 178 adr tbl, sys_call_table @ load syscall table pointer
177 179
178#if defined(CONFIG_OABI_COMPAT) 180#if defined(CONFIG_OABI_COMPAT)
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index d47b5161b029..0d22ad206d52 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -215,6 +215,7 @@
215 blne trace_hardirqs_off 215 blne trace_hardirqs_off
216#endif 216#endif
217 .endif 217 .endif
218 uaccess_restore
218 219
219#ifndef CONFIG_THUMB2_KERNEL 220#ifndef CONFIG_THUMB2_KERNEL
220 @ ARM mode SVC restore 221 @ ARM mode SVC restore
@@ -258,6 +259,7 @@
258 @ on the stack remains correct). 259 @ on the stack remains correct).
259 @ 260 @
260 .macro svc_exit_via_fiq 261 .macro svc_exit_via_fiq
262 uaccess_restore
261#ifndef CONFIG_THUMB2_KERNEL 263#ifndef CONFIG_THUMB2_KERNEL
262 @ ARM mode restore 264 @ ARM mode restore
263 mov r0, sp 265 mov r0, sp
@@ -287,6 +289,7 @@
287 289
288 290
289 .macro restore_user_regs, fast = 0, offset = 0 291 .macro restore_user_regs, fast = 0, offset = 0
292 uaccess_enable r1, isb=0
290#ifndef CONFIG_THUMB2_KERNEL 293#ifndef CONFIG_THUMB2_KERNEL
291 @ ARM mode restore 294 @ ARM mode restore
292 mov r2, sp 295 mov r2, sp
diff --git a/arch/arm/mm/abort-ev4.S b/arch/arm/mm/abort-ev4.S
index 54473cd4aba9..b3b31e30cadd 100644
--- a/arch/arm/mm/abort-ev4.S
+++ b/arch/arm/mm/abort-ev4.S
@@ -19,6 +19,7 @@ ENTRY(v4_early_abort)
19 mrc p15, 0, r1, c5, c0, 0 @ get FSR 19 mrc p15, 0, r1, c5, c0, 0 @ get FSR
20 mrc p15, 0, r0, c6, c0, 0 @ get FAR 20 mrc p15, 0, r0, c6, c0, 0 @ get FAR
21 ldr r3, [r4] @ read aborted ARM instruction 21 ldr r3, [r4] @ read aborted ARM instruction
22 uaccess_disable ip @ disable userspace access
22 bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR 23 bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
23 tst r3, #1 << 20 @ L = 1 -> write? 24 tst r3, #1 << 20 @ L = 1 -> write?
24 orreq r1, r1, #1 << 11 @ yes. 25 orreq r1, r1, #1 << 11 @ yes.
diff --git a/arch/arm/mm/abort-ev5t.S b/arch/arm/mm/abort-ev5t.S
index c913031b79cc..a6a381a6caa5 100644
--- a/arch/arm/mm/abort-ev5t.S
+++ b/arch/arm/mm/abort-ev5t.S
@@ -21,6 +21,7 @@ ENTRY(v5t_early_abort)
21 mrc p15, 0, r0, c6, c0, 0 @ get FAR 21 mrc p15, 0, r0, c6, c0, 0 @ get FAR
22 do_thumb_abort fsr=r1, pc=r4, psr=r5, tmp=r3 22 do_thumb_abort fsr=r1, pc=r4, psr=r5, tmp=r3
23 ldreq r3, [r4] @ read aborted ARM instruction 23 ldreq r3, [r4] @ read aborted ARM instruction
24 uaccess_disable ip @ disable user access
24 bic r1, r1, #1 << 11 @ clear bits 11 of FSR 25 bic r1, r1, #1 << 11 @ clear bits 11 of FSR
25 teq_ldrd tmp=ip, insn=r3 @ insn was LDRD? 26 teq_ldrd tmp=ip, insn=r3 @ insn was LDRD?
26 beq do_DataAbort @ yes 27 beq do_DataAbort @ yes
diff --git a/arch/arm/mm/abort-ev5tj.S b/arch/arm/mm/abort-ev5tj.S
index 1b80d71adb0f..00ab011bef58 100644
--- a/arch/arm/mm/abort-ev5tj.S
+++ b/arch/arm/mm/abort-ev5tj.S
@@ -24,6 +24,7 @@ ENTRY(v5tj_early_abort)
24 bne do_DataAbort 24 bne do_DataAbort
25 do_thumb_abort fsr=r1, pc=r4, psr=r5, tmp=r3 25 do_thumb_abort fsr=r1, pc=r4, psr=r5, tmp=r3
26 ldreq r3, [r4] @ read aborted ARM instruction 26 ldreq r3, [r4] @ read aborted ARM instruction
27 uaccess_disable ip @ disable userspace access
27 teq_ldrd tmp=ip, insn=r3 @ insn was LDRD? 28 teq_ldrd tmp=ip, insn=r3 @ insn was LDRD?
28 beq do_DataAbort @ yes 29 beq do_DataAbort @ yes
29 tst r3, #1 << 20 @ L = 0 -> write 30 tst r3, #1 << 20 @ L = 0 -> write
diff --git a/arch/arm/mm/abort-ev6.S b/arch/arm/mm/abort-ev6.S
index 113704f30e9f..8801a15aa105 100644
--- a/arch/arm/mm/abort-ev6.S
+++ b/arch/arm/mm/abort-ev6.S
@@ -26,17 +26,18 @@ ENTRY(v6_early_abort)
26 ldr ip, =0x4107b36 26 ldr ip, =0x4107b36
27 mrc p15, 0, r3, c0, c0, 0 @ get processor id 27 mrc p15, 0, r3, c0, c0, 0 @ get processor id
28 teq ip, r3, lsr #4 @ r0 ARM1136? 28 teq ip, r3, lsr #4 @ r0 ARM1136?
29 bne do_DataAbort 29 bne 1f
30 tst r5, #PSR_J_BIT @ Java? 30 tst r5, #PSR_J_BIT @ Java?
31 tsteq r5, #PSR_T_BIT @ Thumb? 31 tsteq r5, #PSR_T_BIT @ Thumb?
32 bne do_DataAbort 32 bne 1f
33 bic r1, r1, #1 << 11 @ clear bit 11 of FSR 33 bic r1, r1, #1 << 11 @ clear bit 11 of FSR
34 ldr r3, [r4] @ read aborted ARM instruction 34 ldr r3, [r4] @ read aborted ARM instruction
35 ARM_BE8(rev r3, r3) 35 ARM_BE8(rev r3, r3)
36 36
37 teq_ldrd tmp=ip, insn=r3 @ insn was LDRD? 37 teq_ldrd tmp=ip, insn=r3 @ insn was LDRD?
38 beq do_DataAbort @ yes 38 beq 1f @ yes
39 tst r3, #1 << 20 @ L = 0 -> write 39 tst r3, #1 << 20 @ L = 0 -> write
40 orreq r1, r1, #1 << 11 @ yes. 40 orreq r1, r1, #1 << 11 @ yes.
41#endif 41#endif
421: uaccess_disable ip @ disable userspace access
42 b do_DataAbort 43 b do_DataAbort
diff --git a/arch/arm/mm/abort-ev7.S b/arch/arm/mm/abort-ev7.S
index 4812ad054214..e8d0e08c227f 100644
--- a/arch/arm/mm/abort-ev7.S
+++ b/arch/arm/mm/abort-ev7.S
@@ -15,6 +15,7 @@
15ENTRY(v7_early_abort) 15ENTRY(v7_early_abort)
16 mrc p15, 0, r1, c5, c0, 0 @ get FSR 16 mrc p15, 0, r1, c5, c0, 0 @ get FSR
17 mrc p15, 0, r0, c6, c0, 0 @ get FAR 17 mrc p15, 0, r0, c6, c0, 0 @ get FAR
18 uaccess_disable ip @ disable userspace access
18 19
19 /* 20 /*
20 * V6 code adjusts the returned DFSR. 21 * V6 code adjusts the returned DFSR.
diff --git a/arch/arm/mm/abort-lv4t.S b/arch/arm/mm/abort-lv4t.S
index f3982580c273..6d8e8e3365d1 100644
--- a/arch/arm/mm/abort-lv4t.S
+++ b/arch/arm/mm/abort-lv4t.S
@@ -26,6 +26,7 @@ ENTRY(v4t_late_abort)
26#endif 26#endif
27 bne .data_thumb_abort 27 bne .data_thumb_abort
28 ldr r8, [r4] @ read arm instruction 28 ldr r8, [r4] @ read arm instruction
29 uaccess_disable ip @ disable userspace access
29 tst r8, #1 << 20 @ L = 1 -> write? 30 tst r8, #1 << 20 @ L = 1 -> write?
30 orreq r1, r1, #1 << 11 @ yes. 31 orreq r1, r1, #1 << 11 @ yes.
31 and r7, r8, #15 << 24 32 and r7, r8, #15 << 24
@@ -155,6 +156,7 @@ ENTRY(v4t_late_abort)
155 156
156.data_thumb_abort: 157.data_thumb_abort:
157 ldrh r8, [r4] @ read instruction 158 ldrh r8, [r4] @ read instruction
159 uaccess_disable ip @ disable userspace access
158 tst r8, #1 << 11 @ L = 1 -> write? 160 tst r8, #1 << 11 @ L = 1 -> write?
159 orreq r1, r1, #1 << 8 @ yes 161 orreq r1, r1, #1 << 8 @ yes
160 and r7, r8, #15 << 12 162 and r7, r8, #15 << 12
diff --git a/arch/arm/mm/abort-macro.S b/arch/arm/mm/abort-macro.S
index 50d6c0a900b1..4509bee4e081 100644
--- a/arch/arm/mm/abort-macro.S
+++ b/arch/arm/mm/abort-macro.S
@@ -13,6 +13,7 @@
13 tst \psr, #PSR_T_BIT 13 tst \psr, #PSR_T_BIT
14 beq not_thumb 14 beq not_thumb
15 ldrh \tmp, [\pc] @ Read aborted Thumb instruction 15 ldrh \tmp, [\pc] @ Read aborted Thumb instruction
16 uaccess_disable ip @ disable userspace access
16 and \tmp, \tmp, # 0xfe00 @ Mask opcode field 17 and \tmp, \tmp, # 0xfe00 @ Mask opcode field
17 cmp \tmp, # 0x5600 @ Is it ldrsb? 18 cmp \tmp, # 0x5600 @ Is it ldrsb?
18 orreq \tmp, \tmp, #1 << 11 @ Set L-bit if yes 19 orreq \tmp, \tmp, #1 << 11 @ Set L-bit if yes