[v2] powerpc/mm: Add support for runtime configuration of ASLR limits

Submitted by Michael Ellerman on April 20, 2017, 2:36 p.m.

Details

Message ID 1492698980-19510-1-git-send-email-mpe@ellerman.id.au
State Accepted
Commit 9fea59bd7ca541e5d0851f0b6dbca83c60ea90cd
Headers show

Commit Message

Michael Ellerman April 20, 2017, 2:36 p.m.
Add powerpc support for mmap_rnd_bits and mmap_rnd_compat_bits, which are two
sysctls that allow a user to configure the number of bits of randomness used for
ASLR.

Because of the way the Kconfig for ARCH_MMAP_RND_BITS is defined, we have to
construct at least the MIN value in Kconfig, vs in a header which would be more
natural. Given that we just go ahead and do it all in Kconfig.

At least according to the code (the documentation makes no mention of it), the
value is defined as the number of bits of randomisation *of the page*, not the
address. This makes some sense, with larger page sizes more of the low bits are
forced to zero, which would reduce the randomisation if we didn't take the
PAGE_SIZE into account. However it does mean the min/max values have to change
depending on the PAGE_SIZE in order to actually limit the amount of address
space consumed by the randomisation.

The result of that is that we have to define the default values based on both
32-bit vs 64-bit, but also the configured PAGE_SIZE. Furthermore now that we
have 128TB address space support on Book3S, we also have to take that into
account.

Finally we can wire up the value in arch_mmap_rnd().

Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Bhupesh Sharma <bhsharma@redhat.com>
---
 arch/powerpc/Kconfig   | 44 ++++++++++++++++++++++++++++++++++++++++++++
 arch/powerpc/mm/mmap.c | 11 ++++++-----
 2 files changed, 50 insertions(+), 5 deletions(-)

v2: Fix the 32-bit MAX value incorrectly using MIN as spotted by Kees.

Kees/Bhupesh, would love a Review/Ack/Tested-by from you, I'll plan to merge
this later today (Friday) my time.

Comments

Kees Cook April 20, 2017, 8:08 p.m.
On Thu, Apr 20, 2017 at 7:36 AM, Michael Ellerman <mpe@ellerman.id.au> wrote:
> Add powerpc support for mmap_rnd_bits and mmap_rnd_compat_bits, which are two
> sysctls that allow a user to configure the number of bits of randomness used for
> ASLR.
>
> Because of the way the Kconfig for ARCH_MMAP_RND_BITS is defined, we have to
> construct at least the MIN value in Kconfig, vs in a header which would be more
> natural. Given that we just go ahead and do it all in Kconfig.
>
> At least according to the code (the documentation makes no mention of it), the
> value is defined as the number of bits of randomisation *of the page*, not the
> address. This makes some sense, with larger page sizes more of the low bits are
> forced to zero, which would reduce the randomisation if we didn't take the
> PAGE_SIZE into account. However it does mean the min/max values have to change
> depending on the PAGE_SIZE in order to actually limit the amount of address
> space consumed by the randomisation.
>
> The result of that is that we have to define the default values based on both
> 32-bit vs 64-bit, but also the configured PAGE_SIZE. Furthermore now that we
> have 128TB address space support on Book3S, we also have to take that into
> account.
>
> Finally we can wire up the value in arch_mmap_rnd().
>
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
> Signed-off-by: Bhupesh Sharma <bhsharma@redhat.com>
> ---
>  arch/powerpc/Kconfig   | 44 ++++++++++++++++++++++++++++++++++++++++++++
>  arch/powerpc/mm/mmap.c | 11 ++++++-----
>  2 files changed, 50 insertions(+), 5 deletions(-)
>
> v2: Fix the 32-bit MAX value incorrectly using MIN as spotted by Kees.
>
> Kees/Bhupesh, would love a Review/Ack/Tested-by from you, I'll plan to merge
> this later today (Friday) my time.

Reviewed-by: Kees Cook <keescook@chromium.org>

Looks good!

-Kees

>
> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> index 97a8bc8a095c..6f0503951e94 100644
> --- a/arch/powerpc/Kconfig
> +++ b/arch/powerpc/Kconfig
> @@ -22,6 +22,48 @@ config MMU
>         bool
>         default y
>
> +config ARCH_MMAP_RND_BITS_MAX
> +       # On Book3S 64, the default virtual address space for 64-bit processes
> +       # is 2^47 (128TB). As a maximum, allow randomisation to consume up to
> +       # 32T of address space (2^45), which should ensure a reasonable gap
> +       # between bottom-up and top-down allocations for applications that
> +       # consume "normal" amounts of address space. Book3S 64 only supports 64K
> +       # and 4K page sizes.
> +       default 29 if PPC_BOOK3S_64 && PPC_64K_PAGES # 29 = 45 (32T) - 16 (64K)
> +       default 33 if PPC_BOOK3S_64                  # 33 = 45 (32T) - 12 (4K)
> +       #
> +       # On all other 64-bit platforms (currently only Book3E), the virtual
> +       # address space is 2^46 (64TB). Allow randomisation to consume up to 16T
> +       # of address space (2^44). Only 4K page sizes are supported.
> +       default 32 if 64BIT     # 32 = 44 (16T) - 12 (4K)
> +       #
> +       # For 32-bit, use the compat values, as they're the same.
> +       default ARCH_MMAP_RND_COMPAT_BITS_MAX
> +
> +config ARCH_MMAP_RND_BITS_MIN
> +       # Allow randomisation to consume up to 1GB of address space (2^30).
> +       default 14 if 64BIT && PPC_64K_PAGES    # 14 = 30 (1GB) - 16 (64K)
> +       default 18 if 64BIT                     # 18 = 30 (1GB) - 12 (4K)
> +       #
> +       # For 32-bit, use the compat values, as they're the same.
> +       default ARCH_MMAP_RND_COMPAT_BITS_MIN
> +
> +config ARCH_MMAP_RND_COMPAT_BITS_MAX
> +       # Total virtual address space for 32-bit processes is 2^31 (2GB).
> +       # Allow randomisation to consume up to 512MB of address space (2^29).
> +       default 11 if PPC_256K_PAGES    # 11 = 29 (512MB) - 18 (256K)
> +       default 13 if PPC_64K_PAGES     # 13 = 29 (512MB) - 16 (64K)
> +       default 15 if PPC_16K_PAGES     # 15 = 29 (512MB) - 14 (16K)
> +       default 17                      # 17 = 29 (512MB) - 12 (4K)
> +
> +config ARCH_MMAP_RND_COMPAT_BITS_MIN
> +       # Total virtual address space for 32-bit processes is 2^31 (2GB).
> +       # Allow randomisation to consume up to 8MB of address space (2^23).
> +       default 5 if PPC_256K_PAGES     #  5 = 23 (8MB) - 18 (256K)
> +       default 7 if PPC_64K_PAGES      #  7 = 23 (8MB) - 16 (64K)
> +       default 9 if PPC_16K_PAGES      #  9 = 23 (8MB) - 14 (16K)
> +       default 11                      # 11 = 23 (8MB) - 12 (4K)
> +
>  config HAVE_SETUP_PER_CPU_AREA
>         def_bool PPC64
>
> @@ -120,6 +162,8 @@ config PPC
>         select HAVE_ARCH_HARDENED_USERCOPY
>         select HAVE_ARCH_JUMP_LABEL
>         select HAVE_ARCH_KGDB
> +       select HAVE_ARCH_MMAP_RND_BITS
> +       select HAVE_ARCH_MMAP_RND_COMPAT_BITS   if COMPAT
>         select HAVE_ARCH_SECCOMP_FILTER
>         select HAVE_ARCH_TRACEHOOK
>         select HAVE_CBPF_JIT                    if !PPC64
> diff --git a/arch/powerpc/mm/mmap.c b/arch/powerpc/mm/mmap.c
> index a5d9ef59debe..6141cfff634e 100644
> --- a/arch/powerpc/mm/mmap.c
> +++ b/arch/powerpc/mm/mmap.c
> @@ -59,13 +59,14 @@ static inline int mmap_is_legacy(void)
>
>  unsigned long arch_mmap_rnd(void)
>  {
> -       unsigned long rnd;
> +       unsigned long shift, rnd;
>
> -       /* 8MB for 32bit, 1GB for 64bit */
> +       shift = mmap_rnd_bits;
> +#ifdef CONFIG_COMPAT
>         if (is_32bit_task())
> -               rnd = get_random_long() % (1<<(23-PAGE_SHIFT));
> -       else
> -               rnd = get_random_long() % (1UL<<(30-PAGE_SHIFT));
> +               shift = mmap_rnd_compat_bits;
> +#endif
> +       rnd = get_random_long() % (1 << shift);
>
>         return rnd << PAGE_SHIFT;
>  }
> --
> 2.7.4
>
Aneesh Kumar K.V April 21, 2017, 5:51 a.m.
Michael Ellerman <mpe@ellerman.id.au> writes:

> Add powerpc support for mmap_rnd_bits and mmap_rnd_compat_bits, which are two
> sysctls that allow a user to configure the number of bits of randomness used for
> ASLR.
>
> Because of the way the Kconfig for ARCH_MMAP_RND_BITS is defined, we have to
> construct at least the MIN value in Kconfig, vs in a header which would be more
> natural. Given that we just go ahead and do it all in Kconfig.
>
> At least according to the code (the documentation makes no mention of it), the
> value is defined as the number of bits of randomisation *of the page*, not the
> address. This makes some sense, with larger page sizes more of the low bits are
> forced to zero, which would reduce the randomisation if we didn't take the
> PAGE_SIZE into account. However it does mean the min/max values have to change
> depending on the PAGE_SIZE in order to actually limit the amount of address
> space consumed by the randomisation.
>
> The result of that is that we have to define the default values based on both
> 32-bit vs 64-bit, but also the configured PAGE_SIZE. Furthermore now that we
> have 128TB address space support on Book3S, we also have to take that into
> account.
>
> Finally we can wire up the value in arch_mmap_rnd().
>
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
> Signed-off-by: Bhupesh Sharma <bhsharma@redhat.com>

Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>

