diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2013-07-04 06:40:32 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2013-07-31 16:31:36 -0400 |
commit | 19accfd373847ac3d10623c5d20f948846299741 (patch) | |
tree | 682dd44ea1710afbb7e61a24185ffa4c9a0fb0da /arch/arm/kernel | |
parent | 5b43e7a383d69381ffe53423e46dd0fafae07da3 (diff) |
ARM: move vector stubs
Move the machine vector stubs into the page above the vector page,
which we can prevent from being visible to userspace. Also move
the reset stub, and place the swi vector at a location that the
'ldr' can get to it.
This hides pointers into the kernel which could give valuable
information to attackers, and reduces the number of exploitable
instructions at a fixed address.
Cc: <stable@vger.kernel.org>
Acked-by: Nicolas Pitre <nico@linaro.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/entry-armv.S | 50 | ||||
-rw-r--r-- | arch/arm/kernel/traps.c | 4 |
2 files changed, 26 insertions, 28 deletions
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 02437345289a..79a41fa978f5 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S | |||
@@ -944,9 +944,9 @@ __kuser_helper_end: | |||
944 | /* | 944 | /* |
945 | * Vector stubs. | 945 | * Vector stubs. |
946 | * | 946 | * |
947 | * This code is copied to 0xffff0200 so we can use branches in the | 947 | * This code is copied to 0xffff1000 so we can use branches in the |
948 | * vectors, rather than ldr's. Note that this code must not | 948 | * vectors, rather than ldr's. Note that this code must not exceed |
949 | * exceed 0x300 bytes. | 949 | * a page size. |
950 | * | 950 | * |
951 | * Common stub entry macro: | 951 | * Common stub entry macro: |
952 | * Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC | 952 | * Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC |
@@ -995,6 +995,15 @@ ENDPROC(vector_\name) | |||
995 | 995 | ||
996 | .globl __stubs_start | 996 | .globl __stubs_start |
997 | __stubs_start: | 997 | __stubs_start: |
998 | @ This must be the first word | ||
999 | .word vector_swi | ||
1000 | |||
1001 | vector_rst: | ||
1002 | ARM( swi SYS_ERROR0 ) | ||
1003 | THUMB( svc #0 ) | ||
1004 | THUMB( nop ) | ||
1005 | b vector_und | ||
1006 | |||
998 | /* | 1007 | /* |
999 | * Interrupt dispatcher | 1008 | * Interrupt dispatcher |
1000 | */ | 1009 | */ |
@@ -1089,6 +1098,16 @@ __stubs_start: | |||
1089 | .align 5 | 1098 | .align 5 |
1090 | 1099 | ||
1091 | /*============================================================================= | 1100 | /*============================================================================= |
1101 | * Address exception handler | ||
1102 | *----------------------------------------------------------------------------- | ||
1103 | * These aren't too critical. | ||
1104 | * (they're not supposed to happen, and won't happen in 32-bit data mode). | ||
1105 | */ | ||
1106 | |||
1107 | vector_addrexcptn: | ||
1108 | b vector_addrexcptn | ||
1109 | |||
1110 | /*============================================================================= | ||
1092 | * Undefined FIQs | 1111 | * Undefined FIQs |
1093 | *----------------------------------------------------------------------------- | 1112 | *----------------------------------------------------------------------------- |
1094 | * Enter in FIQ mode, spsr = ANY CPSR, lr = ANY PC | 1113 | * Enter in FIQ mode, spsr = ANY CPSR, lr = ANY PC |
@@ -1101,35 +1120,14 @@ __stubs_start: | |||
1101 | vector_fiq: | 1120 | vector_fiq: |
1102 | subs pc, lr, #4 | 1121 | subs pc, lr, #4 |
1103 | 1122 | ||
1104 | /*============================================================================= | ||
1105 | * Address exception handler | ||
1106 | *----------------------------------------------------------------------------- | ||
1107 | * These aren't too critical. | ||
1108 | * (they're not supposed to happen, and won't happen in 32-bit data mode). | ||
1109 | */ | ||
1110 | |||
1111 | vector_addrexcptn: | ||
1112 | b vector_addrexcptn | ||
1113 | |||
1114 | /* | ||
1115 | * We group all the following data together to optimise | ||
1116 | * for CPUs with separate I & D caches. | ||
1117 | */ | ||
1118 | .align 5 | ||
1119 | |||
1120 | .LCvswi: | ||
1121 | .word vector_swi | ||
1122 | |||
1123 | .globl __stubs_end | 1123 | .globl __stubs_end |
1124 | __stubs_end: | 1124 | __stubs_end: |
1125 | 1125 | ||
1126 | .equ stubs_offset, __vectors_start + 0x200 - __stubs_start | 1126 | .equ stubs_offset, __vectors_start + 0x1000 - __stubs_start |
1127 | 1127 | ||
1128 | .globl __vectors_start | 1128 | .globl __vectors_start |
1129 | __vectors_start: | 1129 | __vectors_start: |
1130 | ARM( swi SYS_ERROR0 ) | 1130 | W(b) vector_rst + stubs_offset |
1131 | THUMB( svc #0 ) | ||
1132 | THUMB( nop ) | ||
1133 | W(b) vector_und + stubs_offset | 1131 | W(b) vector_und + stubs_offset |
1134 | W(ldr) pc, .LCvswi + stubs_offset | 1132 | W(ldr) pc, .LCvswi + stubs_offset |
1135 | W(b) vector_pabt + stubs_offset | 1133 | W(b) vector_pabt + stubs_offset |
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 9433e8a12b5e..2c8c7fa78b8c 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
@@ -837,7 +837,7 @@ void __init early_trap_init(void *vectors_base) | |||
837 | * are visible to the instruction stream. | 837 | * are visible to the instruction stream. |
838 | */ | 838 | */ |
839 | memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start); | 839 | memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start); |
840 | memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start); | 840 | memcpy((void *)vectors + 0x1000, __stubs_start, __stubs_end - __stubs_start); |
841 | memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz); | 841 | memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz); |
842 | 842 | ||
843 | /* | 843 | /* |
@@ -852,7 +852,7 @@ void __init early_trap_init(void *vectors_base) | |||
852 | memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE), | 852 | memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE), |
853 | sigreturn_codes, sizeof(sigreturn_codes)); | 853 | sigreturn_codes, sizeof(sigreturn_codes)); |
854 | 854 | ||
855 | flush_icache_range(vectors, vectors + PAGE_SIZE); | 855 | flush_icache_range(vectors, vectors + PAGE_SIZE * 2); |
856 | modify_domain(DOMAIN_USER, DOMAIN_CLIENT); | 856 | modify_domain(DOMAIN_USER, DOMAIN_CLIENT); |
857 | #else /* ifndef CONFIG_CPU_V7M */ | 857 | #else /* ifndef CONFIG_CPU_V7M */ |
858 | /* | 858 | /* |