mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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>
This commit is contained in:
		
							parent
							
								
									c6f5b001e6
								
							
						
					
					
						commit
						d1fd836dcf
					
				
					 9 changed files with 6 additions and 33 deletions
				
			
		| 
						 | 
					@ -1,7 +1,6 @@
 | 
				
			||||||
config ARM
 | 
					config ARM
 | 
				
			||||||
	bool
 | 
						bool
 | 
				
			||||||
	default y
 | 
						default y
 | 
				
			||||||
	select ARCH_BINFMT_ELF_RANDOMIZE_PIE
 | 
					 | 
				
			||||||
	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
 | 
						select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
 | 
				
			||||||
	select ARCH_HAS_ELF_RANDOMIZE
 | 
						select ARCH_HAS_ELF_RANDOMIZE
 | 
				
			||||||
	select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
 | 
						select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,5 @@
 | 
				
			||||||
config ARM64
 | 
					config ARM64
 | 
				
			||||||
	def_bool y
 | 
						def_bool y
 | 
				
			||||||
	select ARCH_BINFMT_ELF_RANDOMIZE_PIE
 | 
					 | 
				
			||||||
	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
 | 
						select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
 | 
				
			||||||
	select ARCH_HAS_ELF_RANDOMIZE
 | 
						select ARCH_HAS_ELF_RANDOMIZE
 | 
				
			||||||
	select ARCH_HAS_GCOV_PROFILE_ALL
 | 
						select ARCH_HAS_GCOV_PROFILE_ALL
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,7 +23,6 @@ config MIPS
 | 
				
			||||||
	select HAVE_KRETPROBES
 | 
						select HAVE_KRETPROBES
 | 
				
			||||||
	select HAVE_DEBUG_KMEMLEAK
 | 
						select HAVE_DEBUG_KMEMLEAK
 | 
				
			||||||
	select HAVE_SYSCALL_TRACEPOINTS
 | 
						select HAVE_SYSCALL_TRACEPOINTS
 | 
				
			||||||
	select ARCH_BINFMT_ELF_RANDOMIZE_PIE
 | 
					 | 
				
			||||||
	select ARCH_HAS_ELF_RANDOMIZE
 | 
						select ARCH_HAS_ELF_RANDOMIZE
 | 
				
			||||||
	select HAVE_ARCH_TRANSPARENT_HUGEPAGE if CPU_SUPPORTS_HUGEPAGES && 64BIT
 | 
						select HAVE_ARCH_TRANSPARENT_HUGEPAGE if CPU_SUPPORTS_HUGEPAGES && 64BIT
 | 
				
			||||||
	select RTC_LIB if !MACH_LOONGSON
 | 
						select RTC_LIB if !MACH_LOONGSON
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -88,7 +88,6 @@ config PPC
 | 
				
			||||||
	select ARCH_MIGHT_HAVE_PC_PARPORT
 | 
						select ARCH_MIGHT_HAVE_PC_PARPORT
 | 
				
			||||||
	select ARCH_MIGHT_HAVE_PC_SERIO
 | 
						select ARCH_MIGHT_HAVE_PC_SERIO
 | 
				
			||||||
	select BINFMT_ELF
 | 
						select BINFMT_ELF
 | 
				
			||||||
	select ARCH_BINFMT_ELF_RANDOMIZE_PIE
 | 
					 | 
				
			||||||
	select ARCH_HAS_ELF_RANDOMIZE
 | 
						select ARCH_HAS_ELF_RANDOMIZE
 | 
				
			||||||
	select OF
 | 
						select OF
 | 
				
			||||||
	select OF_EARLY_FLATTREE
 | 
						select OF_EARLY_FLATTREE
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -163,10 +163,9 @@ extern unsigned int vdso_enabled;
 | 
				
			||||||
   the loader.  We need to make sure that it is out of the way of the program
 | 
					   the loader.  We need to make sure that it is out of the way of the program
 | 
				
			||||||
   that it will "exec", and that there is sufficient room for the brk. 64-bit
 | 
					   that it will "exec", and that there is sufficient room for the brk. 64-bit
 | 
				
			||||||
   tasks are aligned to 4GB. */
 | 
					   tasks are aligned to 4GB. */
 | 
				
			||||||
extern unsigned long randomize_et_dyn(void);
 | 
					#define ELF_ET_DYN_BASE (is_32bit_task() ? \
 | 
				
			||||||
#define ELF_ET_DYN_BASE (randomize_et_dyn() + (is_32bit_task() ? \
 | 
					 | 
				
			||||||
				(STACK_TOP / 3 * 2) : \
 | 
									(STACK_TOP / 3 * 2) : \
 | 
				
			||||||
				(STACK_TOP / 3 * 2) & ~((1UL << 32) - 1)))
 | 
									(STACK_TOP / 3 * 2) & ~((1UL << 32) - 1))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* This yields a mask that user programs can use to figure out what
 | 
					/* This yields a mask that user programs can use to figure out what
 | 
				
			||||||
   instruction set this CPU supports. */
 | 
					   instruction set this CPU supports. */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -177,14 +177,6 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 | 
				
			||||||
	return addr;
 | 
						return addr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
