1. 24 May, 2015 9 commits
    • Hector Marco-Gisbert's avatar
      ASLR: fix stack randomization on 64-bit systems · ba455d81
      Hector Marco-Gisbert authored
      commit 4e7c22d4 upstream
      
      The issue is that the stack for processes is not properly randomized on 64 bit
      architectures due to an integer overflow.
      
      The affected function is randomize_stack_top() in file "fs/binfmt_elf.c":
      
      static unsigned long randomize_stack_top(unsigned long stack_top)
      {
               unsigned int random_variable = 0;
      
               if ((current->flags & PF_RANDOMIZE) &&
                       !(current->personality & ADDR_NO_RANDOMIZE)) {
                       random_variable = get_random_int() & STACK_RND_MASK;
                       random_variable <<= PAGE_SHIFT;
               }
               return PAGE_ALIGN(stack_top) + random_variable;
               return PAGE_ALIGN(stack_top) - random_variable;
      }
      
      Note that, it declares the "random_variable" variable as "unsigned int". Since
      the result of the shifting operation between STACK_RND_MASK (which is
      0x3fffff on x86_64, 22 bits) and PAGE_SHIFT (which is 12 on x86_64):
      
      random_variable <<= PAGE_SHIFT;
      
      then the two leftmost bits are dropped when storing the result in the
      "random_variable". This variable shall be at least 34 bits long to hold the
      (22+12) result.
      
      These two dropped bits have an impact on the entropy of process stack.
      Concretely, the total stack entropy is reduced by four: from 2^28 to 2^30 (One
      fourth of expected entropy).
      
      This patch restores back the entropy by correcting the types involved in the
      operations in the functions randomize_stack_top() and stack_maxrandom_size().
      
      The successful fix can be tested with:
      $ for i in `seq 1 10`; do cat /proc/self/maps | grep stack; done
      7ffeda566000-7ffeda587000 rw-p 00000000 00:00 0                          [stack]
      7fff5a332000-7fff5a353000 rw-p 00000000 00:00 0                          [stack]
      7ffcdb7a1000-7ffcdb7c2000 rw-p 00000000 00:00 0                          [stack]
      7ffd5e2c4000-7ffd5e2e5000 rw-p 00000000 00:00 0                          [stack]
      ...
      
      Once corrected, the leading bytes should be between 7ffc and 7fff, rather
      than always being 7fff.
      
      CVE-2015-1593
      Signed-off-by: default avatarHector Marco-Gisbert <hecmargi@upv.es>
      Signed-off-by: default avatarIsmael Ripoll <iripoll@upv.es>
      [kees: rebase, fix 80 char, clean up commit message, add test example, cve]
      Signed-off-by: default avatarKees Cook <keescook@chromium.org>
      Cc: stable@vger.kernel.org
      Signed-off-by: default avatarWilly Tarreau <w@1wt.eu>
      ba455d81
    • Andy Lutomirski's avatar
      x86_64, vdso: Fix the vdso address randomization algorithm · 7f36f1ac
      Andy Lutomirski authored
      commit 394f56fe upstream
      
      The theory behind vdso randomization is that it's mapped at a random
      offset above the top of the stack.  To avoid wasting a page of
      memory for an extra page table, the vdso isn't supposed to extend
      past the lowest PMD into which it can fit.  Other than that, the
      address should be a uniformly distributed address that meets all of
      the alignment requirements.
      
      The current algorithm is buggy: the vdso has about a 50% probability
      of being at the very end of a PMD.  The current algorithm also has a
      decent chance of failing outright due to incorrect handling of the
      case where the top of the stack is near the top of its PMD.
      
      This fixes the implementation.  The paxtest estimate of vdso
      "randomisation" improves from 11 bits to 18 bits.  (Disclaimer: I
      don't know what the paxtest code is actually calculating.)
      
      It's worth noting that this algorithm is inherently biased: the vdso
      is more likely to end up near the end of its PMD than near the
      beginning.  Ideally we would either nix the PMD sharing requirement
      or jointly randomize the vdso and the stack to reduce the bias.
      
      In the mean time, this is a considerable improvement with basically
      no risk of compatibility issues, since the allowed outputs of the
      algorithm are unchanged.
      
      As an easy test, doing this:
      
      for i in `seq 10000`
        do grep -P vdso /proc/self/maps |cut -d- -f1
      done |sort |uniq -d
      
      used to produce lots of output (1445 lines on my most recent run).
      A tiny subset looks like this:
      
      7fffdfffe000
      7fffe01fe000
      7fffe05fe000
      7fffe07fe000
      7fffe09fe000
      7fffe0bfe000
      7fffe0dfe000
      
      Note the suspicious fe000 endings.  With the fix, I get a much more
      palatable 76 repeated addresses.
      Reviewed-by: default avatarKees Cook <keescook@chromium.org>
      Cc: stable@vger.kernel.org
      Signed-off-by: default avatarAndy Lutomirski <luto@amacapital.net>
      [bwh: Backported to 2.6.32:
       - The whole file is only built for x86_64; adjust context and comment for this
       - We don't have align_vdso_addr()]
      Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
      Signed-off-by: default avatarWilly Tarreau <w@1wt.eu>
      7f36f1ac
    • Andy Lutomirski's avatar
      x86, kvm: Clear paravirt_enabled on KVM guests for espfix32's benefit · b23c0b06
      Andy Lutomirski authored
      commit 29fa6825 upstream
      
      paravirt_enabled has the following effects:
      
       - Disables the F00F bug workaround warning.  There is no F00F bug
         workaround any more because Linux's standard IDT handling already
         works around the F00F bug, but the warning still exists.  This
         is only cosmetic, and, in any event, there is no such thing as
         KVM on a CPU with the F00F bug.
      
       - Disables 32-bit APM BIOS detection.  On a KVM paravirt system,
         there should be no APM BIOS anyway.
      
       - Disables tboot.  I think that the tboot code should check the
         CPUID hypervisor bit directly if it matters.
      
       - paravirt_enabled disables espfix32.  espfix32 should *not* be
         disabled under KVM paravirt.
      
      The last point is the purpose of this patch.  It fixes a leak of the
      high 16 bits of the kernel stack address on 32-bit KVM paravirt
      guests.  Fixes CVE-2014-8134.
      Suggested-by: default avatarKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
      Signed-off-by: default avatarAndy Lutomirski <luto@amacapital.net>
      Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
      Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
      [bwh: Backported to 2.6.32: adjust indentation, context]
      Signed-off-by: default avatarWilly Tarreau <w@1wt.eu>
      b23c0b06
    • Andy Lutomirski's avatar
      x86/tls: Don't validate lm in set_thread_area() after all · c52fdba6
      Andy Lutomirski authored
      commit 3fb2f423 upstream.
      
      It turns out that there's a lurking ABI issue.  GCC, when
      compiling this in a 32-bit program:
      
      struct user_desc desc = {
      	.entry_number    = idx,
      	.base_addr       = base,
      	.limit           = 0xfffff,
      	.seg_32bit       = 1,
      	.contents        = 0, /* Data, grow-up */
      	.read_exec_only  = 0,
      	.limit_in_pages  = 1,
      	.seg_not_present = 0,
      	.useable         = 0,
      };
      
      will leave .lm uninitialized.  This means that anything in the
      kernel that reads user_desc.lm for 32-bit tasks is unreliable.
      
      Revert the .lm check in set_thread_area().  The value never did
      anything in the first place.
      
      Fixes: 0e58af4e ("x86/tls: Disallow unusual TLS segments")
      Signed-off-by: default avatarAndy Lutomirski <luto@amacapital.net>
      Acked-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Linus Torvalds <torvalds@linux-foundation.org>
      Link: http://lkml.kernel.org/r/d7875b60e28c512f6a6fc0baf5714d58e7eaadbb.1418856405.git.luto@amacapital.netSigned-off-by: default avatarIngo Molnar <mingo@kernel.org>
      [bwh: Backported to 3.2: adjust filename]
      Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
      (cherry picked from commit c759a579)
      Signed-off-by: default avatarWilly Tarreau <w@1wt.eu>
      c52fdba6
    • Andy Lutomirski's avatar
      x86/tls: Disallow unusual TLS segments · 18cb16aa
      Andy Lutomirski authored
      commit 0e58af4e upstream.
      
      Users have no business installing custom code segments into the
      GDT, and segments that are not present but are otherwise valid
      are a historical source of interesting attacks.
      
      For completeness, block attempts to set the L bit.  (Prior to
      this patch, the L bit would have been silently dropped.)
      
      This is an ABI break.  I've checked glibc, musl, and Wine, and
      none of them look like they'll have any trouble.
      
      Note to stable maintainers: this is a hardening patch that fixes
      no known bugs.  Given the possibility of ABI issues, this
      probably shouldn't be backported quickly.
      Signed-off-by: default avatarAndy Lutomirski <luto@amacapital.net>
      Acked-by: default avatarH. Peter Anvin <hpa@zytor.com>
      Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
      Cc: Linus Torvalds <torvalds@linux-foundation.org>
      Cc: security@kernel.org <security@kernel.org>
      Cc: Willy Tarreau <w@1wt.eu>
      Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
      Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
      (cherry picked from commit fbc3c534)
      Signed-off-by: default avatarWilly Tarreau <w@1wt.eu>
      18cb16aa
    • Andy Lutomirski's avatar
      x86, tls: Interpret an all-zero struct user_desc as "no segment" · 1f50d3c7
      Andy Lutomirski authored
      commit 3669ef9f upstream.
      
      The Witcher 2 did something like this to allocate a TLS segment index:
      
              struct user_desc u_info;
              bzero(&u_info, sizeof(u_info));
              u_info.entry_number = (uint32_t)-1;
      
              syscall(SYS_set_thread_area, &u_info);
      
      Strictly speaking, this code was never correct.  It should have set
      read_exec_only and seg_not_present to 1 to indicate that it wanted
      to find a free slot without putting anything there, or it should
      have put something sensible in the TLS slot if it wanted to allocate
      a TLS entry for real.  The actual effect of this code was to
      allocate a bogus segment that could be used to exploit espfix.
      
      The set_thread_area hardening patches changed the behavior, causing
      set_thread_area to return -EINVAL and crashing the game.
      
      This changes set_thread_area to interpret this as a request to find
      a free slot and to leave it empty, which isn't *quite* what the game
      expects but should be close enough to keep it working.  In
      particular, using the code above to allocate two segments will
      allocate the same segment both times.
      
      According to FrostbittenKing on Github, this fixes The Witcher 2.
      
      If this somehow still causes problems, we could instead allocate
      a limit==0 32-bit data segment, but that seems rather ugly to me.
      
      Fixes: 41bdc785 x86/tls: Validate TLS entries to protect espfix
      Signed-off-by: default avatarAndy Lutomirski <luto@amacapital.net>
      Cc: torvalds@linux-foundation.org
      Link: http://lkml.kernel.org/r/0cb251abe1ff0958b8e468a9a9a905b80ae3a746.1421954363.git.luto@amacapital.netSigned-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
      (cherry picked from commit 3175b4cb)
      Signed-off-by: default avatarWilly Tarreau <w@1wt.eu>
      1f50d3c7
    • Andy Lutomirski's avatar
      x86, tls, ldt: Stop checking lm in LDT_empty · 598b6280
      Andy Lutomirski authored
      commit e30ab185 upstream.
      
      32-bit programs don't have an lm bit in their ABI, so they can't
      reliably cause LDT_empty to return true without resorting to memset.
      They shouldn't need to do this.
      
      This should fix a longstanding, if minor, issue in all 64-bit kernels
      as well as a potential regression in the TLS hardening code.
      
      Fixes: 41bdc785 x86/tls: Validate TLS entries to protect espfix
      Signed-off-by: default avatarAndy Lutomirski <luto@amacapital.net>
      Cc: torvalds@linux-foundation.org
      Link: http://lkml.kernel.org/r/72a059de55e86ad5e2935c80aa91880ddf19d07c.1421954363.git.luto@amacapital.netSigned-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
      (cherry picked from commit f62570cb)
      Signed-off-by: default avatarWilly Tarreau <w@1wt.eu>
      598b6280
    • Andy Lutomirski's avatar
      x86/tls: Validate TLS entries to protect espfix · 85e01300
      Andy Lutomirski authored
      commit 41bdc785 upstream
      
      Installing a 16-bit RW data segment into the GDT defeats espfix.
      AFAICT this will not affect glibc, Wine, or dosemu at all.
      Signed-off-by: default avatarAndy Lutomirski <luto@amacapital.net>
      Acked-by: default avatarH. Peter Anvin <hpa@zytor.com>
      Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
      Cc: Linus Torvalds <torvalds@linux-foundation.org>
      Cc: security@kernel.org <security@kernel.org>
      Cc: Willy Tarreau <w@1wt.eu>
      Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
      Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
      Signed-off-by: default avatarWilly Tarreau <w@1wt.eu>
      85e01300
    • Andy Lutomirski's avatar
      x86/asm/traps: Disable tracing and kprobes in fixup_bad_iret and sync_regs · f0d8cc6f
      Andy Lutomirski authored
      commit 7ddc6a21 upstream.
      
      These functions can be executed on the int3 stack, so kprobes
      are dangerous. Tracing is probably a bad idea, too.
      
      Fixes: b645af2d ("x86_64, traps: Rework bad_iret")
      Signed-off-by: default avatarAndy Lutomirski <luto@amacapital.net>
      Cc: Linus Torvalds <torvalds@linux-foundation.org>
      Cc: Steven Rostedt <rostedt@goodmis.org>
      Link: http://lkml.kernel.org/r/50e33d26adca60816f3ba968875801652507d0c4.1416870125.git.luto@amacapital.netSigned-off-by: default avatarIngo Molnar <mingo@kernel.org>
      [bwh: Backported to 3.2:
       - Use __kprobes instead of NOKPROBE_SYMBOL()
       - Don't use __visible]
      Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
      (cherry picked from commit 8ea4c465)
      Signed-off-by: default avatarWilly Tarreau <w@1wt.eu>
      f0d8cc6f
  2. 13 Dec, 2014 31 commits