lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Mon, 17 Nov 2014 18:17:20 -0800
From:	Greg Thelen <gthelen@...gle.com>
To:	Junjie Mao <eternal.n08@...il.com>
Cc:	Kees Cook <keescook@...omium.org>, linux-kernel@...r.kernel.org,
	"H. Peter Anvin" <hpa@...or.com>,
	Thomas Gleixner <tglx@...utronix.de>,
	Ingo Molnar <mingo@...hat.com>, x86@...nel.org,
	Josh Triplett <josh@...htriplett.org>,
	Matt Fleming <matt.fleming@...el.com>,
	Ard Biesheuvel <ard.biesheuvel@...aro.org>,
	Vivek Goyal <vgoyal@...hat.com>,
	Andi Kleen <ak@...ux.intel.com>,
	Fengguang Wu <fengguang.wu@...el.com>, stable@...r.kernel.org
Subject: Re: [PATCH v3] x86, kaslr: Prevent .bss from overlaping initrd

On Fri, Oct 31 2014, Junjie Mao wrote:

> When choosing a random address, the current implementation does not take into
> account the reversed space for .bss and .brk sections. Thus the relocated kernel
> may overlap other components in memory. Here is an example of the overlap from a
> x86_64 kernel in qemu (the ranges of physical addresses are presented):
>
>  Physical Address
>
>     0x0fe00000                  --+--------------------+  <-- randomized base
>                                /  |  relocated kernel  |
>                    vmlinux.bin    | (from vmlinux.bin) |
>     0x1336d000    (an ELF file)   +--------------------+--
>                                \  |                    |  \
>     0x1376d870                  --+--------------------+   |
>                                   |    relocs table    |   |
>     0x13c1c2a8                    +--------------------+   .bss and .brk
>                                   |                    |   |
>     0x13ce6000                    +--------------------+   |
>                                   |                    |  /
>     0x13f77000                    |       initrd       |--
>                                   |                    |
>     0x13fef374                    +--------------------+
>
> The initrd image will then be overwritten by the memset during early
> initialization:
>
> [    1.655204] Unpacking initramfs...
> [    1.662831] Initramfs unpacking failed: junk in compressed archive
>
> This patch prevents the above situation by requiring a larger space when looking
> for a random kernel base, so that existing logic can effectively avoids the
> overlap.
>
> Fixes: 82fa9637a2 ("x86, kaslr: Select random position from e820 maps")
> Reported-by: Fengguang Wu <fengguang.wu@...el.com>
> Signed-off-by: Junjie Mao <eternal.n08@...il.com>
> [kees: switched to perl to avoid hex translation pain in mawk vs gawk]
> [kees: calculated overlap without relocs table]
> Signed-off-by: Kees Cook <keescook@...omium.org>
> Cc: stable@...r.kernel.org
> ---
> This version updates the commit log only.
>
> Kees, please help review the documentation. Thanks!
>
> Best Regards
> Junjie Mao
[...]
> diff --git a/arch/x86/tools/calc_run_size.pl b/arch/x86/tools/calc_run_size.pl
> new file mode 100644
> index 000000000000..0b0b124d3ece
> --- /dev/null
> +++ b/arch/x86/tools/calc_run_size.pl
> @@ -0,0 +1,30 @@
> +#!/usr/bin/perl
> +#
> +# Calculate the amount of space needed to run the kernel, including room for
> +# the .bss and .brk sections.
> +#
> +# Usage:
> +# objdump -h a.out | perl calc_run_size.pl
> +use strict;
> +
> +my $mem_size = 0;
> +my $file_offset = 0;
> +
> +my $sections=" *[0-9]+ \.(?:bss|brk) +";
> +while (<>) {
> + if (/^$sections([0-9a-f]+) +(?:[0-9a-f]+ +){2}([0-9a-f]+)/) {
> + my $size = hex($1);
> + my $offset = hex($2);
> + $mem_size += $size;
> + if ($file_offset == 0) {
> + $file_offset = $offset;
> + } elsif ($file_offset != $offset) {
> + die ".bss and .brk lack common file offset\n";
> + }
> + }
> +}
> +
> +if ($file_offset == 0) {
> + die "Never found .bss or .brk file offset\n";
> +}
> +printf("%d\n", $mem_size + $file_offset);

Given that bss and brk are nobits (i.e. only ALLOC) sections, does
file_offset make sense as a load address.  This fails with gold:

$ git checkout v3.18-rc5
$ make  # with gold
[...]
..bss and .brk lack common file offset
..bss and .brk lack common file offset
..bss and .brk lack common file offset
..bss and .brk lack common file offset
  MKPIGGY arch/x86/boot/compressed/piggy.S
Usage: arch/x86/boot/compressed/mkpiggy compressed_file run_size
make[2]: *** [arch/x86/boot/compressed/piggy.S] Error 1
make[1]: *** [arch/x86/boot/compressed/vmlinux] Error 2
make: *** [bzImage] Error 2

In ld.bfd brk/bss file_offsets match, but they differ with ld.gold:

$ objdump -h vmlinux.ld
[...]
  0 .text         00818bb3  ffffffff81000000  0000000001000000  00200000  2**12
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
[...]
 26 .bss          000e0000  ffffffff81fe8000  0000000001fe8000  013e8000  2**12
                  ALLOC
 27 .brk          00026000  ffffffff820c8000  00000000020c8000  013e8000  2**0
                  ALLOC

$ objdump -h vmlinux.ld | perl arch/x86/tools/calc_run_size.pl
21946368
# aka 0x14ee000


$ objdump -h vmlinux.gold
[...]
  0 .text         00818bb3  ffffffff81000000  0000000001000000  00001000  2**12
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
[...]
 26 .bss          000e0000  ffffffff81feb000  0000000001feb000  00e90000  2**12
                  ALLOC
 27 .brk          00026000  ffffffff820cb000  00000000020cb000  00f70000  2**0
                  ALLOC
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