unsigned long randomize_et_dyn(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (current->flags & PF_RANDOMIZE)
 | 
					 | 
				
			||||||
		return arch_mmap_rnd();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0UL;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef CONFIG_64BIT
 | 
					#ifndef CONFIG_64BIT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -87,7 +87,6 @@ config X86
 | 
				
			||||||
	select HAVE_ARCH_KMEMCHECK
 | 
						select HAVE_ARCH_KMEMCHECK
 | 
				
			||||||
	select HAVE_ARCH_KASAN if X86_64 && SPARSEMEM_VMEMMAP
 | 
						select HAVE_ARCH_KASAN if X86_64 && SPARSEMEM_VMEMMAP
 | 
				
			||||||
	select HAVE_USER_RETURN_NOTIFIER
 | 
						select HAVE_USER_RETURN_NOTIFIER
 | 
				
			||||||
	select ARCH_BINFMT_ELF_RANDOMIZE_PIE
 | 
					 | 
				
			||||||
	select ARCH_HAS_ELF_RANDOMIZE
 | 
						select ARCH_HAS_ELF_RANDOMIZE
 | 
				
			||||||
	select HAVE_ARCH_JUMP_LABEL
 | 
						select HAVE_ARCH_JUMP_LABEL
 | 
				
			||||||
	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
 | 
						select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,9 +27,6 @@ config COMPAT_BINFMT_ELF
 | 
				
			||||||
	bool
 | 
						bool
 | 
				
			||||||
	depends on COMPAT && BINFMT_ELF
 | 
						depends on COMPAT && BINFMT_ELF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config ARCH_BINFMT_ELF_RANDOMIZE_PIE
 | 
					 | 
				
			||||||
	bool
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
config ARCH_BINFMT_ELF_STATE
 | 
					config ARCH_BINFMT_ELF_STATE
 | 
				
			||||||
	bool
 | 
						bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,6 +31,7 @@
 | 
				
			||||||
#include <linux/security.h>
 | 
					#include <linux/security.h>
 | 
				
			||||||
#include <linux/random.h>
 | 
					#include <linux/random.h>
 | 
				
			||||||
#include <linux/elf.h>
 | 
					#include <linux/elf.h>
 | 
				
			||||||
 | 
					#include <linux/elf-randomize.h>
 | 
				
			||||||
#include <linux/utsname.h>
 | 
					#include <linux/utsname.h>
 | 
				
			||||||
#include <linux/coredump.h>
 | 
					#include <linux/coredump.h>
 | 
				
			||||||
#include <linux/sched.h>
 | 
					#include <linux/sched.h>
 | 
				
			||||||
| 
						 | 
					@ -910,21 +911,10 @@ static int load_elf_binary(struct linux_binprm *bprm)
 | 
				
			||||||
			 * default mmap base, as well as whatever program they
 | 
								 * default mmap base, as well as whatever program they
 | 
				
			||||||
			 * might try to exec.  This is because the brk will
 | 
								 * might try to exec.  This is because the brk will
 | 
				
			||||||
			 * follow the loader, and is not movable.  */
 | 
								 * follow the loader, and is not movable.  */
 | 
				
			||||||
#ifdef CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE
 | 
								load_bias = ELF_ET_DYN_BASE - vaddr;
 | 
				
			||||||
			/* Memory randomization might have been switched off
 | 
					 | 
				
			||||||
			 * in runtime via sysctl or explicit setting of
 | 
					 | 
				
			||||||
			 * personality flags.
 | 
					 | 
				
			||||||
			 * If that is the case, retain the original non-zero
 | 
					 | 
				
			||||||
			 * load_bias value in order to establish proper
 | 
					 | 
				
			||||||
			 * non-randomized mappings.
 | 
					 | 
				
			||||||
			 */
 | 
					 | 
				
			||||||
			if (current->flags & PF_RANDOMIZE)
 | 
								if (current->flags & PF_RANDOMIZE)
 | 
				
			||||||
				load_bias = 0;
 | 
									load_bias += arch_mmap_rnd();
 | 
				
			||||||
			else
 | 
								load_bias = ELF_PAGESTART(load_bias);
 | 
				
			||||||
				load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
			load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
			total_size = total_mapping_size(elf_phdata,
 | 
								total_size = total_mapping_size(elf_phdata,
 | 
				
			||||||
							loc->elf_ex.e_phnum);
 | 
												loc->elf_ex.e_phnum);
 | 
				
			||||||
			if (!total_size) {
 | 
								if (!total_size) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue