diff options
author | Kees Cook <keescook@chromium.org> | 2015-04-14 18:48:07 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-14 19:49:05 -0400 |
commit | d1fd836dcf00d2028c700c7e44d2c23404062c90 (patch) | |
tree | f31f4ef7362328899d906258ec7a003a98579b91 | |
parent | c6f5b001e65cdac592b65a08c5d2dd179cfba568 (diff) |
mm: split ET_DYN ASLR from mmap ASLR
This fixes the "offset2lib" weakness in ASLR for arm, arm64, mips,
powerpc, and x86. The problem is that if there is a leak of ASLR from
the executable (ET_DYN), it means a leak of shared library offset as
well (mmap), and vice versa. Further details and a PoC of this attack
is available here:
http://cybersecurity.upv.es/attacks/offset2lib/offset2lib.html
With this patch, a PIE linked executable (ET_DYN) has its own ASLR
region:
$ ./show_mmaps_pie
54859ccd6000-54859ccd7000 r-xp ... /tmp/show_mmaps_pie
54859ced6000-54859ced7000 r--p ... /tmp/show_mmaps_pie
54859ced7000-54859ced8000 rw-p ... /tmp/show_mmaps_pie
7f75be764000-7f75be91f000 r-xp ... /lib/x86_64-linux-gnu/libc.so.6
7f75be91f000-7f75beb1f000 ---p ... /lib/x86_64-linux-gnu/libc.so.6
7f75beb1f000-7f75beb23000 r--p ... /lib/x86_64-linux-gnu/libc.so.6
7f75beb23000-7f75beb25000 rw-p ... /lib/x86_64-linux-gnu/libc.so.6
7f75beb25000-7f75beb2a000 rw-p ...
7f75beb2a000-7f75beb4d000 r-xp ... /lib64/ld-linux-x86-64.so.2
7f75bed45000-7f75bed46000 rw-p ...
7f75bed46000-7f75bed47000 r-xp ...
7f75bed47000-7f75bed4c000 rw-p ...
7f75bed4c000-7f75bed4d000 r--p ... /lib64/ld-linux-x86-64.so.2
7f75bed4d000-7f75bed4e000 rw-p ... /lib64/ld-linux-x86-64.so.2
7f75bed4e000-7f75bed4f000 rw-p ...
7fffb3741000-7fffb3762000 rw-p ... [stack]
7fffb377b000-7fffb377d000 r--p ... [vvar]
7fffb377d000-7fffb377f000 r-xp ... [vdso]
The change is to add a call the newly created arch_mmap_rnd() into the
ELF loader for handling ET_DYN ASLR in a separate region from mmap ASLR,
as was already done on s390. Removes CONFIG_BINFMT_ELF_RANDOMIZE_PIE,
which is no longer needed.
Signed-off-by: Kees Cook <keescook@chromium.org>
Reported-by: Hector Marco-Gisbert <hecmargi@upv.es>
Cc: Russell King <linux@arm.linux.org.uk>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: "David A. Long" <dave.long@linaro.org>
Cc: Andrey Ryabinin <a.ryabinin@samsung.com>
Cc: Arun Chandran <achandran@mvista.com>
Cc: Yann Droneaud <ydroneaud@opteya.com>
Cc: Min-Hua Chen <orca.chen@gmail.com>
Cc: Paul Burton <paul.burton@imgtec.com>
Cc: Alex Smith <alex@alex-smith.me.uk>
Cc: Markos Chandras <markos.chandras@imgtec.com>
Cc: Vineeth Vijayan <vvijayan@mvista.com>
Cc: Jeff Bailey <jeffbailey@google.com>
Cc: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Cc: Ben Hutchings <ben@decadent.org.uk>
Cc: Behan Webster <behanw@converseincode.com>
Cc: Ismael Ripoll <iripoll@upv.es>
Cc: Jan-Simon Mller <dl9pf@gmx.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | arch/arm/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm64/Kconfig | 1 | ||||
-rw-r--r-- | arch/mips/Kconfig | 1 | ||||
-rw-r--r-- | arch/powerpc/Kconfig | 1 | ||||
-rw-r--r-- | arch/s390/include/asm/elf.h | 5 | ||||
-rw-r--r-- | arch/s390/mm/mmap.c | 8 | ||||
-rw-r--r-- | arch/x86/Kconfig | 1 | ||||
-rw-r--r-- | fs/Kconfig.binfmt | 3 | ||||
-rw-r--r-- | fs/binfmt_elf.c | 18 |
9 files changed, 6 insertions, 33 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index f85200a63a8b..4b62f4caf0ce 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -1,7 +1,6 @@ | |||
1 | config ARM | 1 | config ARM |
2 | bool | 2 | bool |
3 | default y | 3 | default y |
4 | select ARCH_BINFMT_ELF_RANDOMIZE_PIE | ||
5 | select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE | 4 | select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE |
6 | select ARCH_HAS_ELF_RANDOMIZE | 5 | select ARCH_HAS_ELF_RANDOMIZE |
7 | select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST | 6 | select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST |
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 7c1dbeb73e8d..34f487d5d84e 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig | |||
@@ -1,6 +1,5 @@ | |||
1 | config ARM64 | 1 | config ARM64 |
2 | def_bool y | 2 | def_bool y |
3 | select ARCH_BINFMT_ELF_RANDOMIZE_PIE | ||
4 | select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE | 3 | select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE |
5 | select ARCH_HAS_ELF_RANDOMIZE | 4 | select ARCH_HAS_ELF_RANDOMIZE |
6 | select ARCH_HAS_GCOV_PROFILE_ALL | 5 | select ARCH_HAS_GCOV_PROFILE_ALL |
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 688ce274f59d..a326c4cb8cf0 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
@@ -23,7 +23,6 @@ config MIPS | |||
23 | select HAVE_KRETPROBES | 23 | select HAVE_KRETPROBES |
24 | select HAVE_DEBUG_KMEMLEAK | 24 | select HAVE_DEBUG_KMEMLEAK |
25 | select HAVE_SYSCALL_TRACEPOINTS | 25 | select HAVE_SYSCALL_TRACEPOINTS |
26 | select ARCH_BINFMT_ELF_RANDOMIZE_PIE | ||
27 | select ARCH_HAS_ELF_RANDOMIZE | 26 | select ARCH_HAS_ELF_RANDOMIZE |
28 | select HAVE_ARCH_TRANSPARENT_HUGEPAGE if CPU_SUPPORTS_HUGEPAGES && 64BIT | 27 | select HAVE_ARCH_TRANSPARENT_HUGEPAGE if CPU_SUPPORTS_HUGEPAGES && 64BIT |
29 | select RTC_LIB if !MACH_LOONGSON | 28 | select RTC_LIB if !MACH_LOONGSON |
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index fc5fffbb331b..e99014adf017 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -88,7 +88,6 @@ config PPC | |||
88 | select ARCH_MIGHT_HAVE_PC_PARPORT | 88 | select ARCH_MIGHT_HAVE_PC_PARPORT |
89 | select ARCH_MIGHT_HAVE_PC_SERIO | 89 | select ARCH_MIGHT_HAVE_PC_SERIO |
90 | select BINFMT_ELF | 90 | select BINFMT_ELF |
91 | select ARCH_BINFMT_ELF_RANDOMIZE_PIE | ||
92 | select ARCH_HAS_ELF_RANDOMIZE | 91 | select ARCH_HAS_ELF_RANDOMIZE |
93 | select OF | 92 | select OF |
94 | select OF_EARLY_FLATTREE | 93 | select OF_EARLY_FLATTREE |
diff --git a/arch/s390/include/asm/elf.h b/arch/s390/include/asm/elf.h index f8db4781a4c2..ff662155b2c4 100644 --- a/arch/s390/include/asm/elf.h +++ b/arch/s390/include/asm/elf.h | |||
@@ -163,10 +163,9 @@ extern unsigned int vdso_enabled; | |||
163 | the loader. We need to make sure that it is out of the way of the program | 163 | the loader. We need to make sure that it is out of the way of the program |
164 | that it will "exec", and that there is sufficient room for the brk. 64-bit | 164 | that it will "exec", and that there is sufficient room for the brk. 64-bit |
165 | tasks are aligned to 4GB. */ | 165 | tasks are aligned to 4GB. */ |
166 | extern unsigned long randomize_et_dyn(void); | 166 | #define ELF_ET_DYN_BASE (is_32bit_task() ? \ |
167 | #define ELF_ET_DYN_BASE (randomize_et_dyn() + (is_32bit_task() ? \ | ||
168 | (STACK_TOP / 3 * 2) : \ | 167 | (STACK_TOP / 3 * 2) : \ |
169 | (STACK_TOP / 3 * 2) & ~((1UL << 32) - 1))) | 168 | (STACK_TOP / 3 * 2) & ~((1UL << 32) - 1)) |
170 | 169 | ||
171 | /* This yields a mask that user programs can use to figure out what | 170 | /* This yields a mask that user programs can use to figure out what |
172 | instruction set this CPU supports. */ | 171 | instruction set this CPU supports. */ |
diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c index 8c11536f972d..bb3367c5cb0b 100644 --- a/arch/s390/mm/mmap.c +++ b/arch/s390/mm/mmap.c | |||
@@ -177,14 +177,6 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, | |||
177 | return addr; | 177 | return addr; |
178 | } | 178 | } |
179 | 179 | ||
180 | unsigned long randomize_et_dyn(void) | ||
181 | { | ||
182 | if (current->flags & PF_RANDOMIZE) | ||
183 | return arch_mmap_rnd(); | ||
184 | |||
185 | return 0UL; | ||
186 | } | ||
187 | |||
188 | #ifndef CONFIG_64BIT | 180 | #ifndef CONFIG_64BIT |
189 | 181 | ||
190 | /* | 182 | /* |
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 782ddbbc1c9a..1f7f185934a5 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -87,7 +87,6 @@ config X86 | |||
87 | select HAVE_ARCH_KMEMCHECK | 87 | select HAVE_ARCH_KMEMCHECK |
88 | select HAVE_ARCH_KASAN if X86_64 && SPARSEMEM_VMEMMAP | 88 | select HAVE_ARCH_KASAN if X86_64 && SPARSEMEM_VMEMMAP |
89 | select HAVE_USER_RETURN_NOTIFIER | 89 | select HAVE_USER_RETURN_NOTIFIER |
90 | select ARCH_BINFMT_ELF_RANDOMIZE_PIE | ||
91 | select ARCH_HAS_ELF_RANDOMIZE | 90 | select ARCH_HAS_ELF_RANDOMIZE |
92 | select HAVE_ARCH_JUMP_LABEL | 91 | select HAVE_ARCH_JUMP_LABEL |
93 | select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE | 92 | select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE |
diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt index 270c48148f79..2d0cbbd14cfc 100644 --- a/fs/Kconfig.binfmt +++ b/fs/Kconfig.binfmt | |||
@@ -27,9 +27,6 @@ config COMPAT_BINFMT_ELF | |||
27 | bool | 27 | bool |
28 | depends on COMPAT && BINFMT_ELF | 28 | depends on COMPAT && BINFMT_ELF |
29 | 29 | ||
30 | config ARCH_BINFMT_ELF_RANDOMIZE_PIE | ||
31 | bool | ||
32 | |||
33 | config ARCH_BINFMT_ELF_STATE | 30 | config ARCH_BINFMT_ELF_STATE |
34 | bool | 31 | bool |
35 | 32 | ||
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index d925f55e4857..b20c05477e90 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/security.h> | 31 | #include <linux/security.h> |
32 | #include <linux/random.h> | 32 | #include <linux/random.h> |
33 | #include <linux/elf.h> | 33 | #include <linux/elf.h> |
34 | #include <linux/elf-randomize.h> | ||
34 | #include <linux/utsname.h> | 35 | #include <linux/utsname.h> |
35 | #include <linux/coredump.h> | 36 | #include <linux/coredump.h> |
36 | #include <linux/sched.h> | 37 | #include <linux/sched.h> |
@@ -910,21 +911,10 @@ static int load_elf_binary(struct linux_binprm *bprm) | |||
910 | * default mmap base, as well as whatever program they | 911 | * default mmap base, as well as whatever program they |
911 | * might try to exec. This is because the brk will | 912 | * might try to exec. This is because the brk will |
912 | * follow the loader, and is not movable. */ | 913 | * follow the loader, and is not movable. */ |
913 | #ifdef CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE | 914 | load_bias = ELF_ET_DYN_BASE - vaddr; |
914 | /* Memory randomization might have been switched off | ||
915 | * in runtime via sysctl or explicit setting of | ||
916 | * personality flags. | ||
917 | * If that is the case, retain the original non-zero | ||
918 | * load_bias value in order to establish proper | ||
919 | * non-randomized mappings. | ||
920 | */ | ||
921 | if (current->flags & PF_RANDOMIZE) | 915 | if (current->flags & PF_RANDOMIZE) |
922 | load_bias = 0; | 916 | load_bias += arch_mmap_rnd(); |
923 | else | 917 | load_bias = ELF_PAGESTART(load_bias); |
924 | load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr); | ||
925 | #else | ||
926 | load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr); | ||
927 | #endif | ||
928 | total_size = total_mapping_size(elf_phdata, | 918 | total_size = total_mapping_size(elf_phdata, |
929 | loc->elf_ex.e_phnum); | 919 | loc->elf_ex.e_phnum); |
930 | if (!total_size) { | 920 | if (!total_size) { |