diff --git a/debian/changelog b/debian/changelog index fe041b638..9b9437bf0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -259,6 +259,8 @@ linux (4.11.11-1) UNRELEASED; urgency=medium (fixes FTBFS) * [sparc64] Update "Revert "sparc: move exports to definitions"" for the addition of __multi3 (fixes FTBFS) + * binfmt_elf: use ELF_ET_DYN_BASE only for PIE (CVE-2017-1000370, + CVE-2017-1000371) [ Uwe Kleine-König ] * [arm64] enable FB_SIMPLE diff --git a/debian/patches/bugfix/all/binfmt_elf-use-elf_et_dyn_base-only-for-pie.patch b/debian/patches/bugfix/all/binfmt_elf-use-elf_et_dyn_base-only-for-pie.patch new file mode 100644 index 000000000..b2a0f5a1e --- /dev/null +++ b/debian/patches/bugfix/all/binfmt_elf-use-elf_et_dyn_base-only-for-pie.patch @@ -0,0 +1,167 @@ +From: Kees Cook +Date: Mon, 10 Jul 2017 15:52:37 -0700 +Subject: binfmt_elf: use ELF_ET_DYN_BASE only for PIE +Origin: https://git.kernel.org/linus/eab09532d40090698b05a07c1c87f39fdbc5fab5 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-1000370 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-1000371 + +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") +Link: http://lkml.kernel.org/r/20170621173201.GA114489@beast +Signed-off-by: Kees Cook +Acked-by: Rik van Riel +Cc: Daniel Micay +Cc: Qualys Security Advisory +Cc: Thomas Gleixner +Cc: Ingo Molnar +Cc: "H. Peter Anvin" +Cc: Alexander Viro +Cc: Dmitry Safonov +Cc: Andy Lutomirski +Cc: Grzegorz Andrejczuk +Cc: Masahiro Yamada +Cc: Benjamin Herrenschmidt +Cc: Catalin Marinas +Cc: Heiko Carstens +Cc: James Hogan +Cc: Martin Schwidefsky +Cc: Michael Ellerman +Cc: Paul Mackerras +Cc: Pratyush Anand +Cc: Russell King +Cc: Will Deacon +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + arch/x86/include/asm/elf.h | 13 +++++----- + fs/binfmt_elf.c | 59 +++++++++++++++++++++++++++++++++++++++------- + 2 files changed, 58 insertions(+), 14 deletions(-) + +--- a/arch/x86/include/asm/elf.h ++++ b/arch/x86/include/asm/elf.h +@@ -246,12 +246,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, +--- a/fs/binfmt_elf.c ++++ b/fs/binfmt_elf.c +@@ -927,17 +927,60 @@ static int load_elf_binary(struct linux_ + elf_flags = MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE; + + vaddr = elf_ppnt->p_vaddr; ++ /* ++ * If we are loading ET_EXEC or we have already performed ++ * the ET_DYN load_addr calculations, proceed normally. ++ */ + if (loc->elf_ex.e_type == ET_EXEC || load_addr_set) { + elf_flags |= MAP_FIXED; + } else if (loc->elf_ex.e_type == ET_DYN) { +- /* Try and get dynamic programs out of the way of the +- * default mmap base, as well as whatever program they +- * might try to exec. This is because the brk will +- * follow the loader, and is not movable. */ +- load_bias = ELF_ET_DYN_BASE - vaddr; +- if (current->flags & PF_RANDOMIZE) +- load_bias += arch_mmap_rnd(); +- load_bias = ELF_PAGESTART(load_bias); ++ /* ++ * This logic is run once for the first LOAD Program ++ * Header for ET_DYN binaries to calculate the ++ * randomization (load_bias) for all the LOAD ++ * Program Headers, and to calculate the entire ++ * size of the ELF mapping (total_size). (Note that ++ * load_addr_set is set to true later once the ++ * initial mapping is performed.) ++ * ++ * There are effectively two types of ET_DYN ++ * binaries: programs (i.e. PIE: ET_DYN with INTERP) ++ * and loaders (ET_DYN without INTERP, since they ++ * _are_ the ELF interpreter). The loaders must ++ * be loaded away from programs since the program ++ * may otherwise collide with the loader (especially ++ * for ET_EXEC which does not have a randomized ++ * position). For example to handle invocations of ++ * "./ld.so someprog" to test out a new version of ++ * the loader, the subsequent program that the ++ * loader loads must avoid the loader itself, so ++ * they cannot share the same load range. Sufficient ++ * room for the brk must be allocated with the ++ * loader as well, since brk must be available with ++ * the loader. ++ * ++ * Therefore, programs are loaded offset from ++ * ELF_ET_DYN_BASE and loaders are loaded into the ++ * independently randomized mmap region (0 load_bias ++ * without MAP_FIXED). ++ */ ++ if (elf_interpreter) { ++ load_bias = ELF_ET_DYN_BASE; ++ if (current->flags & PF_RANDOMIZE) ++ load_bias += arch_mmap_rnd(); ++ elf_flags |= MAP_FIXED; ++ } else ++ load_bias = 0; ++ ++ /* ++ * Since load_bias is used for all subsequent loading ++ * calculations, we must lower it by the first vaddr ++ * so that the remaining calculations based on the ++ * ELF vaddrs will be correctly offset. The result ++ * is then page aligned. ++ */ ++ load_bias = ELF_PAGESTART(load_bias - vaddr); ++ + total_size = total_mapping_size(elf_phdata, + loc->elf_ex.e_phnum); + if (!total_size) { diff --git a/debian/patches/series b/debian/patches/series index 87e2a4d18..53fbecfaf 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -143,6 +143,7 @@ debian/i386-686-pae-pci-set-pci-nobios-by-default.patch bugfix/all/tracing-Use-strlcpy-instead-of-strcpy-in-__trace_fin.patch bugfix/all/sunrpc-refactor-svc_set_num_threads.patch bugfix/all/nfsv4-fix-callback-server-shutdown.patch +bugfix/all/binfmt_elf-use-elf_et_dyn_base-only-for-pie.patch # Fix exported symbol versions bugfix/sparc/revert-sparc-move-exports-to-definitions.patch