From: Daniel Cashman <hidden> Date: 2015-11-18 23:20:16
From: dcashman <redacted>
Address Space Layout Randomization (ASLR) provides a barrier to exploitation of user-space processes in the presence of security vulnerabilities by making it more difficult to find desired code/data which could help an attack. This is done by adding a random offset to the location of regions in the process address space, with a greater range of potential offset values corresponding to better protection/a larger search-space for brute force, but also to greater potential for fragmentation.
The offset added to the mmap_base address, which provides the basis for the majority of the mappings for a process, is set once on process exec in arch_pick_mmap_layout() and is done via hard-coded per-arch values, which reflect, hopefully, the best compromise for all systems. The trade-off between increased entropy in the offset value generation and the corresponding increased variability in address space fragmentation is not absolute, however, and some platforms may tolerate higher amounts of entropy. This patch introduces both new Kconfig values and a sysctl interface which may be used to change the amount of entropy used for offset generation on a system.
The direct motivation for this change was in response to the libstagefright vulnerabilities that affected Android, specifically to information provided by Google's project zero at:
http://googleprojectzero.blogspot.com/2015/09/stagefrightened.html
The attack presented therein, by Google's project zero, specifically targeted the limited randomness used to generate the offset added to the mmap_base address in order to craft a brute-force-based attack. Concretely, the attack was against the mediaserver process, which was limited to respawning every 5 seconds, on an arm device. The hard-coded 8 bits used resulted in an average expected success rate of defeating the mmap ASLR after just over 10 minutes (128 tries at 5 seconds a piece). With this patch, and an accompanying increase in the entropy value to 16 bits, the same attack would take an average expected time of over 45 hours (32768 tries), which makes it both less feasible and more likely to be noticed.
The introduced Kconfig and sysctl options are limited by per-arch minimum and maximum values, the minimum of which was chosen to match the current hard-coded value and the maximum of which was chosen so as to give the greatest flexibility without generating an invalid mmap_base address, generally a 3-4 bits less than the number of bits in the user-space accessible virtual address space.
When decided whether or not to change the default value, a system developer should consider that mmap_base address could be placed anywhere up to 2^(value) bits away from the non-randomized location, which would introduce variable-sized areas above and below the mmap_base address such that the maximum vm_area_struct size may be reduced, preventing very large allocations.
Changes in v3:
* moved sysctl from /proc/sys/kernel to /proc/sys/vm
* added to arch/x86 (both 32 and 64 bit)
* added to arch/arm64
* added ability for arch to specify default value in between max - min
dcashman (4):
mm: mmap: Add new /proc tunable for mmap_base ASLR.
arm: mm: support ARCH_MMAP_RND_BITS.
arm64: mm: support ARCH_MMAP_RND_BITS.
x86: mm: support ARCH_MMAP_RND_BITS.
Documentation/sysctl/vm.txt | 29 ++++++++++++++++++++
arch/Kconfig | 64 +++++++++++++++++++++++++++++++++++++++++++++
arch/arm/Kconfig | 10 +++++++
arch/arm/mm/mmap.c | 3 +--
arch/arm64/Kconfig | 23 ++++++++++++++++
arch/arm64/mm/mmap.c | 6 +++--
arch/x86/Kconfig | 16 ++++++++++++
arch/x86/mm/mmap.c | 12 ++++-----
include/linux/mm.h | 11 ++++++++
kernel/sysctl.c | 22 ++++++++++++++++
mm/mmap.c | 12 +++++++++
11 files changed, 198 insertions(+), 10 deletions(-)
--
2.6.0.rc2.230.g3dd15c0
From: Daniel Cashman <hidden> Date: 2015-11-18 23:20:22
From: dcashman <redacted>
arm: arch_mmap_rnd() uses a hard-code value of 8 to generate the
random offset for the mmap base address. This value represents a
compromise between increased ASLR effectiveness and avoiding
address-space fragmentation. Replace it with a Kconfig option, which
is sensibly bounded, so that platform developers may choose where to
place this compromise. Keep 8 as the minimum acceptable value.
Signed-off-by: Daniel Cashman <redacted>
---
arch/arm/Kconfig | 10 ++++++++++
arch/arm/mm/mmap.c | 3 +--
2 files changed, 11 insertions(+), 2 deletions(-)
@@ -306,6 +307,15 @@ config MMUSelectifyouwantMMU-basedvirtualisedaddressingspacesupportbypagedmemorymanagement.Ifunsure,say'Y'.+configARCH_MMAP_RND_BITS_MIN+default8++configARCH_MMAP_RND_BITS_MAX+default14ifMMU&&PAGE_OFFSET=0x40000000+default15ifMMU&&PAGE_OFFSET=0x80000000+default16ifMMU+default8+## The "ARM system type" choice list is ordered alphabetically by option# text. Please add new entries in the option alphabetic order.
@@ -173,8 +173,7 @@ unsigned long arch_mmap_rnd(void){unsignedlongrnd;-/* 8 bits of randomness in 20 address space bits */-rnd=(unsignedlong)get_random_int()%(1<<8);+rnd=(unsignedlong)get_random_int()%(1<<mmap_rnd_bits);returnrnd<<PAGE_SHIFT;}
From: Daniel Cashman <hidden> Date: 2015-11-18 23:20:32
From: dcashman <redacted>
x86: arch_mmap_rnd() uses hard-coded values, 8 for 32-bit and 28 for
64-bit, to generate the random offset for the mmap base address.
This value represents a compromise between increased ASLR
effectiveness and avoiding address-space fragmentation. Replace it
with a Kconfig option, which is sensibly bounded, so that platform
developers may choose where to place this compromise. Keep default
values as new minimums.
Signed-off-by: Daniel Cashman <redacted>
---
arch/x86/Kconfig | 16 ++++++++++++++++
arch/x86/mm/mmap.c | 12 ++++++------
2 files changed, 22 insertions(+), 6 deletions(-)
From: Daniel Cashman <hidden> Date: 2015-11-18 23:21:08
From: dcashman <redacted>
arm64: arch_mmap_rnd() uses STACK_RND_MASK to generate the
random offset for the mmap base address. This value represents a
compromise between increased ASLR effectiveness and avoiding
address-space fragmentation. Replace it with a Kconfig option, which
is sensibly bounded, so that platform developers may choose where to
place this compromise. Keep default values as new minimums.
Signed-off-by: Daniel Cashman <redacted>
---
arch/arm64/Kconfig | 23 +++++++++++++++++++++++
arch/arm64/mm/mmap.c | 6 ++++--
2 files changed, 27 insertions(+), 2 deletions(-)
From: Daniel Cashman <hidden> Date: 2015-11-18 23:21:31
From: dcashman <redacted>
ASLR currently only uses 8 bits to generate the random offset for the
mmap base address on 32 bit architectures. This value was chosen to
prevent a poorly chosen value from dividing the address space in such
a way as to prevent large allocations. This may not be an issue on all
platforms. Allow the specification of a minimum number of bits so that
platforms desiring greater ASLR protection may determine where to place
the trade-off.
Signed-off-by: Daniel Cashman <redacted>
---
Documentation/sysctl/vm.txt | 29 ++++++++++++++++++++
arch/Kconfig | 64 +++++++++++++++++++++++++++++++++++++++++++++
include/linux/mm.h | 11 ++++++++
kernel/sysctl.c | 22 ++++++++++++++++
mm/mmap.c | 12 +++++++++
5 files changed, 138 insertions(+)
@@ -42,6 +42,8 @@ Currently, these files are in /proc/sys/vm: - min_slab_ratio - min_unmapped_ratio - mmap_min_addr+- mmap_rnd_bits+- mmap_rnd_compat_bits - nr_hugepages - nr_overcommit_hugepages - nr_trim_pages (only if CONFIG_MMU=n)
@@ -485,6 +487,33 @@ against future potential kernel bugs. ==============================================================+mmap_rnd_bits:++This value can be used to select the number of bits to use to+determine the random offset to the base address of vma regions+resulting from mmap allocations on architectures which support+tuning address space randomization. This value will be bounded+by the architecture's minimum and maximum supported values.++This value can be changed after boot using the+/proc/sys/kernel/mmap_rnd_bits tunable++==============================================================++mmap_rnd_compat_bits:++This value can be used to select the number of bits to use to+determine the random offset to the base address of vma regions+resulting from mmap allocations for applications run in+compatibility mode on architectures which support tuning address+space randomization. This value will be bounded by the+architecture's minimum and maximum supported values.++This value can be changed after boot using the+/proc/sys/kernel/mmap_rnd_compat_bits tunable++==============================================================+ nr_hugepages Change the minimum size of the hugepage pool.
@@ -511,6 +511,70 @@ config ARCH_HAS_ELF_RANDOMIZE-arch_mmap_rnd()-arch_randomize_brk()+configHAVE_ARCH_MMAP_RND_BITS+bool+help+Anarchshouldselectthissymbolifitsupportssettingavariable+numberofbitsforuseinestablishingthebaseaddressformmap+allocationsandprovidesvaluesforboth:+-ARCH_MMAP_RND_BITS_MIN+-ARCH_MMAP_RND_BITS_MAX++configARCH_MMAP_RND_BITS_MIN+int++configARCH_MMAP_RND_BITS_MAX+int++configARCH_MMAP_RND_BITS_DEFAULT+int++configARCH_MMAP_RND_BITS+int"Number of bits to use for ASLR of mmap base address"ifEXPERT+rangeARCH_MMAP_RND_BITS_MINARCH_MMAP_RND_BITS_MAX+defaultARCH_MMAP_RND_BITS_DEFAULTifARCH_MMAP_RND_BITS_DEFAULT+defaultARCH_MMAP_RND_BITS_MIN+depends onHAVE_ARCH_MMAP_RND_BITS+help+Thisvaluecanbeusedtoselectthenumberofbitstouseto+determinetherandomoffsettothebaseaddressofvmaregions+resultingfrommmapallocations.Thisvaluewillbebounded+bythearchitecture'sminimumandmaximumsupportedvalues.++Thisvaluecanbechangedafterbootusingthe+/proc/sys/kernel/mmap_rnd_bitstunable++configHAVE_ARCH_MMAP_RND_COMPAT_BITS+bool+help+Anarchshouldselectthissymbolifitsupportsrunningapplications+incompatibilitymode,supportssettingavariablenumberofbitsfor+useinestablishingthebaseaddressformmapallocations,and+providesvaluesforboth:+-ARCH_MMAP_RND_COMPAT_BITS_MIN+-ARCH_MMAP_RND_COMPAT_BITS_MAX++configARCH_MMAP_RND_COMPAT_BITS_MIN+int++configARCH_MMAP_RND_COMPAT_BITS_MAX+int++configARCH_MMAP_RND_COMPAT_BITS+int"Number of bits to use for ASLR of mmap base address for compatible applications"ifEXPERT+rangeARCH_MMAP_RND_COMPAT_BITS_MINARCH_MMAP_RND_COMPAT_BITS_MAX+defaultARCH_MMAP_RND_COMPAT_BITS_MIN+depends onHAVE_ARCH_MMAP_RND_COMPAT_BITS+help+Thisvaluecanbeusedtoselectthenumberofbitstouseto+determinetherandomoffsettothebaseaddressofvmaregions+resultingfrommmapallocationsforcompatibleapplicationsThis+valuewillbeboundedbythearchitecture'sminimumandmaximum+supportedvalues.++Thisvaluecanbechangedafterbootusingthe+/proc/sys/kernel/mmap_rnd_compat_bitstunable+configHAVE_COPY_THREAD_TLSboolhelp
From: Daniel Cashman <hidden> Date: 2015-11-19 00:14:20
On 11/18/2015 03:20 PM, Daniel Cashman wrote:
==============================================================
+mmap_rnd_bits:
+
+This value can be used to select the number of bits to use to
+determine the random offset to the base address of vma regions
+resulting from mmap allocations on architectures which support
+tuning address space randomization. This value will be bounded
+by the architecture's minimum and maximum supported values.
+
+This value can be changed after boot using the
+/proc/sys/kernel/mmap_rnd_bits tunable
+
+==============================================================
+
+mmap_rnd_compat_bits:
+
+This value can be used to select the number of bits to use to
+determine the random offset to the base address of vma regions
+resulting from mmap allocations for applications run in
+compatibility mode on architectures which support tuning address
+space randomization. This value will be bounded by the
+architecture's minimum and maximum supported values.
+
+This value can be changed after boot using the
+/proc/sys/kernel/mmap_rnd_compat_bits tunable
+
+==============================================================
As Kees pointed out in my erroneously sent (missing v3 prefix)
patch-set: the /proc/sys/kernel/ entries were not changed to reflect the
move to /proc/sys/vm/.
From: Will Deacon <hidden> Date: 2015-11-23 15:05:08
On Wed, Nov 18, 2015 at 03:20:07PM -0800, Daniel Cashman wrote:
quoted hunk
From: dcashman <redacted>
arm64: arch_mmap_rnd() uses STACK_RND_MASK to generate the
random offset for the mmap base address. This value represents a
compromise between increased ASLR effectiveness and avoiding
address-space fragmentation. Replace it with a Kconfig option, which
is sensibly bounded, so that platform developers may choose where to
place this compromise. Keep default values as new minimums.
Signed-off-by: Daniel Cashman <redacted>
---
arch/arm64/Kconfig | 23 +++++++++++++++++++++++
arch/arm64/mm/mmap.c | 6 ++++--
2 files changed, 27 insertions(+), 2 deletions(-)
FYI: we now support 16k pages too, so this might need updating. It would
be much nicer if this was somehow computed rather than have the results
all open-coded like this.
Will
From: Daniel Cashman <hidden> Date: 2015-11-23 18:55:21
On 11/23/2015 07:04 AM, Will Deacon wrote:
On Wed, Nov 18, 2015 at 03:20:07PM -0800, Daniel Cashman wrote:
quoted
+config ARCH_MMAP_RND_BITS_MAX
+ default 20 if ARM64_64K_PAGES && ARCH_VA_BITS=39
+ default 24 if ARCH_VA_BITS=39
+ default 23 if ARM64_64K_PAGES && ARCH_VA_BITS=42
+ default 27 if ARCH_VA_BITS=42
+ default 29 if ARM64_64K_PAGES && ARCH_VA_BITS=48
+ default 33 if ARCH_VA_BITS=48
+ default 15 if ARM64_64K_PAGES
+ default 19
+
+config ARCH_MMAP_RND_COMPAT_BITS_MIN
+ default 7 if ARM64_64K_PAGES
+ default 11
FYI: we now support 16k pages too, so this might need updating. It would
be much nicer if this was somehow computed rather than have the results
all open-coded like this.
Yes, I ideally wanted this to be calculated based on the different page
options and VA_BITS (which itself has a similar stanza), but I don't
know how to do that/if it is currently supported in Kconfig. This would
be even more desirable with the addition of 16K_PAGES, as with this
setup we have a combinatorial problem.
We could move this logic into the code where min/max are initialized,
but that would create its own mess, creating new Kconfig values to
introduce it in an arch-agnostic way after patch-set v2 moved that to
mm/mmap.c instread of arch/${arch}/mm/mmap.c Suggestions welcome.
Thank You,
Dan
From: Andrew Morton <akpm@linux-foundation.org> Date: 2015-11-25 00:39:12
On Wed, 18 Nov 2015 15:20:04 -0800 Daniel Cashman [off-list ref] wrote:
Address Space Layout Randomization (ASLR) provides a barrier to
exploitation of user-space processes in the presence of security
vulnerabilities by making it more difficult to find desired code/data
which could help an attack. This is done by adding a random offset to the
location of regions in the process address space, with a greater range of
potential offset values corresponding to better protection/a larger
search-space for brute force, but also to greater potential for
fragmentation.
The offset added to the mmap_base address, which provides the basis for
the majority of the mappings for a process, is set once on process exec in
arch_pick_mmap_layout() and is done via hard-coded per-arch values, which
reflect, hopefully, the best compromise for all systems. The trade-off
between increased entropy in the offset value generation and the
corresponding increased variability in address space fragmentation is not
absolute, however, and some platforms may tolerate higher amounts of
entropy. This patch introduces both new Kconfig values and a sysctl
interface which may be used to change the amount of entropy used for
offset generation on a system.
The direct motivation for this change was in response to the
libstagefright vulnerabilities that affected Android, specifically to
information provided by Google's project zero at:
http://googleprojectzero.blogspot.com/2015/09/stagefrightened.html
The attack presented therein, by Google's project zero, specifically
targeted the limited randomness used to generate the offset added to the
mmap_base address in order to craft a brute-force-based attack.
Concretely, the attack was against the mediaserver process, which was
limited to respawning every 5 seconds, on an arm device. The hard-coded 8
bits used resulted in an average expected success rate of defeating the
mmap ASLR after just over 10 minutes (128 tries at 5 seconds a piece).
With this patch, and an accompanying increase in the entropy value to 16
bits, the same attack would take an average expected time of over 45 hours
(32768 tries), which makes it both less feasible and more likely to be
noticed.
The introduced Kconfig and sysctl options are limited by per-arch minimum
and maximum values, the minimum of which was chosen to match the current
hard-coded value and the maximum of which was chosen so as to give the
greatest flexibility without generating an invalid mmap_base address,
generally a 3-4 bits less than the number of bits in the user-space
accessible virtual address space.
When decided whether or not to change the default value, a system
developer should consider that mmap_base address could be placed anywhere
up to 2^(value) bits away from the non-randomized location, which would
introduce variable-sized areas above and below the mmap_base address such
that the maximum vm_area_struct size may be reduced, preventing very large
allocations.
Nice, thanks.
mips, powerpc and s390 also implement arch_mmap_rnd(). Are there any
special considerations here, or it just a matter of maintainers wiring
it up and testing it?
These could be __read_mostly.
If one believes in such things. One effect of __read_mostly is to
clump the write-often stuff into the same cachelines and I've never
been convinced that one outweighs the other...
Is there any harm in permitting the attacker to read these values?
And is there any benefit in permitting non-attackers to read them?
I'm on the fence. Things like kernel/randomize_va_space is 644. But
since I don't see a benefit in exposing them, let's make them all 600
instead -- it's a new interface, better to keep it narrower now.
These could be __read_mostly.
If one believes in such things. One effect of __read_mostly is to
clump the write-often stuff into the same cachelines and I've never
been convinced that one outweighs the other...
The _min and _max values should be const, actually, since they're
build-time selected. The _bits could easily be __read_mostly, yeah.
-Kees
--
Kees Cook
Chrome OS & Brillo Security
From: Michael Ellerman <mpe@ellerman.id.au> Date: 2015-11-25 04:26:47
On Mon, 2015-11-23 at 10:55 -0800, Daniel Cashman wrote:
On 11/23/2015 07:04 AM, Will Deacon wrote:
quoted
On Wed, Nov 18, 2015 at 03:20:07PM -0800, Daniel Cashman wrote:
quoted
+config ARCH_MMAP_RND_BITS_MAX
+ default 20 if ARM64_64K_PAGES && ARCH_VA_BITS=39
+ default 24 if ARCH_VA_BITS=39
+ default 23 if ARM64_64K_PAGES && ARCH_VA_BITS=42
+ default 27 if ARCH_VA_BITS=42
+ default 29 if ARM64_64K_PAGES && ARCH_VA_BITS=48
+ default 33 if ARCH_VA_BITS=48
+ default 15 if ARM64_64K_PAGES
+ default 19
+
+config ARCH_MMAP_RND_COMPAT_BITS_MIN
+ default 7 if ARM64_64K_PAGES
+ default 11
FYI: we now support 16k pages too, so this might need updating. It would
be much nicer if this was somehow computed rather than have the results
all open-coded like this.
Yes, I ideally wanted this to be calculated based on the different page
options and VA_BITS (which itself has a similar stanza), but I don't
know how to do that/if it is currently supported in Kconfig. This would
be even more desirable with the addition of 16K_PAGES, as with this
setup we have a combinatorial problem.
We could move this logic into the code where min/max are initialized,
but that would create its own mess, creating new Kconfig values to
introduce it in an arch-agnostic way after patch-set v2 moved that to
mm/mmap.c instead of arch/${arch}/mm/mmap.c Suggestions welcome.
Could we instead change the meaning of the mmap_rnd_bits value to be the number
of address space bits that may be randomised?
ie. 40 would mean "please randomise in a 1T range", which with PAGE_SIZE=4K
gives you 28 random bits. etc.
That would make the value independent of PAGE_SIZE, and only depend on the size
of the address space.
It would also mean the values userspace sets and sees don't need to change if the
kernel PAGE_SIZE changes. (which probably doesn't happen often but still)
cheers
From: Michael Ellerman <mpe@ellerman.id.au> Date: 2015-11-25 04:40:06
On Wed, 2015-11-18 at 15:20 -0800, Daniel Cashman wrote:
From: dcashman <redacted>
ASLR currently only uses 8 bits to generate the random offset for the
mmap base address on 32 bit architectures. This value was chosen to
prevent a poorly chosen value from dividing the address space in such
a way as to prevent large allocations. This may not be an issue on all
platforms. Allow the specification of a minimum number of bits so that
platforms desiring greater ASLR protection may determine where to place
the trade-off.
@@ -511,6 +511,70 @@ config ARCH_HAS_ELF_RANDOMIZE-arch_mmap_rnd()-arch_randomize_brk()+configHAVE_ARCH_MMAP_RND_BITS+bool+help+Anarchshouldselectthissymbolifitsupportssettingavariable+numberofbitsforuseinestablishingthebaseaddressformmap+allocationsandprovidesvaluesforboth:+-ARCH_MMAP_RND_BITS_MIN+-ARCH_MMAP_RND_BITS_MAX++configARCH_MMAP_RND_BITS_MIN+int++configARCH_MMAP_RND_BITS_MAX+int++configARCH_MMAP_RND_BITS_DEFAULT+int++configARCH_MMAP_RND_BITS+int"Number of bits to use for ASLR of mmap base address"ifEXPERT+rangeARCH_MMAP_RND_BITS_MINARCH_MMAP_RND_BITS_MAX+defaultARCH_MMAP_RND_BITS_DEFAULTifARCH_MMAP_RND_BITS_DEFAULT
Here you support a default which is separate from the minimum.
+ default ARCH_MMAP_RND_BITS_MIN
+ depends on HAVE_ARCH_MMAP_RND_BITS
...
+
+config ARCH_MMAP_RND_COMPAT_BITS
+ int "Number of bits to use for ASLR of mmap base address for compatible applications" if EXPERT
+ range ARCH_MMAP_RND_COMPAT_BITS_MIN ARCH_MMAP_RND_COMPAT_BITS_MAX
+ default ARCH_MMAP_RND_COMPAT_BITS_MIN
But here you don't.
Just forgot?
I'd like to have a default which is separate from the minimum. That way we can
have a default which is reasonably large, but allow it to be lowered easily if
anything breaks.
cheers
On Mon, Nov 23, 2015 at 10:55:16AM -0800, Daniel Cashman wrote:
On 11/23/2015 07:04 AM, Will Deacon wrote:
quoted
On Wed, Nov 18, 2015 at 03:20:07PM -0800, Daniel Cashman wrote:
quoted
+config ARCH_MMAP_RND_BITS_MAX
+ default 20 if ARM64_64K_PAGES && ARCH_VA_BITS=39
Where is ARCH_VA_BITS defined? We only have options like
ARM64_VA_BITS_39.
BTW, we no longer allow the 64K pages and 39-bit VA combination.
quoted
quoted
+ default 24 if ARCH_VA_BITS=39
+ default 23 if ARM64_64K_PAGES && ARCH_VA_BITS=42
+ default 27 if ARCH_VA_BITS=42
+ default 29 if ARM64_64K_PAGES && ARCH_VA_BITS=48
+ default 33 if ARCH_VA_BITS=48
+ default 15 if ARM64_64K_PAGES
+ default 19
+
+config ARCH_MMAP_RND_COMPAT_BITS_MIN
+ default 7 if ARM64_64K_PAGES
+ default 11
FYI: we now support 16k pages too, so this might need updating. It would
be much nicer if this was somehow computed rather than have the results
all open-coded like this.
Yes, I ideally wanted this to be calculated based on the different page
options and VA_BITS (which itself has a similar stanza), but I don't
know how to do that/if it is currently supported in Kconfig. This would
be even more desirable with the addition of 16K_PAGES, as with this
setup we have a combinatorial problem.
For KASan, we ended up calculating KASAN_SHADOW_OFFSET in
arch/arm64/Makefile. What would the formula be for the above
ARCH_MMAP_RND_BITS_MAX?
--
Catalin
From: Daniel Cashman <hidden> Date: 2015-11-25 19:07:18
On 11/24/2015 04:39 PM, Andrew Morton wrote:
mips, powerpc and s390 also implement arch_mmap_rnd(). Are there any
special considerations here, or it just a matter of maintainers wiring
it up and testing it?
I had not yet looked at those at all, as I had no way to do even a
rudimentary "does it boot" test and opted to post v3 first. Upon first
glance, it should just be a matter of wiring it up:
Mips is divided into 12/16 bits for 32/64 bit (assume baseline 4k page)
w/COMPAT kconfig, powerpc is 11/18 w/COMPAT, s390 is 11/11 w/COMPAT.
s390 is a bit strange as COMPAT is for a 31-bit address space, although
is_32bit_task() is used to determine which mask to use, and the mask
itself for 64-bit only introduces 11 bits of entropy, but while still
affecting larger chunks of the address space (mask is 0x3ff80, resulting
in an effective 0x7ff shift of PAGE_SIZE + 7 bits).
I could go ahead and add these to patchset v4 and as with the previous
architectures, rely on feedback from arch-specific maintainers to help
tune and test the values.
-Dan
Is there any harm in permitting the attacker to read these values?
And is there any benefit in permitting non-attackers to read them?
I'm on the fence. Things like kernel/randomize_va_space is 644. But
since I don't see a benefit in exposing them, let's make them all 600
instead -- it's a new interface, better to keep it narrower now.
Is there any harm in allowing the attacker to read these values? Nothing
immediately comes to mind. It is a form of information leakage, and I
guess a local attacker could use this information to calibrate an attack
or decide whether or not brute-forcing is a worthy approach, but this
easily could be leaked in other ways as well.
Is there a benefit to allowing non-attackers to read them? Possibly
could be used in tests seeking to verify the system environment, but
again, this could be discovered in other ways.
I like Kees' suggestion of starting narrow and granting if need arises.
These could be __read_mostly.
If one believes in such things. One effect of __read_mostly is to
clump the write-often stuff into the same cachelines and I've never
been convinced that one outweighs the other...
The _min and _max values should be const, actually, since they're
build-time selected. The _bits could easily be __read_mostly, yeah.
Yes, one would generally expect these to never be touched, and even if
they were, the threshold of __read_mostly would certainly be crossed.
-Dan
From: Daniel Cashman <hidden> Date: 2015-11-25 19:33:20
On 11/24/2015 08:26 PM, Michael Ellerman wrote:
On Mon, 2015-11-23 at 10:55 -0800, Daniel Cashman wrote:
quoted
On 11/23/2015 07:04 AM, Will Deacon wrote:
quoted
On Wed, Nov 18, 2015 at 03:20:07PM -0800, Daniel Cashman wrote:
quoted
+config ARCH_MMAP_RND_BITS_MAX
+ default 20 if ARM64_64K_PAGES && ARCH_VA_BITS=39
+ default 24 if ARCH_VA_BITS=39
+ default 23 if ARM64_64K_PAGES && ARCH_VA_BITS=42
+ default 27 if ARCH_VA_BITS=42
+ default 29 if ARM64_64K_PAGES && ARCH_VA_BITS=48
+ default 33 if ARCH_VA_BITS=48
+ default 15 if ARM64_64K_PAGES
+ default 19
+
+config ARCH_MMAP_RND_COMPAT_BITS_MIN
+ default 7 if ARM64_64K_PAGES
+ default 11
FYI: we now support 16k pages too, so this might need updating. It would
be much nicer if this was somehow computed rather than have the results
all open-coded like this.
Yes, I ideally wanted this to be calculated based on the different page
options and VA_BITS (which itself has a similar stanza), but I don't
know how to do that/if it is currently supported in Kconfig. This would
be even more desirable with the addition of 16K_PAGES, as with this
setup we have a combinatorial problem.
We could move this logic into the code where min/max are initialized,
but that would create its own mess, creating new Kconfig values to
introduce it in an arch-agnostic way after patch-set v2 moved that to
mm/mmap.c instead of arch/${arch}/mm/mmap.c Suggestions welcome.
Could we instead change the meaning of the mmap_rnd_bits value to be the number
of address space bits that may be randomised?
ie. 40 would mean "please randomise in a 1T range", which with PAGE_SIZE=4K
gives you 28 random bits. etc.
That would make the value independent of PAGE_SIZE, and only depend on the size
of the address space.
It would also mean the values userspace sets and sees don't need to change if the
kernel PAGE_SIZE changes. (which probably doesn't happen often but still)
This is an intriguing idea. It might actually be more meaningful to a
sysadmin when weighing how high they're willing to go, since it makes
the relation to the address space overall more apparent. Though the
cost would be more obvious, the benefit would become less-so, as the
amount of entropy used, and thus expected brute-force requirements would
be hidden. I'll defer to Andrew Morton, as the maintainer, to make this
decision as I think both approaches are valid.
Thank You,
Dan
From: Daniel Cashman <hidden> Date: 2015-11-25 19:36:55
On 11/24/2015 08:40 PM, Michael Ellerman wrote:
On Wed, 2015-11-18 at 15:20 -0800, Daniel Cashman wrote:
quoted
From: dcashman <redacted>
ASLR currently only uses 8 bits to generate the random offset for the
mmap base address on 32 bit architectures. This value was chosen to
prevent a poorly chosen value from dividing the address space in such
a way as to prevent large allocations. This may not be an issue on all
platforms. Allow the specification of a minimum number of bits so that
platforms desiring greater ASLR protection may determine where to place
the trade-off.
@@ -511,6 +511,70 @@ config ARCH_HAS_ELF_RANDOMIZE-arch_mmap_rnd()-arch_randomize_brk()+configHAVE_ARCH_MMAP_RND_BITS+bool+help+Anarchshouldselectthissymbolifitsupportssettingavariable+numberofbitsforuseinestablishingthebaseaddressformmap+allocationsandprovidesvaluesforboth:+-ARCH_MMAP_RND_BITS_MIN+-ARCH_MMAP_RND_BITS_MAX++configARCH_MMAP_RND_BITS_MIN+int++configARCH_MMAP_RND_BITS_MAX+int++configARCH_MMAP_RND_BITS_DEFAULT+int++configARCH_MMAP_RND_BITS+int"Number of bits to use for ASLR of mmap base address"ifEXPERT+rangeARCH_MMAP_RND_BITS_MINARCH_MMAP_RND_BITS_MAX+defaultARCH_MMAP_RND_BITS_DEFAULTifARCH_MMAP_RND_BITS_DEFAULT
Here you support a default which is separate from the minimum.
quoted
+ default ARCH_MMAP_RND_BITS_MIN
+ depends on HAVE_ARCH_MMAP_RND_BITS
...
quoted
+
+config ARCH_MMAP_RND_COMPAT_BITS
+ int "Number of bits to use for ASLR of mmap base address for compatible applications" if EXPERT
+ range ARCH_MMAP_RND_COMPAT_BITS_MIN ARCH_MMAP_RND_COMPAT_BITS_MAX
+ default ARCH_MMAP_RND_COMPAT_BITS_MIN
But here you don't.
Just forgot?
Yes. Good catch.
I'd like to have a default which is separate from the minimum. That way we can
have a default which is reasonably large, but allow it to be lowered easily if
anything breaks.
Will add it, along w/the documentation cleanup and other changes.
Thank You,
Dan
From: Daniel Cashman <hidden> Date: 2015-11-25 20:39:20
On 11/25/2015 04:06 AM, Catalin Marinas wrote:
On Mon, Nov 23, 2015 at 10:55:16AM -0800, Daniel Cashman wrote:
quoted
On 11/23/2015 07:04 AM, Will Deacon wrote:
quoted
On Wed, Nov 18, 2015 at 03:20:07PM -0800, Daniel Cashman wrote:
quoted
+config ARCH_MMAP_RND_BITS_MAX
+ default 20 if ARM64_64K_PAGES && ARCH_VA_BITS=39
Where is ARCH_VA_BITS defined? We only have options like
ARM64_VA_BITS_39.
BTW, we no longer allow the 64K pages and 39-bit VA combination.
It is not, and should have been ARM64_VA_BITS. This stanza was meant to
mimic the one for ARM64_VA_BITS. Thank you for pointing this, and the
39-bit combination out.
quoted
quoted
quoted
+ default 24 if ARCH_VA_BITS=39
+ default 23 if ARM64_64K_PAGES && ARCH_VA_BITS=42
+ default 27 if ARCH_VA_BITS=42
+ default 29 if ARM64_64K_PAGES && ARCH_VA_BITS=48
+ default 33 if ARCH_VA_BITS=48
+ default 15 if ARM64_64K_PAGES
+ default 19
+
+config ARCH_MMAP_RND_COMPAT_BITS_MIN
+ default 7 if ARM64_64K_PAGES
+ default 11
FYI: we now support 16k pages too, so this might need updating. It would
be much nicer if this was somehow computed rather than have the results
all open-coded like this.
Yes, I ideally wanted this to be calculated based on the different page
options and VA_BITS (which itself has a similar stanza), but I don't
know how to do that/if it is currently supported in Kconfig. This would
be even more desirable with the addition of 16K_PAGES, as with this
setup we have a combinatorial problem.
For KASan, we ended up calculating KASAN_SHADOW_OFFSET in
arch/arm64/Makefile. What would the formula be for the above
ARCH_MMAP_RND_BITS_MAX?
The general formula I used ended up being:
_max = floor(log(TASK_SIZE)) - log(PAGE_SIZE) - 3
which in the case of arm64 ended up being VA_BITS - PAGE_SHIFT - 3.
Aside: following this would actually put COMPAT_BITS_MAX at 17 for 4k
pages, rather than 16, but I left it at 16 to mirror what was put in
arch/arm/Kconfig.
Thank You,
Dan
From: Michael Ellerman <mpe@ellerman.id.au> Date: 2015-11-26 07:08:02
On Tue, 2015-11-24 at 16:39 -0800, Andrew Morton wrote:
On Wed, 18 Nov 2015 15:20:04 -0800 Daniel Cashman [off-list ref] wrote:
quoted
Address Space Layout Randomization (ASLR) provides a barrier to
exploitation of user-space processes in the presence of security
vulnerabilities by making it more difficult to find desired code/data
which could help an attack. This is done by adding a random offset to the
location of regions in the process address space, with a greater range of
potential offset values corresponding to better protection/a larger
search-space for brute force, but also to greater potential for
fragmentation.
mips, powerpc and s390 also implement arch_mmap_rnd(). Are there any
special considerations here, or it just a matter of maintainers wiring
it up and testing it?
I had a quick stab at powerpc. It seems to work OK, though I've only tested on
64-bit 64K pages.
I'll update this when Daniel does a version which supports a DEFAULT for both
MIN values.
cheers
From 7c42636d5df21203977900d283c722116f06310c Mon Sep 17 00:00:00 2001
From: Michael Ellerman <mpe@ellerman.id.au>
Date: Thu, 26 Nov 2015 17:40:00 +1100
Subject: [PATCH] powerpc/mm: Use ARCH_MMCAP_RND_BITS
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/Kconfig | 32 ++++++++++++++++++++++++++++++++
arch/powerpc/mm/mmap.c | 12 +++++++-----
2 files changed, 39 insertions(+), 5 deletions(-)
From: Martin Schwidefsky <hidden> Date: 2015-11-26 15:11:43
On Wed, 25 Nov 2015 11:07:09 -0800
Daniel Cashman [off-list ref] wrote:
On 11/24/2015 04:39 PM, Andrew Morton wrote:
quoted
mips, powerpc and s390 also implement arch_mmap_rnd(). Are there any
special considerations here, or it just a matter of maintainers wiring
it up and testing it?
I had not yet looked at those at all, as I had no way to do even a
rudimentary "does it boot" test and opted to post v3 first. Upon first
glance, it should just be a matter of wiring it up:
Mips is divided into 12/16 bits for 32/64 bit (assume baseline 4k page)
w/COMPAT kconfig, powerpc is 11/18 w/COMPAT, s390 is 11/11 w/COMPAT.
s390 is a bit strange as COMPAT is for a 31-bit address space, although
is_32bit_task() is used to determine which mask to use, and the mask
itself for 64-bit only introduces 11 bits of entropy, but while still
affecting larger chunks of the address space (mask is 0x3ff80, resulting
in an effective 0x7ff shift of PAGE_SIZE + 7 bits).
s390 uses a mmap randomization of 11 bits but applies it to different
bits dependent if the task is a compat task or not. From the machine
perspective we would like to always use the randomization bits for
normal, non-compat tasks. But as the 2GB address space for compat tasks
is really limited the randomization is applied in bits 2^12..2^22 for
compat tasks vs 2^19..2^29 for normal tasks at the cost of performance.
This has to do with the cache aliasing on z13.
By the way we will replace is_32bit_task with() is_compat_task(), I have
a patch from Heiko pending for that.
--
blue skies,
Martin.
"Reality continues to ruin my life." - Calvin.
2015-11-25 23:39 GMT+03:00 Daniel Cashman [off-list ref]:
On 11/25/2015 04:06 AM, Catalin Marinas wrote:
quoted
On Mon, Nov 23, 2015 at 10:55:16AM -0800, Daniel Cashman wrote:
quoted
On 11/23/2015 07:04 AM, Will Deacon wrote:
quoted
On Wed, Nov 18, 2015 at 03:20:07PM -0800, Daniel Cashman wrote:
quoted
+config ARCH_MMAP_RND_BITS_MAX
+ default 20 if ARM64_64K_PAGES && ARCH_VA_BITS=39
Where is ARCH_VA_BITS defined? We only have options like
ARM64_VA_BITS_39.
BTW, we no longer allow the 64K pages and 39-bit VA combination.
It is not, and should have been ARM64_VA_BITS. This stanza was meant to
mimic the one for ARM64_VA_BITS. Thank you for pointing this, and the
39-bit combination out.
quoted
quoted
quoted
quoted
+ default 24 if ARCH_VA_BITS=39
+ default 23 if ARM64_64K_PAGES && ARCH_VA_BITS=42
+ default 27 if ARCH_VA_BITS=42
+ default 29 if ARM64_64K_PAGES && ARCH_VA_BITS=48
+ default 33 if ARCH_VA_BITS=48
+ default 15 if ARM64_64K_PAGES
+ default 19
+
+config ARCH_MMAP_RND_COMPAT_BITS_MIN
+ default 7 if ARM64_64K_PAGES
+ default 11
FYI: we now support 16k pages too, so this might need updating. It would
be much nicer if this was somehow computed rather than have the results
all open-coded like this.
Yes, I ideally wanted this to be calculated based on the different page
options and VA_BITS (which itself has a similar stanza), but I don't
know how to do that/if it is currently supported in Kconfig. This would
be even more desirable with the addition of 16K_PAGES, as with this
setup we have a combinatorial problem.
For KASan, we ended up calculating KASAN_SHADOW_OFFSET in
arch/arm64/Makefile. What would the formula be for the above
ARCH_MMAP_RND_BITS_MAX?
The general formula I used ended up being:
_max = floor(log(TASK_SIZE)) - log(PAGE_SIZE) - 3
For kasan, we calculate KASAN_SHADOW_OFFSET in Makefile, because we need to use
that value in Makefiles.
For ARCH_MMAP_RND_COMPAT_BITS_MIN/MAX I don't see a reason why it has
to be in Kconfig.
Can't we just use your formula to #define ARCH_MMAP_RND_COMPAT_BITS_*
in some arch header?
which in the case of arm64 ended up being VA_BITS - PAGE_SHIFT - 3.
Aside: following this would actually put COMPAT_BITS_MAX at 17 for 4k
pages, rather than 16, but I left it at 16 to mirror what was put in
arch/arm/Kconfig.
Thank You,
Dan
On Fri, Nov 27, 2015 at 11:36:30AM +0300, Andrey Ryabinin wrote:
2015-11-25 23:39 GMT+03:00 Daniel Cashman [off-list ref]:
quoted
On 11/25/2015 04:06 AM, Catalin Marinas wrote:
quoted
For KASan, we ended up calculating KASAN_SHADOW_OFFSET in
arch/arm64/Makefile. What would the formula be for the above
ARCH_MMAP_RND_BITS_MAX?
The general formula I used ended up being:
_max = floor(log(TASK_SIZE)) - log(PAGE_SIZE) - 3
For kasan, we calculate KASAN_SHADOW_OFFSET in Makefile, because we need to use
that value in Makefiles.
For ARCH_MMAP_RND_COMPAT_BITS_MIN/MAX I don't see a reason why it has
to be in Kconfig.
Can't we just use your formula to #define ARCH_MMAP_RND_COMPAT_BITS_*
in some arch header?
Because there is another option, ARCH_MMAP_RND_BITS depending on EXPERT
which uses the MIN/MAX range defined per architecture. Since it's an
expert feature, we could as well ignore the MIN/MAX in Kconfig and just
add BUILD_BUG_ON checks to the code. This way we could simply define
them in C files.
Alternatively, add arithmetics support to kbuild ;).
--
Catalin