> ---
>  arch/powerpc/Kconfig   | 44 ++++++++++++++++++++++++++++++++++++++++++++
>  arch/powerpc/mm/mmap.c | 11 ++++++-----
>  2 files changed, 50 insertions(+), 5 deletions(-)
>
> v2: Fix the 32-bit MAX value incorrectly using MIN as spotted by Kees.
>
> Kees/Bhupesh, would love a Review/Ack/Tested-by from you, I'll plan to merge
> this later today (Friday) my time.
>
> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> index 97a8bc8a095c..6f0503951e94 100644
> --- a/arch/powerpc/Kconfig
> +++ b/arch/powerpc/Kconfig
> @@ -22,6 +22,48 @@ config MMU
>  	bool
>  	default y
>  
> +config ARCH_MMAP_RND_BITS_MAX
> +	# On Book3S 64, the default virtual address space for 64-bit processes
> +	# is 2^47 (128TB). As a maximum, allow randomisation to consume up to
> +	# 32T of address space (2^45), which should ensure a reasonable gap
> +	# between bottom-up and top-down allocations for applications that
> +	# consume "normal" amounts of address space. Book3S 64 only supports 64K
> +	# and 4K page sizes.
> +	default 29 if PPC_BOOK3S_64 && PPC_64K_PAGES # 29 = 45 (32T) - 16 (64K)
> +	default 33 if PPC_BOOK3S_64		     # 33 = 45 (32T) - 12 (4K)
> +	#
> +	# On all other 64-bit platforms (currently only Book3E), the virtual
> +	# address space is 2^46 (64TB). Allow randomisation to consume up to 16T
> +	# of address space (2^44). Only 4K page sizes are supported.
> +	default 32 if 64BIT	# 32 = 44 (16T) - 12 (4K)
> +	#
> +	# For 32-bit, use the compat values, as they're the same.
> +	default ARCH_MMAP_RND_COMPAT_BITS_MAX
> +
> +config ARCH_MMAP_RND_BITS_MIN
> +	# Allow randomisation to consume up to 1GB of address space (2^30).
> +	default 14 if 64BIT && PPC_64K_PAGES	# 14 = 30 (1GB) - 16 (64K)
> +	default 18 if 64BIT			# 18 = 30 (1GB) - 12 (4K)
> +	#
> +	# For 32-bit, use the compat values, as they're the same.
> +	default ARCH_MMAP_RND_COMPAT_BITS_MIN
> +
> +config ARCH_MMAP_RND_COMPAT_BITS_MAX
> +	# Total virtual address space for 32-bit processes is 2^31 (2GB).
> +	# Allow randomisation to consume up to 512MB of address space (2^29).
> +	default 11 if PPC_256K_PAGES	# 11 = 29 (512MB) - 18 (256K)
> +	default 13 if PPC_64K_PAGES	# 13 = 29 (512MB) - 16 (64K)
> +	default 15 if PPC_16K_PAGES 	# 15 = 29 (512MB) - 14 (16K)
> +	default 17			# 17 = 29 (512MB) - 12 (4K)
> +
> +config ARCH_MMAP_RND_COMPAT_BITS_MIN
> +	# Total virtual address space for 32-bit processes is 2^31 (2GB).
> +	# Allow randomisation to consume up to 8MB of address space (2^23).
> +	default 5 if PPC_256K_PAGES	#  5 = 23 (8MB) - 18 (256K)
> +	default 7 if PPC_64K_PAGES	#  7 = 23 (8MB) - 16 (64K)
> +	default 9 if PPC_16K_PAGES	#  9 = 23 (8MB) - 14 (16K)
> +	default 11			# 11 = 23 (8MB) - 12 (4K)
> +
>  config HAVE_SETUP_PER_CPU_AREA
>  	def_bool PPC64
>  
> @@ -120,6 +162,8 @@ config PPC
>  	select HAVE_ARCH_HARDENED_USERCOPY
>  	select HAVE_ARCH_JUMP_LABEL
>  	select HAVE_ARCH_KGDB
> +	select HAVE_ARCH_MMAP_RND_BITS
> +	select HAVE_ARCH_MMAP_RND_COMPAT_BITS	if COMPAT
>  	select HAVE_ARCH_SECCOMP_FILTER
>  	select HAVE_ARCH_TRACEHOOK
>  	select HAVE_CBPF_JIT			if !PPC64
> diff --git a/arch/powerpc/mm/mmap.c b/arch/powerpc/mm/mmap.c
> index a5d9ef59debe..6141cfff634e 100644
> --- a/arch/powerpc/mm/mmap.c
> +++ b/arch/powerpc/mm/mmap.c
> @@ -59,13 +59,14 @@ static inline int mmap_is_legacy(void)
>  
>  unsigned long arch_mmap_rnd(void)
>  {
> -	unsigned long rnd;
> +	unsigned long shift, rnd;
>  
> -	/* 8MB for 32bit, 1GB for 64bit */
> +	shift = mmap_rnd_bits;
> +#ifdef CONFIG_COMPAT
>  	if (is_32bit_task())
> -		rnd = get_random_long() % (1<<(23-PAGE_SHIFT));
> -	else
> -		rnd = get_random_long() % (1UL<<(30-PAGE_SHIFT));
> +		shift = mmap_rnd_compat_bits;
> +#endif
> +	rnd = get_random_long() % (1 << shift);
>  
>  	return rnd << PAGE_SHIFT;
>  }
> -- 
> 2.7.4
Bhupesh Sharma April 21, 2017, 6:49 a.m.
Hi Michael,

Thanks for the v2. It looks good.

On Thu, Apr 20, 2017 at 8:06 PM, Michael Ellerman <mpe@ellerman.id.au> wrote:
> Add powerpc support for mmap_rnd_bits and mmap_rnd_compat_bits, which are two
> sysctls that allow a user to configure the number of bits of randomness used for
> ASLR.
>
> Because of the way the Kconfig for ARCH_MMAP_RND_BITS is defined, we have to
> construct at least the MIN value in Kconfig, vs in a header which would be more
> natural. Given that we just go ahead and do it all in Kconfig.
>
> At least according to the code (the documentation makes no mention of it), the
> value is defined as the number of bits of randomisation *of the page*, not the
> address. This makes some sense, with larger page sizes more of the low bits are
> forced to zero, which would reduce the randomisation if we didn't take the
> PAGE_SIZE into account. However it does mean the min/max values have to change
> depending on the PAGE_SIZE in order to actually limit the amount of address
> space consumed by the randomisation.
>
> The result of that is that we have to define the default values based on both
> 32-bit vs 64-bit, but also the configured PAGE_SIZE. Furthermore now that we
> have 128TB address space support on Book3S, we also have to take that into
> account.
>
> Finally we can wire up the value in arch_mmap_rnd().
>
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
> Signed-off-by: Bhupesh Sharma <bhsharma@redhat.com>
> ---
>  arch/powerpc/Kconfig   | 44 ++++++++++++++++++++++++++++++++++++++++++++
>  arch/powerpc/mm/mmap.c | 11 ++++++-----
>  2 files changed, 50 insertions(+), 5 deletions(-)
>
> v2: Fix the 32-bit MAX value incorrectly using MIN as spotted by Kees.
>
> Kees/Bhupesh, would love a Review/Ack/Tested-by from you, I'll plan to merge
> this later today (Friday) my time.
>
> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> index 97a8bc8a095c..6f0503951e94 100644
> --- a/arch/powerpc/Kconfig
> +++ b/arch/powerpc/Kconfig
> @@ -22,6 +22,48 @@ config MMU
>         bool
>         default y
>
> +config ARCH_MMAP_RND_BITS_MAX
> +       # On Book3S 64, the default virtual address space for 64-bit processes
> +       # is 2^47 (128TB). As a maximum, allow randomisation to consume up to
> +       # 32T of address space (2^45), which should ensure a reasonable gap
> +       # between bottom-up and top-down allocations for applications that
> +       # consume "normal" amounts of address space. Book3S 64 only supports 64K
> +       # and 4K page sizes.
> +       default 29 if PPC_BOOK3S_64 && PPC_64K_PAGES # 29 = 45 (32T) - 16 (64K)
> +       default 33 if PPC_BOOK3S_64                  # 33 = 45 (32T) - 12 (4K)
> +       #
> +       # On all other 64-bit platforms (currently only Book3E), the virtual
> +       # address space is 2^46 (64TB). Allow randomisation to consume up to 16T
> +       # of address space (2^44). Only 4K page sizes are supported.
> +       default 32 if 64BIT     # 32 = 44 (16T) - 12 (4K)
> +       #
> +       # For 32-bit, use the compat values, as they're the same.
> +       default ARCH_MMAP_RND_COMPAT_BITS_MAX
> +
> +config ARCH_MMAP_RND_BITS_MIN
> +       # Allow randomisation to consume up to 1GB of address space (2^30).
> +       default 14 if 64BIT && PPC_64K_PAGES    # 14 = 30 (1GB) - 16 (64K)
> +       default 18 if 64BIT                     # 18 = 30 (1GB) - 12 (4K)
> +       #
> +       # For 32-bit, use the compat values, as they're the same.
> +       default ARCH_MMAP_RND_COMPAT_BITS_MIN
> +
> +config ARCH_MMAP_RND_COMPAT_BITS_MAX
> +       # Total virtual address space for 32-bit processes is 2^31 (2GB).
> +       # Allow randomisation to consume up to 512MB of address space (2^29).
> +       default 11 if PPC_256K_PAGES    # 11 = 29 (512MB) - 18 (256K)
> +       default 13 if PPC_64K_PAGES     # 13 = 29 (512MB) - 16 (64K)
> +       default 15 if PPC_16K_PAGES     # 15 = 29 (512MB) - 14 (16K)
> +       default 17                      # 17 = 29 (512MB) - 12 (4K)
> +
> +config ARCH_MMAP_RND_COMPAT_BITS_MIN
> +       # Total virtual address space for 32-bit processes is 2^31 (2GB).
> +       # Allow randomisation to consume up to 8MB of address space (2^23).
> +       default 5 if PPC_256K_PAGES     #  5 = 23 (8MB) - 18 (256K)
> +       default 7 if PPC_64K_PAGES      #  7 = 23 (8MB) - 16 (64K)
> +       default 9 if PPC_16K_PAGES      #  9 = 23 (8MB) - 14 (16K)
> +       default 11                      # 11 = 23 (8MB) - 12 (4K)
> +
>  config HAVE_SETUP_PER_CPU_AREA
>         def_bool PPC64
>
> @@ -120,6 +162,8 @@ config PPC
>         select HAVE_ARCH_HARDENED_USERCOPY
>         select HAVE_ARCH_JUMP_LABEL
>         select HAVE_ARCH_KGDB
> +       select HAVE_ARCH_MMAP_RND_BITS
> +       select HAVE_ARCH_MMAP_RND_COMPAT_BITS   if COMPAT
>         select HAVE_ARCH_SECCOMP_FILTER
>         select HAVE_ARCH_TRACEHOOK
>         select HAVE_CBPF_JIT                    if !PPC64
> diff --git a/arch/powerpc/mm/mmap.c b/arch/powerpc/mm/mmap.c
> index a5d9ef59debe..6141cfff634e 100644
> --- a/arch/powerpc/mm/mmap.c
> +++ b/arch/powerpc/mm/mmap.c
> @@ -59,13 +59,14 @@ static inline int mmap_is_legacy(void)
>
>  unsigned long arch_mmap_rnd(void)
>  {
> -       unsigned long rnd;
> +       unsigned long shift, rnd;
>
> -       /* 8MB for 32bit, 1GB for 64bit */
> +       shift = mmap_rnd_bits;
> +#ifdef CONFIG_COMPAT
>         if (is_32bit_task())
> -               rnd = get_random_long() % (1<<(23-PAGE_SHIFT));
> -       else
> -               rnd = get_random_long() % (1UL<<(30-PAGE_SHIFT));
> +               shift = mmap_rnd_compat_bits;
> +#endif
> +       rnd = get_random_long() % (1 << shift);
>
>         return rnd << PAGE_SHIFT;
>  }
> --
> 2.7.4

I used a simple program to dump the load address used for a ASLR elf
on the RHEL PPC64LE platform using the above patch:

1. Create a test PIE program which shows its own memory map:

$ cat show_mmap_pie.c
#include <stdlib.h>
#include <stdio.h>

int main(void){
    char command[1024];
    sprintf(command,"cat /proc/%d/maps",getpid());
    system(command);
    return 0;
}

2. Compile it as a PIE:

$ gcc -o show_mmap_pie -fpie -pie show_mmap_pie.c

3. After applying the patch, we can increase the randomization range
on  RHEL PPC64LE system with 64K page size:

# cat /proc/sys/vm/mmap_rnd_bits
14

# ./show_mmap_pie

4c050000-4c060000 r-xp 00000000 fd:00 102212985
  /root/show_mmap_pie
4c060000-4c070000 r--p 00000000 fd:00 102212985
  /root/show_mmap_pie
4c070000-4c080000 rw-p 00010000 fd:00 102212985
  /root/show_mmap_pie
7fffa0460000-7fffa0620000 r-xp 00000000 fd:00 33617825
  /usr/lib64/libc-2.17.so
7fffa0620000-7fffa0630000 r--p 001b0000 fd:00 33617825
  /usr/lib64/libc-2.17.so
7fffa0630000-7fffa0640000 rw-p 001c0000 fd:00 33617825
  /usr/lib64/libc-2.17.so
7fffa0650000-7fffa0670000 r-xp 00000000 00:00 0                          [vdso]
7fffa0670000-7fffa06a0000 r-xp 00000000 fd:00 33617818
  /usr/lib64/ld-2.17.so
7fffa06a0000-7fffa06b0000 r--p 00020000 fd:00 33617818
  /usr/lib64/ld-2.17.so
7fffa06b0000-7fffa06c0000 rw-p 00030000 fd:00 33617818
  /usr/lib64/ld-2.17.so
7fffe3fe0000-7fffe4010000 rw-p 00000000 00:00 0                          [stack]

# echo 28 > /proc/sys/vm/mmap_rnd_bits

# ./show_mmap_pie
202e31d0000-202e31e0000 r-xp 00000000 fd:00 102212985
  /root/show_mmap_pie
202e31e0000-202e31f0000 r--p 00000000 fd:00 102212985
  /root/show_mmap_pie
202e31f0000-202e3200000 rw-p 00010000 fd:00 102212985
  /root/show_mmap_pie
7ef112640000-7ef112800000 r-xp 00000000 fd:00 33617825
  /usr/lib64/libc-2.17.so
7ef112800000-7ef112810000 r--p 001b0000 fd:00 33617825
  /usr/lib64/libc-2.17.so
7ef112810000-7ef112820000 rw-p 001c0000 fd:00 33617825
  /usr/lib64/libc-2.17.so
7ef112830000-7ef112850000 r-xp 00000000 00:00 0                          [vdso]
7ef112850000-7ef112880000 r-xp 00000000 fd:00 33617818
  /usr/lib64/ld-2.17.so
7ef112880000-7ef112890000 r--p 00020000 fd:00 33617818
  /usr/lib64/ld-2.17.so
7ef112890000-7ef1128a0000 rw-p 00030000 fd:00 33617818
  /usr/lib64/ld-2.17.so
7fffd3070000-7fffd30a0000 rw-p 00000000 00:00 0                          [stack]

So, you can add my Tested-by for this patch as well.

Regards,
Bhupesh
Michael Ellerman April 23, 2017, 11:53 a.m.
On Thu, 2017-04-20 at 14:36:20 UTC, Michael Ellerman wrote:
> Add powerpc support for mmap_rnd_bits and mmap_rnd_compat_bits, which are two
> sysctls that allow a user to configure the number of bits of randomness used for
> ASLR.
> 
> Because of the way the Kconfig for ARCH_MMAP_RND_BITS is defined, we have to
> construct at least the MIN value in Kconfig, vs in a header which would be more
> natural. Given that we just go ahead and do it all in Kconfig.
> 
> At least according to the code (the documentation makes no mention of it), the
> value is defined as the number of bits of randomisation *of the page*, not the
> address. This makes some sense, with larger page sizes more of the low bits are
> forced to zero, which would reduce the randomisation if we didn't take the
> PAGE_SIZE into account. However it does mean the min/max values have to change
> depending on the PAGE_SIZE in order to actually limit the amount of address
> space consumed by the randomisation.
> 
> The result of that is that we have to define the default values based on both
> 32-bit vs 64-bit, but also the configured PAGE_SIZE. Furthermore now that we
> have 128TB address space support on Book3S, we also have to take that into
> account.
> 
> Finally we can wire up the value in arch_mmap_rnd().
> 
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
> Signed-off-by: Bhupesh Sharma <bhsharma@redhat.com>
> Reviewed-by: Kees Cook <keescook@chromium.org>
> Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>

Applied to powerpc next.

https://git.kernel.org/powerpc/c/9fea59bd7ca541e5d0851f0b6dbca8

cheers
Balbir Singh April 24, 2017, 1:02 a.m.
On Fri, 2017-04-21 at 00:36 +1000, Michael Ellerman wrote:
> Add powerpc support for mmap_rnd_bits and mmap_rnd_compat_bits, which are two
> sysctls that allow a user to configure the number of bits of randomness used for
> ASLR.
> 
> Because of the way the Kconfig for ARCH_MMAP_RND_BITS is defined, we have to
> construct at least the MIN value in Kconfig, vs in a header which would be more
> natural. Given that we just go ahead and do it all in Kconfig.
> 
> At least according to the code (the documentation makes no mention of it), the
> value is defined as the number of bits of randomisation *of the page*, not the
> address. This makes some sense, with larger page sizes more of the low bits are
> forced to zero, which would reduce the randomisation if we didn't take the
> PAGE_SIZE into account. However it does mean the min/max values have to change
> depending on the PAGE_SIZE in order to actually limit the amount of address
> space consumed by the randomisation.
> 
> The result of that is that we have to define the default values based on both
> 32-bit vs 64-bit, but also the configured PAGE_SIZE. Furthermore now that we
> have 128TB address space support on Book3S, we also have to take that into
> account.

Could we please suggest that this should not be sent to stable or back-ported
as the 128T default is new?

> 
> Finally we can wire up the value in arch_mmap_rnd().
> 
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
> Signed-off-by: Bhupesh Sharma <bhsharma@redhat.com>
> ---
>  arch/powerpc/Kconfig   | 44 ++++++++++++++++++++++++++++++++++++++++++++
>  arch/powerpc/mm/mmap.c | 11 ++++++-----
>  2 files changed, 50 insertions(+), 5 deletions(-)
> 
> v2: Fix the 32-bit MAX value incorrectly using MIN as spotted by Kees.
> 
> Kees/Bhupesh, would love a Review/Ack/Tested-by from you, I'll plan to merge
> this later today (Friday) my time.
> 
> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> index 97a8bc8a095c..6f0503951e94 100644
> --- a/arch/powerpc/Kconfig
> +++ b/arch/powerpc/Kconfig
> @@ -22,6 +22,48 @@ config MMU
>  	bool
>  	default y
>  
> +config ARCH_MMAP_RND_BITS_MAX
> +	# On Book3S 64, the default virtual address space for 64-bit processes
> +	# is 2^47 (128TB). As a maximum, allow randomisation to consume up to
> +	# 32T of address space (2^45), which should ensure a reasonable gap
> +	# between bottom-up and top-down allocations for applications that
> +	# consume "normal" amounts of address space. Book3S 64 only supports 64K
> +	# and 4K page sizes.
> +	default 29 if PPC_BOOK3S_64 && PPC_64K_PAGES # 29 = 45 (32T) - 16 (64K)
> +	default 33 if PPC_BOOK3S_64		     # 33 = 45 (32T) - 12 (4K)
> +	#
> +	# On all other 64-bit platforms (currently only Book3E), the virtual
> +	# address space is 2^46 (64TB). Allow randomisation to consume up to 16T
> +	# of address space (2^44). Only 4K page sizes are supported.
> +	default 32 if 64BIT	# 32 = 44 (16T) - 12 (4K)
> +	#
> +	# For 32-bit, use the compat values, as they're the same.
> +	default ARCH_MMAP_RND_COMPAT_BITS_MAX
> +
> +config ARCH_MMAP_RND_BITS_MIN
> +	# Allow randomisation to consume up to 1GB of address space (2^30).
> +	default 14 if 64BIT && PPC_64K_PAGES	# 14 = 30 (1GB) - 16 (64K)
> +	default 18 if 64BIT			# 18 = 30 (1GB) - 12 (4K)
> +	#
> +	# For 32-bit, use the compat values, as they're the same.
> +	default ARCH_MMAP_RND_COMPAT_BITS_MIN
> +
> +config ARCH_MMAP_RND_COMPAT_BITS_MAX
> +	# Total virtual address space for 32-bit processes is 2^31 (2GB).
> +	# Allow randomisation to consume up to 512MB of address space (2^29).
> +	default 11 if PPC_256K_PAGES	# 11 = 29 (512MB) - 18 (256K)
> +	default 13 if PPC_64K_PAGES	# 13 = 29 (512MB) - 16 (64K)
> +	default 15 if PPC_16K_PAGES 	# 15 = 29 (512MB) - 14 (16K)
> +	default 17			# 17 = 29 (512MB) - 12 (4K)
> +
> +config ARCH_MMAP_RND_COMPAT_BITS_MIN
> +	# Total virtual address space for 32-bit processes is 2^31 (2GB).
> +	# Allow randomisation to consume up to 8MB of address space (2^23).
> +	default 5 if PPC_256K_PAGES	#  5 = 23 (8MB) - 18 (256K)
> +	default 7 if PPC_64K_PAGES	#  7 = 23 (8MB) - 16 (64K)
> +	default 9 if PPC_16K_PAGES	#  9 = 23 (8MB) - 14 (16K)
> +	default 11			# 11 = 23 (8MB) - 12 (4K)
> +
>  config HAVE_SETUP_PER_CPU_AREA
>  	def_bool PPC64
>  
> @@ -120,6 +162,8 @@ config PPC
>  	select HAVE_ARCH_HARDENED_USERCOPY
>  	select HAVE_ARCH_JUMP_LABEL
>  	select HAVE_ARCH_KGDB
> +	select HAVE_ARCH_MMAP_RND_BITS
> +	select HAVE_ARCH_MMAP_RND_COMPAT_BITS	if COMPAT
>  	select HAVE_ARCH_SECCOMP_FILTER
>  	select HAVE_ARCH_TRACEHOOK
>  	select HAVE_CBPF_JIT			if !PPC64
> diff --git a/arch/powerpc/mm/mmap.c b/arch/powerpc/mm/mmap.c
> index a5d9ef59debe..6141cfff634e 100644
> --- a/arch/powerpc/mm/mmap.c
> +++ b/arch/powerpc/mm/mmap.c
> @@ -59,13 +59,14 @@ static inline int mmap_is_legacy(void)
>  
>  unsigned long arch_mmap_rnd(void)
>  {
> -	unsigned long rnd;
> +	unsigned long shift, rnd;
>  
> -	/* 8MB for 32bit, 1GB for 64bit */
> +	shift = mmap_rnd_bits;
> +#ifdef CONFIG_COMPAT
>  	if (is_32bit_task())
> -		rnd = get_random_long() % (1<<(23-PAGE_SHIFT));
> -	else
> -		rnd = get_random_long() % (1UL<<(30-PAGE_SHIFT));
> +		shift = mmap_rnd_compat_bits;
> +#endif
> +	rnd = get_random_long() % (1 << shift);
>

Nitpick, 1 should be 1UL?
  
>  	return rnd << PAGE_SHIFT;
>  }

Acked-by: Balbir Singh <bsingharora@gmail.com>
Michael Ellerman April 24, 2017, 2:29 p.m.
Balbir Singh <bsingharora@gmail.com> writes:

> On Fri, 2017-04-21 at 00:36 +1000, Michael Ellerman wrote:
>> Add powerpc support for mmap_rnd_bits and mmap_rnd_compat_bits, which are two
>> sysctls that allow a user to configure the number of bits of randomness used for
>> ASLR.
...
>
> Could we please suggest that this should not be sent to stable or back-ported
> as the 128T default is new?

I'm not sure I follow. I didn't tag it for stable. Do you mean we should
explicitly mark it as not-for-stable?

If someone sends it to stable@vger I'll be pinged before it goes in and
nak it, if someone wants to backport it (incorrectly) to their own tree
then good luck to them :)

>> diff --git a/arch/powerpc/mm/mmap.c b/arch/powerpc/mm/mmap.c
>> index a5d9ef59debe..6141cfff634e 100644
>> --- a/arch/powerpc/mm/mmap.c
>> +++ b/arch/powerpc/mm/mmap.c
>> @@ -59,13 +59,14 @@ static inline int mmap_is_legacy(void)
>>  
>>  unsigned long arch_mmap_rnd(void)
>>  {
>> -	unsigned long rnd;
>> +	unsigned long shift, rnd;
>>  
>> -	/* 8MB for 32bit, 1GB for 64bit */
>> +	shift = mmap_rnd_bits;
>> +#ifdef CONFIG_COMPAT
>>  	if (is_32bit_task())
>> -		rnd = get_random_long() % (1<<(23-PAGE_SHIFT));
>> -	else
>> -		rnd = get_random_long() % (1UL<<(30-PAGE_SHIFT));
>> +		shift = mmap_rnd_compat_bits;
>> +#endif
>> +	rnd = get_random_long() % (1 << shift);
>
> Nitpick, 1 should be 1UL?

No, shift can only be 29 at most IIRC?

But it's a bit fragile, so I'll change it.

cheers
Kees Cook April 24, 2017, 5:56 p.m.
On Mon, Apr 24, 2017 at 7:29 AM, Michael Ellerman <mpe@ellerman.id.au> wrote:
> Balbir Singh <bsingharora@gmail.com> writes:
>
>> On Fri, 2017-04-21 at 00:36 +1000, Michael Ellerman wrote:
>>> Add powerpc support for mmap_rnd_bits and mmap_rnd_compat_bits, which are two
>>> sysctls that allow a user to configure the number of bits of randomness used for
>>> ASLR.
> ...
>>
>> Could we please suggest that this should not be sent to stable or back-ported
>> as the 128T default is new?
>
> I'm not sure I follow. I didn't tag it for stable. Do you mean we should
> explicitly mark it as not-for-stable?
>
> If someone sends it to stable@vger I'll be pinged before it goes in and
> nak it, if someone wants to backport it (incorrectly) to their own tree
> then good luck to them :)
>
>>> diff --git a/arch/powerpc/mm/mmap.c b/arch/powerpc/mm/mmap.c
>>> index a5d9ef59debe..6141cfff634e 100644
>>> --- a/arch/powerpc/mm/mmap.c
>>> +++ b/arch/powerpc/mm/mmap.c
>>> @@ -59,13 +59,14 @@ static inline int mmap_is_legacy(void)
>>>
>>>  unsigned long arch_mmap_rnd(void)
>>>  {
>>> -    unsigned long rnd;
>>> +    unsigned long shift, rnd;
>>>
>>> -    /* 8MB for 32bit, 1GB for 64bit */
>>> +    shift = mmap_rnd_bits;
>>> +#ifdef CONFIG_COMPAT
>>>      if (is_32bit_task())
>>> -            rnd = get_random_long() % (1<<(23-PAGE_SHIFT));
>>> -    else
>>> -            rnd = get_random_long() % (1UL<<(30-PAGE_SHIFT));
>>> +            shift = mmap_rnd_compat_bits;
>>> +#endif
>>> +    rnd = get_random_long() % (1 << shift);
>>
>> Nitpick, 1 should be 1UL?

Nice catch!

> No, shift can only be 29 at most IIRC?

The largest value in the kconfigs is 33?

> But it's a bit fragile, so I'll change it.

Thanks!

-Kees
Michael Ellerman April 24, 2017, 10:44 p.m.
Kees Cook <keescook@chromium.org> writes:
> On Mon, Apr 24, 2017 at 7:29 AM, Michael Ellerman <mpe@ellerman.id.au> wrote:
>> Balbir Singh <bsingharora@gmail.com> writes:
>>>> diff --git a/arch/powerpc/mm/mmap.c b/arch/powerpc/mm/mmap.c
>>>> index a5d9ef59debe..6141cfff634e 100644
>>>> --- a/arch/powerpc/mm/mmap.c
>>>> +++ b/arch/powerpc/mm/mmap.c
>>>> @@ -59,13 +59,14 @@ static inline int mmap_is_legacy(void)
>>>>
>>>>  unsigned long arch_mmap_rnd(void)
>>>>  {
>>>> -    unsigned long rnd;
>>>> +    unsigned long shift, rnd;
>>>>
>>>> -    /* 8MB for 32bit, 1GB for 64bit */
>>>> +    shift = mmap_rnd_bits;
>>>> +#ifdef CONFIG_COMPAT
>>>>      if (is_32bit_task())
>>>> -            rnd = get_random_long() % (1<<(23-PAGE_SHIFT));
>>>> -    else
>>>> -            rnd = get_random_long() % (1UL<<(30-PAGE_SHIFT));
>>>> +            shift = mmap_rnd_compat_bits;
>>>> +#endif
>>>> +    rnd = get_random_long() % (1 << shift);
>>>
>>> Nitpick, 1 should be 1UL?
>
> Nice catch!
>
>> No, shift can only be 29 at most IIRC?
>
> The largest value in the kconfigs is 33?

Yeah you're right, for the 4K page kernel it can be 33.

Will fix.

cheers
Balbir Singh April 25, 2017, 12:56 a.m.
On Tue, 2017-04-25 at 00:29 +1000, Michael Ellerman wrote:
> Balbir Singh <bsingharora@gmail.com> writes:
> 
> > On Fri, 2017-04-21 at 00:36 +1000, Michael Ellerman wrote:
> > > Add powerpc support for mmap_rnd_bits and mmap_rnd_compat_bits, which are two
> > > sysctls that allow a user to configure the number of bits of randomness used for
> > > ASLR.
> 
> ...
> > 
> > Could we please suggest that this should not be sent to stable or back-ported
> > as the 128T default is new?
> 
> I'm not sure I follow. I didn't tag it for stable. Do you mean we should
> explicitly mark it as not-for-stable?
> 

Yeah.. I am concerned someone might backport it without looking at
the dependencies :)

> If someone sends it to stable@vger I'll be pinged before it goes in and
> nak it, if someone wants to backport it (incorrectly) to their own tree
> then good luck to them :)

Fair enough

<snip>

> > > +	rnd = get_random_long() % (1 << shift);
> > 
> > Nitpick, 1 should be 1UL?
> 
> No, shift can only be 29 at most IIRC?
> 
> But it's a bit fragile, so I'll change it.
> 
> cheers

Cheers and I agree with Kees, a lot of the arch_mmap_rnd() code is beginning
to look similar :)

Balbir Singh

Patch hide | download patch | download mbox

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 97a8bc8a095c..6f0503951e94 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -22,6 +22,48 @@  config MMU
 	bool
 	default y
 
+config ARCH_MMAP_RND_BITS_MAX
+	# On Book3S 64, the default virtual address space for 64-bit processes
+	# is 2^47 (128TB). As a maximum, allow randomisation to consume up to
+	# 32T of address space (2^45), which should ensure a reasonable gap
+	# between bottom-up and top-down allocations for applications that
+	# consume "normal" amounts of address space. Book3S 64 only supports 64K
+	# and 4K page sizes.
+	default 29 if PPC_BOOK3S_64 && PPC_64K_PAGES # 29 = 45 (32T) - 16 (64K)
+	default 33 if PPC_BOOK3S_64		     # 33 = 45 (32T) - 12 (4K)
+	#
+	# On all other 64-bit platforms (currently only Book3E), the virtual
+	# address space is 2^46 (64TB). Allow randomisation to consume up to 16T
+	# of address space (2^44). Only 4K page sizes are supported.
+	default 32 if 64BIT	# 32 = 44 (16T) - 12 (4K)
+	#
+	# For 32-bit, use the compat values, as they're the same.
+	default ARCH_MMAP_RND_COMPAT_BITS_MAX
+
+config ARCH_MMAP_RND_BITS_MIN
+	# Allow randomisation to consume up to 1GB of address space (2^30).
+	default 14 if 64BIT && PPC_64K_PAGES	# 14 = 30 (1GB) - 16 (64K)
+	default 18 if 64BIT			# 18 = 30 (1GB) - 12 (4K)
+	#
+	# For 32-bit, use the compat values, as they're the same.
+	default ARCH_MMAP_RND_COMPAT_BITS_MIN
+
+config ARCH_MMAP_RND_COMPAT_BITS_MAX
+	# Total virtual address space for 32-bit processes is 2^31 (2GB).
+	# Allow randomisation to consume up to 512MB of address space (2^29).
+	default 11 if PPC_256K_PAGES	# 11 = 29 (512MB) - 18 (256K)
+	default 13 if PPC_64K_PAGES	# 13 = 29 (512MB) - 16 (64K)
+	default 15 if PPC_16K_PAGES 	# 15 = 29 (512MB) - 14 (16K)
+	default 17			# 17 = 29 (512MB) - 12 (4K)
+
+config ARCH_MMAP_RND_COMPAT_BITS_MIN
+	# Total virtual address space for 32-bit processes is 2^31 (2GB).
+	# Allow randomisation to consume up to 8MB of address space (2^23).
+	default 5 if PPC_256K_PAGES	#  5 = 23 (8MB) - 18 (256K)
+	default 7 if PPC_64K_PAGES	#  7 = 23 (8MB) - 16 (64K)
+	default 9 if PPC_16K_PAGES	#  9 = 23 (8MB) - 14 (16K)
+	default 11			# 11 = 23 (8MB) - 12 (4K)
+
 config HAVE_SETUP_PER_CPU_AREA
 	def_bool PPC64
 
@@ -120,6 +162,8 @@  config PPC
 	select HAVE_ARCH_HARDENED_USERCOPY
 	select HAVE_ARCH_JUMP_LABEL
 	select HAVE_ARCH_KGDB
+	select HAVE_ARCH_MMAP_RND_BITS
+	select HAVE_ARCH_MMAP_RND_COMPAT_BITS	if COMPAT
 	select HAVE_ARCH_SECCOMP_FILTER
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_CBPF_JIT			if !PPC64
diff --git a/arch/powerpc/mm/mmap.c b/arch/powerpc/mm/mmap.c
index a5d9ef59debe..6141cfff634e 100644
--- a/arch/powerpc/mm/mmap.c
+++ b/arch/powerpc/mm/mmap.c
@@ -59,13 +59,14 @@  static inline int mmap_is_legacy(void)
 
 unsigned long arch_mmap_rnd(void)
 {
-	unsigned long rnd;
+	unsigned long shift, rnd;
 
-	/* 8MB for 32bit, 1GB for 64bit */
+	shift = mmap_rnd_bits;
+#ifdef CONFIG_COMPAT
 	if (is_32bit_task())
-		rnd = get_random_long() % (1<<(23-PAGE_SHIFT));
-	else
-		rnd = get_random_long() % (1UL<<(30-PAGE_SHIFT));
+		shift = mmap_rnd_compat_bits;
+#endif
+	rnd = get_random_long() % (1 << shift);
 
 	return rnd << PAGE_SHIFT;
 }