aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArd Biesheuvel <ard.biesheuvel@linaro.org>2016-01-01 09:02:12 -0500
committerCatalin Marinas <catalin.marinas@arm.com>2016-02-24 09:57:26 -0500
commit6c94f27ac847ff8ef15b3da5b200574923bd6287 (patch)
treee7a5384289c44b3d10a0ffb92dd7fb912998cfa6
parenta272858a3c1ecd4a935ba23c66668f81214bd110 (diff)
arm64: switch to relative exception tables
Instead of using absolute addresses for both the exception location and the fixup, use offsets relative to the exception table entry values. Not only does this cut the size of the exception table in half, it is also a prerequisite for KASLR, since absolute exception table entries are subject to dynamic relocation, which is incompatible with the sorting of the exception table that occurs at build time. This patch also introduces the _ASM_EXTABLE preprocessor macro (which exists on x86 as well) and its _asm_extable assembly counterpart, as shorthands to emit exception table entries. Acked-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
-rw-r--r--arch/arm64/include/asm/alternative.h19
-rw-r--r--arch/arm64/include/asm/assembler.h15
-rw-r--r--arch/arm64/include/asm/futex.h12
-rw-r--r--arch/arm64/include/asm/uaccess.h30
-rw-r--r--arch/arm64/include/asm/word-at-a-time.h7
-rw-r--r--arch/arm64/kernel/armv8_deprecated.c7
-rw-r--r--arch/arm64/mm/extable.c2
-rw-r--r--scripts/sortextable.c2
8 files changed, 43 insertions, 51 deletions
diff --git a/arch/arm64/include/asm/alternative.h b/arch/arm64/include/asm/alternative.h
index a9fc24ec1aa9..beccbdefa106 100644
--- a/arch/arm64/include/asm/alternative.h
+++ b/arch/arm64/include/asm/alternative.h
@@ -157,11 +157,8 @@ void apply_alternatives(void *start, size_t length);
157 add \addr, \addr, \post_inc; 157 add \addr, \addr, \post_inc;
158 alternative_endif 158 alternative_endif
159 159
160 .section __ex_table,"a"; 160 _asm_extable 8888b,\l;
161 .align 3; 161 _asm_extable 8889b,\l;
162 .quad 8888b,\l;
163 .quad 8889b,\l;
164 .previous;
165 .endm 162 .endm
166 163
167 .macro uao_stp l, reg1, reg2, addr, post_inc 164 .macro uao_stp l, reg1, reg2, addr, post_inc
@@ -175,11 +172,8 @@ void apply_alternatives(void *start, size_t length);
175 add \addr, \addr, \post_inc; 172 add \addr, \addr, \post_inc;
176 alternative_endif 173 alternative_endif
177 174
178 .section __ex_table,"a"; 175 _asm_extable 8888b,\l;
179 .align 3; 176 _asm_extable 8889b,\l;
180 .quad 8888b,\l;
181 .quad 8889b,\l;
182 .previous
183 .endm 177 .endm
184 178
185 .macro uao_user_alternative l, inst, alt_inst, reg, addr, post_inc 179 .macro uao_user_alternative l, inst, alt_inst, reg, addr, post_inc
@@ -191,10 +185,7 @@ void apply_alternatives(void *start, size_t length);
191 add \addr, \addr, \post_inc; 185 add \addr, \addr, \post_inc;
192 alternative_endif 186 alternative_endif
193 187
194 .section __ex_table,"a"; 188 _asm_extable 8888b,\l;
195 .align 3;
196 .quad 8888b,\l;
197 .previous
198 .endm 189 .endm
199#else 190#else
200 .macro uao_ldp l, reg1, reg2, addr, post_inc 191 .macro uao_ldp l, reg1, reg2, addr, post_inc
diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index ba5aff6c830e..70f7b9e04598 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -94,12 +94,19 @@
94 dmb \opt 94 dmb \opt
95 .endm 95 .endm
96 96
97/*
98 * Emit an entry into the exception table
99 */
100 .macro _asm_extable, from, to
101 .pushsection __ex_table, "a"
102 .align 3
103 .long (\from - .), (\to - .)
104 .popsection
105 .endm
106
97#define USER(l, x...) \ 107#define USER(l, x...) \
989999: x; \ 1089999: x; \
99 .section __ex_table,"a"; \ 109 _asm_extable 9999b, l
100 .align 3; \
101 .quad 9999b,l; \
102 .previous
103 110
104/* 111/*
105 * Register aliases. 112 * Register aliases.
diff --git a/arch/arm64/include/asm/futex.h b/arch/arm64/include/asm/futex.h
index 5f3ab8c1db55..f2585cdd32c2 100644
--- a/arch/arm64/include/asm/futex.h
+++ b/arch/arm64/include/asm/futex.h
@@ -42,10 +42,8 @@
42"4: mov %w0, %w5\n" \ 42"4: mov %w0, %w5\n" \
43" b 3b\n" \ 43" b 3b\n" \
44" .popsection\n" \ 44" .popsection\n" \
45" .pushsection __ex_table,\"a\"\n" \ 45 _ASM_EXTABLE(1b, 4b) \
46" .align 3\n" \ 46 _ASM_EXTABLE(2b, 4b) \
47" .quad 1b, 4b, 2b, 4b\n" \
48" .popsection\n" \
49 ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, \ 47 ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, \
50 CONFIG_ARM64_PAN) \ 48 CONFIG_ARM64_PAN) \
51 : "=&r" (ret), "=&r" (oldval), "+Q" (*uaddr), "=&r" (tmp) \ 49 : "=&r" (ret), "=&r" (oldval), "+Q" (*uaddr), "=&r" (tmp) \
@@ -134,10 +132,8 @@ ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN, CONFIG_ARM64_PAN)
134"4: mov %w0, %w6\n" 132"4: mov %w0, %w6\n"
135" b 3b\n" 133" b 3b\n"
136" .popsection\n" 134" .popsection\n"
137" .pushsection __ex_table,\"a\"\n" 135 _ASM_EXTABLE(1b, 4b)
138" .align 3\n" 136 _ASM_EXTABLE(2b, 4b)
139" .quad 1b, 4b, 2b, 4b\n"
140" .popsection\n"
141ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, CONFIG_ARM64_PAN) 137ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, CONFIG_ARM64_PAN)
142 : "+r" (ret), "=&r" (val), "+Q" (*uaddr), "=&r" (tmp) 138 : "+r" (ret), "=&r" (val), "+Q" (*uaddr), "=&r" (tmp)
143 : "r" (oldval), "r" (newval), "Ir" (-EFAULT) 139 : "r" (oldval), "r" (newval), "Ir" (-EFAULT)
diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
index 16ba0d5c9740..0685d74572af 100644
--- a/arch/arm64/include/asm/uaccess.h
+++ b/arch/arm64/include/asm/uaccess.h
@@ -36,11 +36,11 @@
36#define VERIFY_WRITE 1 36#define VERIFY_WRITE 1
37 37
38/* 38/*
39 * The exception table consists of pairs of addresses: the first is the 39 * The exception table consists of pairs of relative offsets: the first
40 * address of an instruction that is allowed to fault, and the second is 40 * is the relative offset to an instruction that is allowed to fault,
41 * the address at which the program should continue. No registers are 41 * and the second is the relative offset at which the program should
42 * modified, so it is entirely up to the continuation code to figure out 42 * continue. No registers are modified, so it is entirely up to the
43 * what to do. 43 * continuation code to figure out what to do.
44 * 44 *
45 * All the routines below use bits of fixup code that are out of line 45 * All the routines below use bits of fixup code that are out of line
46 * with the main instruction path. This means when everything is well, 46 * with the main instruction path. This means when everything is well,
@@ -50,9 +50,11 @@
50 50
51struct exception_table_entry 51struct exception_table_entry
52{ 52{
53 unsigned long insn, fixup; 53 int insn, fixup;
54}; 54};
55 55
56#define ARCH_HAS_RELATIVE_EXTABLE
57
56extern int fixup_exception(struct pt_regs *regs); 58extern int fixup_exception(struct pt_regs *regs);
57 59
58#define KERNEL_DS (-1UL) 60#define KERNEL_DS (-1UL)
@@ -115,6 +117,12 @@ static inline void set_fs(mm_segment_t fs)
115#define access_ok(type, addr, size) __range_ok(addr, size) 117#define access_ok(type, addr, size) __range_ok(addr, size)
116#define user_addr_max get_fs 118#define user_addr_max get_fs
117 119
120#define _ASM_EXTABLE(from, to) \
121 " .pushsection __ex_table, \"a\"\n" \
122 " .align 3\n" \
123 " .long (" #from " - .), (" #to " - .)\n" \
124 " .popsection\n"
125
118/* 126/*
119 * The "__xxx" versions of the user access functions do not verify the address 127 * The "__xxx" versions of the user access functions do not verify the address
120 * space - it must have been done previously with a separate "access_ok()" 128 * space - it must have been done previously with a separate "access_ok()"
@@ -134,10 +142,7 @@ static inline void set_fs(mm_segment_t fs)
134 " mov %1, #0\n" \ 142 " mov %1, #0\n" \
135 " b 2b\n" \ 143 " b 2b\n" \
136 " .previous\n" \ 144 " .previous\n" \
137 " .section __ex_table,\"a\"\n" \ 145 _ASM_EXTABLE(1b, 3b) \
138 " .align 3\n" \
139 " .quad 1b, 3b\n" \
140 " .previous" \
141 : "+r" (err), "=&r" (x) \ 146 : "+r" (err), "=&r" (x) \
142 : "r" (addr), "i" (-EFAULT)) 147 : "r" (addr), "i" (-EFAULT))
143 148
@@ -206,10 +211,7 @@ do { \
206 "3: mov %w0, %3\n" \ 211 "3: mov %w0, %3\n" \
207 " b 2b\n" \ 212 " b 2b\n" \
208 " .previous\n" \ 213 " .previous\n" \
209 " .section __ex_table,\"a\"\n" \ 214 _ASM_EXTABLE(1b, 3b) \
210 " .align 3\n" \
211 " .quad 1b, 3b\n" \
212 " .previous" \
213 : "+r" (err) \ 215 : "+r" (err) \
214 : "r" (x), "r" (addr), "i" (-EFAULT)) 216 : "r" (x), "r" (addr), "i" (-EFAULT))
215 217
diff --git a/arch/arm64/include/asm/word-at-a-time.h b/arch/arm64/include/asm/word-at-a-time.h
index aab5bf09e9d9..2b79b8a89457 100644
--- a/arch/arm64/include/asm/word-at-a-time.h
+++ b/arch/arm64/include/asm/word-at-a-time.h
@@ -16,6 +16,8 @@
16#ifndef __ASM_WORD_AT_A_TIME_H 16#ifndef __ASM_WORD_AT_A_TIME_H
17#define __ASM_WORD_AT_A_TIME_H 17#define __ASM_WORD_AT_A_TIME_H
18 18
19#include <asm/uaccess.h>
20
19#ifndef __AARCH64EB__ 21#ifndef __AARCH64EB__
20 22
21#include <linux/kernel.h> 23#include <linux/kernel.h>
@@ -81,10 +83,7 @@ static inline unsigned long load_unaligned_zeropad(const void *addr)
81#endif 83#endif
82 " b 2b\n" 84 " b 2b\n"
83 " .popsection\n" 85 " .popsection\n"
84 " .pushsection __ex_table,\"a\"\n" 86 _ASM_EXTABLE(1b, 3b)
85 " .align 3\n"
86 " .quad 1b, 3b\n"
87 " .popsection"
88 : "=&r" (ret), "=&r" (offset) 87 : "=&r" (ret), "=&r" (offset)
89 : "r" (addr), "Q" (*(unsigned long *)addr)); 88 : "r" (addr), "Q" (*(unsigned long *)addr));
90 89
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
index 3e01207917b1..c37202c0c838 100644
--- a/arch/arm64/kernel/armv8_deprecated.c
+++ b/arch/arm64/kernel/armv8_deprecated.c
@@ -297,11 +297,8 @@ static void __init register_insn_emulation_sysctl(struct ctl_table *table)
297 "4: mov %w0, %w5\n" \ 297 "4: mov %w0, %w5\n" \
298 " b 3b\n" \ 298 " b 3b\n" \
299 " .popsection" \ 299 " .popsection" \
300 " .pushsection __ex_table,\"a\"\n" \ 300 _ASM_EXTABLE(0b, 4b) \
301 " .align 3\n" \ 301 _ASM_EXTABLE(1b, 4b) \
302 " .quad 0b, 4b\n" \
303 " .quad 1b, 4b\n" \
304 " .popsection\n" \
305 ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, \ 302 ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, \
306 CONFIG_ARM64_PAN) \ 303 CONFIG_ARM64_PAN) \
307 : "=&r" (res), "+r" (data), "=&r" (temp) \ 304 : "=&r" (res), "+r" (data), "=&r" (temp) \
diff --git a/arch/arm64/mm/extable.c b/arch/arm64/mm/extable.c
index 79444279ba8c..81acd4706878 100644
--- a/arch/arm64/mm/extable.c
+++ b/arch/arm64/mm/extable.c
@@ -11,7 +11,7 @@ int fixup_exception(struct pt_regs *regs)
11 11
12 fixup = search_exception_tables(instruction_pointer(regs)); 12 fixup = search_exception_tables(instruction_pointer(regs));
13 if (fixup) 13 if (fixup)
14 regs->pc = fixup->fixup; 14 regs->pc = (unsigned long)&fixup->fixup + fixup->fixup;
15 15
16 return fixup != NULL; 16 return fixup != NULL;
17} 17}
diff --git a/scripts/sortextable.c b/scripts/sortextable.c
index ecefa0a634f8..19d83647846c 100644
--- a/scripts/sortextable.c
+++ b/scripts/sortextable.c
@@ -282,12 +282,12 @@ do_file(char const *const fname)
282 case EM_386: 282 case EM_386:
283 case EM_X86_64: 283 case EM_X86_64:
284 case EM_S390: 284 case EM_S390:
285 case EM_AARCH64:
285 custom_sort = sort_relative_table; 286 custom_sort = sort_relative_table;
286 break; 287 break;
287 case EM_ARCOMPACT: 288 case EM_ARCOMPACT:
288 case EM_ARCV2: 289 case EM_ARCV2:
289 case EM_ARM: 290 case EM_ARM:
290 case EM_AARCH64:
291 case EM_MICROBLAZE: 291 case EM_MICROBLAZE:
292 case EM_MIPS: 292 case EM_MIPS:
293 case EM_XTENSA: 293 case EM_XTENSA: