Skip to contentSkip to conversation

Patch "binfmt_elf: use ELF_ET_DYN_BASE only for PIE" has been added to the 4.9-stable tree

PATCH [email protected] 1 participant 1 message Jul 18, 2017

Subsystems (4)
lore
Share & tools
lore

[email protected]

author maintainer Applied
#0 lore raw

This is a note to let you know that I've just added the patch titled

binfmt_elf: use ELF_ET_DYN_BASE only for PIE

to the 4.9-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
binfmt_elf-use-elf_et_dyn_base-only-for-pie.patch
and it can be found in the queue-4.9 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.

Quoted 1 line

From eab09532d40090698b05a07c1c87f39fdbc5fab5 Mon Sep 17 00:00:00 2001

From: Kees Cook <[email protected]>
Date: Mon, 10 Jul 2017 15:52:37 -0700
Subject: binfmt_elf: use ELF_ET_DYN_BASE only for PIE

From: Kees Cook <[email protected]>

commit eab09532d40090698b05a07c1c87f39fdbc5fab5 upstream.

The ELF_ET_DYN_BASE position was originally intended to keep loaders away from ET_EXEC binaries. (For example, running "/lib/ld-linux.so.2 /bin/cat" might cause the subsequent load of /bin/cat into where the loader had been loaded.)

With the advent of PIE (ET_DYN binaries with an INTERP Program Header), ELF_ET_DYN_BASE continued to be used since the kernel was only looking at ET_DYN. However, since ELF_ET_DYN_BASE is traditionally set at the top 1/3rd of the TASK_SIZE, a substantial portion of the address space is unused.

For 32-bit tasks when RLIMIT_STACK is set to RLIM_INFINITY, programs are loaded above the mmap region. This means they can be made to collide (CVE-2017-1000370) or nearly collide (CVE-2017-1000371) with pathological stack regions.

Lowering ELF_ET_DYN_BASE solves both by moving programs below the mmap region in all cases, and will now additionally avoid programs falling back to the mmap region by enforcing MAP_FIXED for program loads (i.e. if it would have collided with the stack, now it will fail to load instead of falling back to the mmap region).

To allow for a lower ELF_ET_DYN_BASE, loaders (ET_DYN without INTERP) are loaded into the mmap region, leaving space available for either an ET_EXEC binary with a fixed location or PIE being loaded into mmap by the loader. Only PIE programs are loaded offset from ELF_ET_DYN_BASE, which means architectures can now safely lower their values without risk of loaders colliding with their subsequently loaded programs.

For 64-bit, ELF_ET_DYN_BASE is best set to 4GB to allow runtimes to use the entire 32-bit address space for 32-bit pointers.

Thanks to PaX Team, Daniel Micay, and Rik van Riel for inspiration and suggestions on how to implement this solution.

Fixes d1fd836dcf00 ("mm: split ET_DYN ASLR from mmap ASLR")
Cc Daniel Micay <[email protected]>
Cc Qualys Security Advisory <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc "H. Peter Anvin" <[email protected]>
Cc Alexander Viro <[email protected]>
Cc Dmitry Safonov <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Grzegorz Andrejczuk <[email protected]>
Cc Masahiro Yamada <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Heiko Carstens <[email protected]>
Cc James Hogan <[email protected]>
Cc Martin Schwidefsky <[email protected]>
Cc Michael Ellerman <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Pratyush Anand <[email protected]>
Cc Russell King <[email protected]>
Cc Will Deacon <[email protected]>
---
 arch/x86/include/asm/elf.h |   13 +++++----
 fs/binfmt_elf.c            |   59 ++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 58 insertions(+), 14 deletions(-)
arch/x86/include/asm/elf.h +7 -6
@@ -245,12 +245,13 @@ extern int force_personality32;
 #define CORE_DUMP_USE_REGSET
 #define ELF_EXEC_PAGESIZE	4096
 
-/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
-   use of this is to invoke "./ld.so someprog" to test out a new version of
-   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.  */
-
-#define ELF_ET_DYN_BASE		(TASK_SIZE / 3 * 2)
+/*
+ * This is the base location for PIE (ET_DYN with INTERP) loads. On
+ * 64-bit, this is raised to 4GB to leave the entire 32-bit address
+ * space open for things that want to use the area for 32-bit pointers.
+ */
+#define ELF_ET_DYN_BASE		(mmap_is_ia32() ? 0x000400000UL : \
+						  0x100000000UL)
 
 /* This yields a mask that user programs can use to figure out what
    instruction set this CPU supports.  This could be done in user space,
fs/binfmt_elf.c +51 -8

68 lines not on this page · raw message

Patches currently in stable-queue which might be from [email protected] are

queue-4.9/binfmt_elf-use-elf_et_dyn_base-only-for-pie.patch queue-4.9/exec-limit-arg-stack-to-at-most-75-of-_stk_lim.patch queue-4.9/s390-reduce-elf_et_dyn_base.patch queue-4.9/arm-move-elf_et_dyn_base-to-4mb.patch queue-4.9/arm64-move-elf_et_dyn_base-to-4gb-4mb.patch queue-4.9/selftests-capabilities-fix-the-test_execve-test.patch queue-4.9/powerpc-move-elf_et_dyn_base-to-4gb-4mb.patch