From: Ard Biesheuvel
maillist inclusion
commit ccb456783dd71f474e5783a81d7f18c2cd4dda81
category: feature
feature: ARM kaslr support
issue: #I3ZXZF
CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/ardb/linux.git/commit/?h=arm-kaslr-latest&id=ccb456783dd71f474e5783a81d7f18c2cd4dda81
-------------------------------------------------
To avoid having to relocate the contents of extable entries at
runtime when running with KASLR enabled, wire up the existing
support for emitting them as relative references. This ensures
these quantities are invariant under runtime relocation.
Cc: Russell King
Signed-off-by: Ard Biesheuvel
Signed-off-by: Cui GaoSheng
Reviewed-by: Xiu Jianfeng
Signed-off-by: Chen Jun
Signed-off-by: Yu Changchun
---
arch/arm/include/asm/Kbuild | 1 -
arch/arm/include/asm/assembler.h | 16 +++------
arch/arm/include/asm/extable.h | 47 +++++++++++++++++++++++++++
arch/arm/include/asm/futex.h | 6 ++--
arch/arm/include/asm/uaccess.h | 17 +++-------
arch/arm/include/asm/word-at-a-time.h | 6 ++--
arch/arm/kernel/entry-armv.S | 9 +++--
arch/arm/kernel/swp_emulate.c | 8 ++---
arch/arm/lib/backtrace.S | 13 +++-----
arch/arm/lib/getuser.S | 24 +++++++-------
arch/arm/lib/putuser.S | 15 ++++-----
arch/arm/mm/alignment.c | 24 +++++---------
arch/arm/mm/extable.c | 2 +-
arch/arm/nwfpe/entry.S | 6 ++--
scripts/sorttable.c | 2 +-
15 files changed, 102 insertions(+), 94 deletions(-)
create mode 100644 arch/arm/include/asm/extable.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index f1398b9267c0..e243acbd850f 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -1,6 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
generic-y += early_ioremap.h
-generic-y += extable.h
generic-y += flat.h
generic-y += parport.h
generic-y += seccomp.h
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 6ed30421f697..b6d5c0d83674 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -18,6 +18,7 @@
#endif
#include
+#include
#include
#include
#include
@@ -242,10 +243,7 @@
#define USERL(l, x...) \
9999: x; \
- .pushsection __ex_table,"a"; \
- .align 3; \
- .long 9999b,l; \
- .popsection
+ ex_entry 9999b,l;
#define USER(x...) USERL(9001f, x)
@@ -379,10 +377,7 @@ THUMB( orr \reg , \reg , #PSR_T_BIT )
.error "Unsupported inc macro argument"
.endif
- .pushsection __ex_table,"a"
- .align 3
- .long 9999b, \abort
- .popsection
+ ex_entry 9999b, \abort
.endm
.macro usracc, instr, reg, ptr, inc, cond, rept, abort
@@ -420,10 +415,7 @@ THUMB( orr \reg , \reg , #PSR_T_BIT )
.error "Unsupported inc macro argument"
.endif
- .pushsection __ex_table,"a"
- .align 3
- .long 9999b, \abort
- .popsection
+ ex_entry 9999b, \abort
.endr
.endm
diff --git a/arch/arm/include/asm/extable.h b/arch/arm/include/asm/extable.h
new file mode 100644
index 000000000000..175d42247b96
--- /dev/null
+++ b/arch/arm/include/asm/extable.h
@@ -0,0 +1,47 @@
+#ifndef __ASM_EXTABLE_H
+#define __ASM_EXTABLE_H
+
+#ifndef __ASSEMBLY__
+
+/*
+ * The exception table consists of pairs of relative offsets: the first
+ * is the relative offset to an instruction that is allowed to fault,
+ * and the second is the relative offset at which the program should
+ * continue. No registers are modified, so it is entirely up to the
+ * continuation code to figure out what to do.
+ */
+
+struct exception_table_entry {
+ int insn, fixup;
+};
+
+#define ARCH_HAS_RELATIVE_EXTABLE
+
+extern int fixup_exception(struct pt_regs *regs);
+
+ /*
+ * ex_entry - place-relative extable entry
+ */
+asm( ".macro ex_entry, insn, fixup \n"
+ ".pushsection __ex_table, \"a\", %progbits \n"
+ ".align 3 \n"
+ ".long \\insn - . \n"
+ ".long \\fixup - . \n"
+ ".popsection \n"
+ ".endm \n");
+
+#else
+
+ /*
+ * ex_entry - place-relative extable entry
+ */
+ .macro ex_entry, insn, fixup
+ .pushsection __ex_table, "a", %progbits
+ .align 3
+ .long \insn - .
+ .long \fixup - .
+ .popsection
+ .endm
+
+#endif
+#endif
diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h
index a9151884bc85..6921c58c6c7c 100644
--- a/arch/arm/include/asm/futex.h
+++ b/arch/arm/include/asm/futex.h
@@ -10,10 +10,8 @@
#define __futex_atomic_ex_table(err_reg) \
"3:\n" \
- " .pushsection __ex_table,\"a\"\n" \
- " .align 3\n" \
- " .long 1b, 4f, 2b, 4f\n" \
- " .popsection\n" \
+ " ex_entry 1b, 4f\n" \
+ " ex_entry 2b, 4f\n" \
" .pushsection .text.fixup,\"ax\"\n" \
" .align 2\n" \
"4: mov %0, " err_reg "\n" \
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
index a13d90206472..476d1a15e669 100644
--- a/arch/arm/include/asm/uaccess.h
+++ b/arch/arm/include/asm/uaccess.h
@@ -340,10 +340,7 @@ do { \
" mov %1, #0\n" \
" b 2b\n" \
" .popsection\n" \
- " .pushsection __ex_table,\"a\"\n" \
- " .align 3\n" \
- " .long 1b, 3b\n" \
- " .popsection" \
+ " ex_entry 1b, 3b\n" \
: "+r" (err), "=&r" (x) \
: "r" (addr), "i" (-EFAULT) \
: "cc")
@@ -442,10 +439,7 @@ do { \
"3: mov %0, %3\n" \
" b 2b\n" \
" .popsection\n" \
- " .pushsection __ex_table,\"a\"\n" \
- " .align 3\n" \
- " .long 1b, 3b\n" \
- " .popsection" \
+ " ex_entry 1b, 3b\n" \
: "+r" (err) \
: "r" (x), "r" (__pu_addr), "i" (-EFAULT) \
: "cc")
@@ -501,11 +495,8 @@ do { \
"4: mov %0, %3\n" \
" b 3b\n" \
" .popsection\n" \
- " .pushsection __ex_table,\"a\"\n" \
- " .align 3\n" \
- " .long 1b, 4b\n" \
- " .long 2b, 4b\n" \
- " .popsection" \
+ " ex_entry 1b, 4b\n" \
+ " ex_entry 2b, 4b\n" \
: "+r" (err), "+r" (__pu_addr) \
: "r" (x), "i" (-EFAULT) \
: "cc")
diff --git a/arch/arm/include/asm/word-at-a-time.h b/arch/arm/include/asm/word-at-a-time.h
index 352ab213520d..a440ec1cd85b 100644
--- a/arch/arm/include/asm/word-at-a-time.h
+++ b/arch/arm/include/asm/word-at-a-time.h
@@ -9,6 +9,7 @@
* Heavily based on the x86 algorithm.
*/
#include
+#include
struct word_at_a_time {
const unsigned long one_bits, high_bits;
@@ -85,10 +86,7 @@ static inline unsigned long load_unaligned_zeropad(const void *addr)
#endif
" b 2b\n"
" .popsection\n"
- " .pushsection __ex_table,\"a\"\n"
- " .align 3\n"
- " .long 1b, 3b\n"
- " .popsection"
+ " ex_entry 1b, 3b\n"
: "=&r" (ret), "=&r" (offset)
: "r" (addr), "Qo" (*(unsigned long *)addr));
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 0ea8529a4872..c9af7e2338eb 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -15,6 +15,7 @@
#include
#include
+#include
#include
#include
#include
@@ -535,13 +536,11 @@ ENDPROC(__und_usr)
4: str r4, [sp, #S_PC] @ retry current instruction
ret r9
.popsection
- .pushsection __ex_table,"a"
- .long 1b, 4b
+ ex_entry 1b, 4b
#if CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7
- .long 2b, 4b
- .long 3b, 4b
+ ex_entry 2b, 4b
+ ex_entry 3b, 4b
#endif
- .popsection
/*
* Check whether the instruction is a co-processor instruction.
diff --git a/arch/arm/kernel/swp_emulate.c b/arch/arm/kernel/swp_emulate.c
index 6166ba38bf99..f80230610753 100644
--- a/arch/arm/kernel/swp_emulate.c
+++ b/arch/arm/kernel/swp_emulate.c
@@ -24,6 +24,7 @@
#include
#include
+#include
#include
#include
#include
@@ -45,11 +46,8 @@
"3: mov %0, %5\n" \
" b 2b\n" \
" .previous\n" \
- " .section __ex_table,\"a\"\n" \
- " .align 3\n" \
- " .long 0b, 3b\n" \
- " .long 1b, 3b\n" \
- " .previous" \
+ " ex_entry 0b, 3b\n" \
+ " ex_entry 1b, 3b\n" \
: "=&r" (res), "+r" (data), "=&r" (temp) \
: "r" (addr), "i" (-EAGAIN), "i" (-EFAULT) \
: "cc", "memory")
diff --git a/arch/arm/lib/backtrace.S b/arch/arm/lib/backtrace.S
index 872f658638d9..baccd30cf23f 100644
--- a/arch/arm/lib/backtrace.S
+++ b/arch/arm/lib/backtrace.S
@@ -106,14 +106,11 @@ for_each_frame: tst frame, mask @ Check for address exceptions
bl printk
no_frame: ldmfd sp!, {r4 - r9, pc}
ENDPROC(c_backtrace)
-
- .pushsection __ex_table,"a"
- .align 3
- .long 1001b, 1006b
- .long 1002b, 1006b
- .long 1003b, 1006b
- .long 1004b, 1006b
- .popsection
+
+ ex_entry 1001b, 1006b
+ ex_entry 1002b, 1006b
+ ex_entry 1003b, 1006b
+ ex_entry 1004b, 1006b
.Lbad: .asciz "%sBacktrace aborted due to bad frame pointer <%p>\n"
.align
diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S
index c5e420750c48..d120e0223a8c 100644
--- a/arch/arm/lib/getuser.S
+++ b/arch/arm/lib/getuser.S
@@ -27,6 +27,7 @@
#include
#include
#include
+#include
#include
ENTRY(__get_user_1)
@@ -149,19 +150,18 @@ _ASM_NOKPROBE(__get_user_bad)
_ASM_NOKPROBE(__get_user_bad8)
.pushsection __ex_table, "a"
- .long 1b, __get_user_bad
- .long 2b, __get_user_bad
+ ex_entry 1b, __get_user_bad
+ ex_entry 2b, __get_user_bad
#if __LINUX_ARM_ARCH__ < 6
- .long 3b, __get_user_bad
+ ex_entry 3b, __get_user_bad
#endif
- .long 4b, __get_user_bad
- .long 5b, __get_user_bad8
- .long 6b, __get_user_bad8
+ ex_entry 4b, __get_user_bad
+ ex_entry 5b, __get_user_bad8
+ ex_entry 6b, __get_user_bad8
#ifdef __ARMEB__
- .long 7b, __get_user_bad
- .long 8b, __get_user_bad8
- .long 9b, __get_user_bad8
- .long 10b, __get_user_bad8
- .long 11b, __get_user_bad8
+ ex_entry 7b, __get_user_bad
+ ex_entry 8b, __get_user_bad8
+ ex_entry 9b, __get_user_bad8
+ ex_entry 10b, __get_user_bad8
+ ex_entry 11b, __get_user_bad8
#endif
-.popsection
diff --git a/arch/arm/lib/putuser.S b/arch/arm/lib/putuser.S
index bdd8836dc5c2..1bb85192ba60 100644
--- a/arch/arm/lib/putuser.S
+++ b/arch/arm/lib/putuser.S
@@ -27,6 +27,7 @@
#include
#include
#include
+#include
#include
ENTRY(__put_user_1)
@@ -83,13 +84,11 @@ __put_user_bad:
ret lr
ENDPROC(__put_user_bad)
-.pushsection __ex_table, "a"
- .long 1b, __put_user_bad
- .long 2b, __put_user_bad
+ ex_entry 1b, __put_user_bad
+ ex_entry 2b, __put_user_bad
#if __LINUX_ARM_ARCH__ < 6
- .long 3b, __put_user_bad
+ ex_entry 3b, __put_user_bad
#endif
- .long 4b, __put_user_bad
- .long 5b, __put_user_bad
- .long 6b, __put_user_bad
-.popsection
+ ex_entry 4b, __put_user_bad
+ ex_entry 5b, __put_user_bad
+ ex_entry 6b, __put_user_bad
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index ea81e89e7740..f26a748fe041 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -21,6 +21,7 @@
#include
#include
+#include
#include
#include
#include
@@ -204,10 +205,7 @@ union offset_union {
"3: mov %0, #1\n" \
" b 2b\n" \
" .popsection\n" \
- " .pushsection __ex_table,\"a\"\n" \
- " .align 3\n" \
- " .long 1b, 3b\n" \
- " .popsection\n" \
+ " ex_entry 1b, 3b\n" \
: "=r" (err), "=&r" (val), "=r" (addr) \
: "0" (err), "2" (addr))
@@ -264,11 +262,8 @@ union offset_union {
"4: mov %0, #1\n" \
" b 3b\n" \
" .popsection\n" \
- " .pushsection __ex_table,\"a\"\n" \
- " .align 3\n" \
- " .long 1b, 4b\n" \
- " .long 2b, 4b\n" \
- " .popsection\n" \
+ " ex_entry 1b, 4b\n" \
+ " ex_entry 2b, 4b\n" \
: "=r" (err), "=&r" (v), "=&r" (a) \
: "0" (err), "1" (v), "2" (a)); \
if (err) \
@@ -304,13 +299,10 @@ union offset_union {
"6: mov %0, #1\n" \
" b 5b\n" \
" .popsection\n" \
- " .pushsection __ex_table,\"a\"\n" \
- " .align 3\n" \
- " .long 1b, 6b\n" \
- " .long 2b, 6b\n" \
- " .long 3b, 6b\n" \
- " .long 4b, 6b\n" \
- " .popsection\n" \
+ " ex_entry 1b, 6b\n" \
+ " ex_entry 2b, 6b\n" \
+ " ex_entry 3b, 6b\n" \
+ " ex_entry 4b, 6b\n" \
: "=r" (err), "=&r" (v), "=&r" (a) \
: "0" (err), "1" (v), "2" (a)); \
if (err) \
diff --git a/arch/arm/mm/extable.c b/arch/arm/mm/extable.c
index fc33564597b8..46c4a8a7f5da 100644
--- a/arch/arm/mm/extable.c
+++ b/arch/arm/mm/extable.c
@@ -11,7 +11,7 @@ int fixup_exception(struct pt_regs *regs)
fixup = search_exception_tables(instruction_pointer(regs));
if (fixup) {
- regs->ARM_pc = fixup->fixup;
+ regs->ARM_pc = (unsigned long)&fixup->fixup + fixup->fixup;
#ifdef CONFIG_THUMB2_KERNEL
/* Clear the IT state to avoid nasty surprises in the fixup */
regs->ARM_cpsr &= ~PSR_IT_MASK;
diff --git a/arch/arm/nwfpe/entry.S b/arch/arm/nwfpe/entry.S
index d8f9915566e1..7816b3df00aa 100644
--- a/arch/arm/nwfpe/entry.S
+++ b/arch/arm/nwfpe/entry.S
@@ -8,6 +8,7 @@
*/
#include
+#include
#include
/* This is the kernel's entry point into the floating point emulator.
@@ -107,7 +108,4 @@ next:
.Lfix: ret r9 @ let the user eat segfaults
.popsection
- .pushsection __ex_table,"a"
- .align 3
- .long .Lx1, .Lfix
- .popsection
+ ex_entry .Lx1, .Lfix
diff --git a/scripts/sorttable.c b/scripts/sorttable.c
index 0ef3abfc4a51..ac93e033b7cb 100644
--- a/scripts/sorttable.c
+++ b/scripts/sorttable.c
@@ -341,12 +341,12 @@ static int do_file(char const *const fname, void *addr)
case EM_AARCH64:
case EM_PARISC:
case EM_PPC:
+ case EM_ARM:
case EM_PPC64:
custom_sort = sort_relative_table;
break;
case EM_ARCOMPACT:
case EM_ARCV2:
- case EM_ARM:
case EM_MICROBLAZE:
case EM_MIPS:
case EM_XTENSA:
--
2.22.0