Skip to contentSkip to conversation

Randomization of address chosen by mmap.

RFC PATCH In review Ilya Smith 10 participants 39 messages Mar 22, 2018 – Apr 3, 2018

Subsystems (16)
lore
Share & tools
lore

Ilya Smith

author
#0 lore raw

v2 cover Randomization of address chosen by mmap.

Current implementation doesn't randomize address returned by mmap. All the entropy ends with choosing mmap_base_addr at the process creation. After that mmap build very predictable layout of address space. It allows to bypass ASLR in many cases. This patch make randomization of address on any mmap call.

---
v2: Changed the way how gap was chosen. Now we don't get all possible gaps. Random address generated and used as a tree walking direction. Tree walked with backtracking till suitable gap will be found. When the gap was found, address randomly shifted from next vma start.

The vm_unmapped_area_info structure was extended with new field random_shift what might be used to set arch-depended limit on shift to next vma start. In case of x86-64 architecture this shift is 256 pages for 32 bit applications and 0x1000000 pages for 64 bit.

To get the entropy pseudo-random is used. This is because on Intel x86-64 processors instruction RDRAND works very slow if buffer is consumed - after about 10000 iterations.

This feature could be enabled by setting randomize_va_space with 4.

---
Performance:
After applying this patch single mmap took about 7% longer according to following test:

    before = rdtsc();
    addr = mmap(0, SIZE, PROT_READ | PROT_WRITE, 
                 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
    after = rdtsc();
    diff = after - before;
    munmap(addr, SIZE)
    ...
    unsigned long long total = 0;
    for(int i = 0; i < count; ++i) {
        total += one_iteration();
    }
    printf("%lld\n", total);

Time is consumed by div instruction in computation of the address.

make kernel:
echo 2 > /proc/sys/kernel/randomize_va_space
make mrproper && make defconfig && time make
real 11m9.925s
user 10m17.829s
sys 1m4.969s

echo 4 > /proc/sys/kernel/randomize_va_space
make mrproper && make defconfig && time make
real 11m12.806s
user 10m18.305s
sys 1m4.281s

Ilya Smith (2):
Randomization of address chosen by mmap. Architecture defined limit on memory region random shift.

 arch/alpha/kernel/osf_sys.c         |   1 +
 arch/arc/mm/mmap.c                  |   1 +
 arch/arm/mm/mmap.c                  |   2 +
 arch/frv/mm/elf-fdpic.c             |   1 +
 arch/ia64/kernel/sys_ia64.c         |   1 +
 arch/ia64/mm/hugetlbpage.c          |   1 +
 arch/metag/mm/hugetlbpage.c         |   1 +
 arch/mips/mm/mmap.c                 |   1 +
 arch/parisc/kernel/sys_parisc.c     |   2 +
 arch/powerpc/mm/hugetlbpage-radix.c |   1 +
 arch/powerpc/mm/mmap.c              |   2 +
 arch/powerpc/mm/slice.c             |   2 +
 arch/s390/mm/mmap.c                 |   2 +
 arch/sh/mm/mmap.c                   |   2 +
 arch/sparc/kernel/sys_sparc_32.c    |   1 +
 arch/sparc/kernel/sys_sparc_64.c    |   2 +
 arch/sparc/mm/hugetlbpage.c         |   2 +
 arch/tile/mm/hugetlbpage.c          |   2 +
 arch/x86/kernel/sys_x86_64.c        |   4 +
 arch/x86/mm/hugetlbpage.c           |   4 +
 fs/hugetlbfs/inode.c                |   1 +
 include/linux/mm.h                  |  17 ++--
 mm/mmap.c                           | 165 ++++++++++++++++++++++++++++++++++++
 23 files changed, 213 insertions(+), 5 deletions(-)
Signature · 1 line
2.7.4
author
#1 lore raw

RFC PATCH v2 1/2 Randomization of address chosen by mmap.

---
 include/linux/mm.h |  16 ++++--
 mm/mmap.c          | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 175 insertions(+), 5 deletions(-)
include/linux/mm.h +11 -5
index ad06d42..c716257 100644
@@ -25,6 +25,7 @@
 #include <linux/err.h>
 #include <linux/page_ref.h>
 #include <linux/memremap.h>
+#include <linux/sched.h>
 
 struct mempolicy;
 struct anon_vma;
@@ -2253,6 +2254,13 @@ struct vm_unmapped_area_info {
 	unsigned long align_offset;
 };
 
+#ifndef CONFIG_MMU
+#define randomize_va_space 0
+#else
+extern int randomize_va_space;
+#endif
+
+extern unsigned long unmapped_area_random(struct vm_unmapped_area_info *info);
 extern unsigned long unmapped_area(struct vm_unmapped_area_info *info);
 extern unsigned long unmapped_area_topdown(struct vm_unmapped_area_info *info);
 
@@ -2268,6 +2276,9 @@ extern unsigned long unmapped_area_topdown(struct vm_unmapped_area_info *info);
 static inline unsigned long
 vm_unmapped_area(struct vm_unmapped_area_info *info)
 {
+	/* How about 32 bit process?? */
+	if ((current->flags & PF_RANDOMIZE) && randomize_va_space > 3)
+		return unmapped_area_random(info);
 	if (info->flags & VM_UNMAPPED_AREA_TOPDOWN)
 		return unmapped_area_topdown(info);
 	else
@@ -2529,11 +2540,6 @@ int drop_caches_sysctl_handler(struct ctl_table *, int,
 void drop_slab(void);
 void drop_slab_node(int nid);
 
-#ifndef CONFIG_MMU
-#define randomize_va_space 0
-#else
-extern int randomize_va_space;
-#endif
 
 const char * arch_vma_name(struct vm_area_struct *vma);
 void print_vma_addr(char *prefix, unsigned long rip);
mm/mmap.c +160 -0

172 lines not on this page · raw message

Signature · 1 line
2.7.4
maintainer
#2 lore raw
Quoted 2 lines · On Thu, 22 Mar 2018 19:36:37 +0300 Ilya Smith <[email protected]> wrote:
 include/linux/mm.h |  16 ++++--
 mm/mmap.c          | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++++

You'll be wanting to update the documentation.
Documentation/sysctl/kernel.txt and
Documentation/admin-guide/kernel-parameters.txt.

include/linux/mm.h extern unsigned long unmapped_area_topdown(struct vm_unmapped_area_info *info); · line 2281

Quoted 9 lines

...

include/linux/mm.h +3 -0
@@ -2268,6 +2276,9 @@ extern unsigned long unmapped_area_topdown(struct vm_unmapped_area_info *info);
 static inline unsigned long
 vm_unmapped_area(struct vm_unmapped_area_info *info)
 {
+	/* How about 32 bit process?? */
+	if ((current->flags & PF_RANDOMIZE) && randomize_va_space > 3)
+		return unmapped_area_random(info);

The handling of randomize_va_space is peculiar. Rather than being a bitfield which independently selects different modes, it is treated as a scalar: the larger the value, the more stuff we randomize.

I can see the sense in that (and I wonder what randomize_va_space=5 will do). But it is... odd.

Why did you select randomize_va_space=4 for this? Is there a mode 3 already and we forgot to document it? Or did you leave a gap for something? If the former, please feel free to fix the documentation (in a separate, preceding patch) while you're in there ;)

Quoted 11 lines
include/linux/mm.h +0 -0
 	if (info->flags & VM_UNMAPPED_AREA_TOPDOWN)
 		return unmapped_area_topdown(info);
 	else
@@ -2529,11 +2540,6 @@ int drop_caches_sysctl_handler(struct ctl_table *, int,
 void drop_slab(void);
 void drop_slab_node(int nid);
 
 
...

include/linux/mm.h unsigned long mmap_region(struct file *file, unsigned long addr, · line 1785

Quoted 5 lines
include/linux/mm.h +2 -0
@@ -1780,6 +1781,169 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
 	return error;
 }
 
+unsigned long unmapped_area_random(struct vm_unmapped_area_info *info)
+{

This function is just dead code if CONFIG_MMU=n, yes? Let's add the ifdefs to make it go away in that case.

Quoted 16 lines
mm/mmap.c +13 -0
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma = NULL;
+	struct vm_area_struct *visited_vma = NULL;
+	unsigned long entropy[2];
+	unsigned long length, low_limit, high_limit, gap_start, gap_end;
+	unsigned long addr = 0;
+
+	/* get entropy with prng */
+	prandom_bytes(&entropy, sizeof(entropy));
+	/* small hack to prevent EPERM result */
+	info->low_limit = max(info->low_limit, mmap_min_addr);
+
 
...
 
+found:

mm/mmap.c unsigned long mmap_region(struct file *file, unsigned long addr,

Quoted 10 lines
mm/mmap.c +10 -0
+	/* We found a suitable gap. Clip it with the original high_limit. */
+	if (gap_end > info->high_limit)
+		gap_end = info->high_limit;
+	gap_end -= info->length;
+	gap_end -= (gap_end - info->align_offset) & info->align_mask;
+	/* only one suitable page */
+	if (gap_end ==  gap_start)
+		return gap_start;
+	addr = entropy[1] % (min((gap_end - gap_start) >> PAGE_SHIFT,
+							 0x10000UL));

What does the magic 10000 mean? Isn't a comment needed explaining this?

Quoted 7 lines
mm/mmap.c +4 -0
+	addr = gap_end - (addr << PAGE_SHIFT);
+	addr += (info->align_offset - addr) & info->align_mask;
+	return addr;
+}
 
...
author
#3 lore raw
Quoted 12 lines · Andrew Morton
Quoted 2 lines · On Thu, 22 Mar 2018 19:36:37 +0300 Ilya Smith <[email protected]> wrote:

include/linux/mm.h | 16 ++++--
mm/mmap.c | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++++

You'll be wanting to update the documentation.
Documentation/sysctl/kernel.txt and
Documentation/admin-guide/kernel-parameters.txt.

Sure, thanks for pointing there. I will add few lines there after discussion them here.

Quoted 14 lines

include/linux/mm.h extern unsigned long unmapped_area_topdown(struct vm_unmapped_area_info *info); · line 2281

Quoted 9 lines

...

(quoted diff) +0 -0
@@ -2268,6 +2276,9 @@ extern unsigned long unmapped_area_topdown(struct vm_unmapped_area_info *info);

static inline unsigned long vm_unmapped_area(struct vm_unmapped_area_info *info) {

include/linux/mm.h +3 -0
+	/* How about 32 bit process?? */
+	if ((current->flags & PF_RANDOMIZE) && randomize_va_space > 3)
+		return unmapped_area_random(info);

The handling of randomize_va_space is peculiar. Rather than being a bitfield which independently selects different modes, it is treated as a scalar: the larger the value, the more stuff we randomize.

Quoted 8 lines

I can see the sense in that (and I wonder what randomize_va_space=5 will do). But it is... odd.

Why did you select randomize_va_space=4 for this? Is there a mode 3 already and we forgot to document it? Or did you leave a gap for something? If the former, please feel free to fix the documentation (in a separate, preceding patch) while you're in there ;)

Yes, I was not sure about correct value so leaved some gap for future. Also according to current implementation this value used like a scalar. But I’m agree bitfield looks more flexible for the future. I think right now I can leave 3 as value for my patch and it could be fixed any time in the future. What do you think about it?

Quoted 14 lines
Quoted 14 lines
	if (info->flags & VM_UNMAPPED_AREA_TOPDOWN)
		return unmapped_area_topdown(info);
	else
include/linux/mm.h +0 -0
@@ -2529,11 +2540,6 @@ int drop_caches_sysctl_handler(struct ctl_table *, int,
 void drop_slab(void);
 void drop_slab_node(int nid);
 
 
...
@@ -1780,6 +1781,169 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
 	return error;
 }
 
Quoted 6 lines

mm/mmap.c unsigned long mmap_region(struct file *file, unsigned long addr, · line 1785

Quoted 2 lines
mm/mmap.c +2 -0
+unsigned long unmapped_area_random(struct vm_unmapped_area_info *info)
+{

This function is just dead code if CONFIG_MMU=n, yes? Let's add the ifdefs to make it go away in that case.

Thanks, I missed that case. I will fix it.

Quoted 29 lines
Quoted 16 lines
mm/mmap.c +13 -0
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma = NULL;
+	struct vm_area_struct *visited_vma = NULL;
+	unsigned long entropy[2];
+	unsigned long length, low_limit, high_limit, gap_start, gap_end;
+	unsigned long addr = 0;
+
+	/* get entropy with prng */
+	prandom_bytes(&entropy, sizeof(entropy));
+	/* small hack to prevent EPERM result */
+	info->low_limit = max(info->low_limit, mmap_min_addr);
+
 
...
 
+found:

mm/mmap.c unsigned long mmap_region(struct file *file, unsigned long addr,

Quoted 10 lines
mm/mmap.c +10 -0
+	/* We found a suitable gap. Clip it with the original high_limit. */
+	if (gap_end > info->high_limit)
+		gap_end = info->high_limit;
+	gap_end -= info->length;
+	gap_end -= (gap_end - info->align_offset) & info->align_mask;
+	/* only one suitable page */
+	if (gap_end ==  gap_start)
+		return gap_start;
+	addr = entropy[1] % (min((gap_end - gap_start) >> PAGE_SHIFT,
+							 0x10000UL));

What does the magic 10000 mean? Isn't a comment needed explaining this?

Quoted 8 lines

mm/mmap.c unsigned long mmap_region(struct file *file, unsigned long addr,

Quoted 7 lines
mm/mmap.c +4 -0
+	addr = gap_end - (addr << PAGE_SHIFT);
+	addr += (info->align_offset - addr) & info->align_mask;
+	return addr;
+}
 
...

This one what I fix by next patch. I was trying to make patches separate to make it easier to understand them. This constant came from last version discussion and honestly doesn’t means much. I replaced it with Architecture depended limit that as I plan would be CONFIG value as well.

This value means maximum number of pages we can move away from the next vma. The less value means less security but less memory fragmentation. Any way on 64bit systems memory fragmentation is not such a big problem.

author
#4 lore raw

RFC PATCH v2 2/2 Architecture defined limit on memory region random shift.

In reply to Ilya Smith
---
 arch/alpha/kernel/osf_sys.c         | 1 +
 arch/arc/mm/mmap.c                  | 1 +
 arch/arm/mm/mmap.c                  | 2 ++
 arch/frv/mm/elf-fdpic.c             | 1 +
 arch/ia64/kernel/sys_ia64.c         | 1 +
 arch/ia64/mm/hugetlbpage.c          | 1 +
 arch/metag/mm/hugetlbpage.c         | 1 +
 arch/mips/mm/mmap.c                 | 1 +
 arch/parisc/kernel/sys_parisc.c     | 2 ++
 arch/powerpc/mm/hugetlbpage-radix.c | 1 +
 arch/powerpc/mm/mmap.c              | 2 ++
 arch/powerpc/mm/slice.c             | 2 ++
 arch/s390/mm/mmap.c                 | 2 ++
 arch/sh/mm/mmap.c                   | 2 ++
 arch/sparc/kernel/sys_sparc_32.c    | 1 +
 arch/sparc/kernel/sys_sparc_64.c    | 2 ++
 arch/sparc/mm/hugetlbpage.c         | 2 ++
 arch/tile/mm/hugetlbpage.c          | 2 ++
 arch/x86/kernel/sys_x86_64.c        | 4 ++++
 arch/x86/mm/hugetlbpage.c           | 4 ++++
 fs/hugetlbfs/inode.c                | 1 +
 include/linux/mm.h                  | 1 +
 mm/mmap.c                           | 3 ++-
 23 files changed, 39 insertions(+), 1 deletion(-)
arch/alpha/kernel/osf_sys.c +1 -0
index fa1a392..0ab9f31 100644
@@ -1301,6 +1301,7 @@ arch_get_unmapped_area_1(unsigned long addr, unsigned long len,
 	info.high_limit = limit;
 	info.align_mask = 0;
 	info.align_offset = 0;
+	info.random_shift = 0;
 	return vm_unmapped_area(&info);
 }
 
arch/arc/mm/mmap.c +1 -0
index 2e13683..45225fc 100644
@@ -75,5 +75,6 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
 	info.high_limit = TASK_SIZE;
 	info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
 	info.align_offset = pgoff << PAGE_SHIFT;
+	info.random_shift = 0;
 	return vm_unmapped_area(&info);
 }
arch/arm/mm/mmap.c +2 -0
index eb1de66..1eb660c 100644
@@ -101,6 +101,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
 	info.high_limit = TASK_SIZE;
 	info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
 	info.align_offset = pgoff << PAGE_SHIFT;
+	info.random_shift = 0;
 	return vm_unmapped_area(&info);
 }
 
@@ -152,6 +153,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 	info.high_limit = mm->mmap_base;
 	info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
 	info.align_offset = pgoff << PAGE_SHIFT;
+	info.random_shift = 0;
 	addr = vm_unmapped_area(&info);
 
 	/*
arch/frv/mm/elf-fdpic.c +1 -0
index 46aa289..a2ce2ce 100644
@@ -86,6 +86,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
 	info.high_limit = (current->mm->start_stack - 0x00200000);
 	info.align_mask = 0;
 	info.align_offset = 0;
+	info.random_shift = 0;
 	addr = vm_unmapped_area(&info);
 	if (!(addr & ~PAGE_MASK))
 		goto success;
arch/ia64/kernel/sys_ia64.c +1 -0
index 085adfc..15fa4fb 100644
@@ -64,6 +64,7 @@ arch_get_unmapped_area (struct file *filp, unsigned long addr, unsigned long len
 	info.high_limit = TASK_SIZE;
 	info.align_mask = align_mask;
 	info.align_offset = 0;
+	info.random_shift = 0;
 	return vm_unmapped_area(&info);
 }
 
arch/ia64/mm/hugetlbpage.c +1 -0
index d16e419..ec7822d 100644
@@ -162,6 +162,7 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, u
 	info.high_limit = HPAGE_REGION_BASE + RGN_MAP_LIMIT;
 	info.align_mask = PAGE_MASK & (HPAGE_SIZE - 1);
 	info.align_offset = 0;
+	info.random_shift = 0;
 	return vm_unmapped_area(&info);
 }
 
arch/metag/mm/hugetlbpage.c +1 -0
index 012ee4c..babd325 100644
@@ -191,6 +191,7 @@ hugetlb_get_unmapped_area_new_pmd(unsigned long len)
 	info.high_limit = TASK_SIZE;
 	info.align_mask = PAGE_MASK & HUGEPT_MASK;
 	info.align_offset = 0;
+	info.random_shift = 0;
 	return vm_unmapped_area(&info);
 }
 
arch/mips/mm/mmap.c +1 -0
index 33d3251..5a3d384 100644
@@ -122,6 +122,7 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp,
 	info.flags = 0;
 	info.low_limit = mm->mmap_base;
 	info.high_limit = TASK_SIZE;
+	info.random_shift = 0;
 	return vm_unmapped_area(&info);
 }
 
arch/parisc/kernel/sys_parisc.c +2 -0
index 378a754..abf4b05 100644
@@ -130,6 +130,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
 	info.high_limit = mmap_upper_limit();
 	info.align_mask = last_mmap ? (PAGE_MASK & (SHM_COLOUR - 1)) : 0;
 	info.align_offset = shared_align_offset(last_mmap, pgoff);
+	info.random_shift = 0;
 	addr = vm_unmapped_area(&info);
 
 found_addr:
@@ -192,6 +193,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 	info.high_limit = mm->mmap_base;
 	info.align_mask = last_mmap ? (PAGE_MASK & (SHM_COLOUR - 1)) : 0;
 	info.align_offset = shared_align_offset(last_mmap, pgoff);
+	info.random_shift = 0;
 	addr = vm_unmapped_area(&info);
 	if (!(addr & ~PAGE_MASK))
 		goto found_addr;
arch/powerpc/mm/hugetlbpage-radix.c +1 -0
index 2486bee..1d61a88 100644
@@ -87,6 +87,7 @@ radix__hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
 	info.high_limit = mm->mmap_base + (high_limit - DEFAULT_MAP_WINDOW);
 	info.align_mask = PAGE_MASK & ~huge_page_mask(h);
 	info.align_offset = 0;
+	info.random_shift = 0;
 
 	return vm_unmapped_area(&info);
 }
arch/powerpc/mm/mmap.c +2 -0
index d503f34..7fe98c7 100644
@@ -136,6 +136,7 @@ radix__arch_get_unmapped_area(struct file *filp, unsigned long addr,
 	info.low_limit = mm->mmap_base;
 	info.high_limit = high_limit;
 	info.align_mask = 0;
+	info.random_shift = 0;
 
 	return vm_unmapped_area(&info);
 }
@@ -180,6 +181,7 @@ radix__arch_get_unmapped_area_topdown(struct file *filp,
 	info.low_limit = max(PAGE_SIZE, mmap_min_addr);
 	info.high_limit = mm->mmap_base + (high_limit - DEFAULT_MAP_WINDOW);
 	info.align_mask = 0;
+	info.random_shift = 0;
 
 	addr = vm_unmapped_area(&info);
 	if (!(addr & ~PAGE_MASK))
arch/powerpc/mm/slice.c +2 -0
index 23ec2c5..2005845 100644
@@ -284,6 +284,7 @@ static unsigned long slice_find_area_bottomup(struct mm_struct *mm,
 	info.length = len;
 	info.align_mask = PAGE_MASK & ((1ul << pshift) - 1);
 	info.align_offset = 0;
+	info.random_shift = 0;
 
 	addr = TASK_UNMAPPED_BASE;
 	/*
@@ -330,6 +331,7 @@ static unsigned long slice_find_area_topdown(struct mm_struct *mm,
 	info.length = len;
 	info.align_mask = PAGE_MASK & ((1ul << pshift) - 1);
 	info.align_offset = 0;
+	info.random_shift = 0;
 
 	addr = mm->mmap_base;
 	/*
arch/s390/mm/mmap.c +2 -0
index 831bdcf..141823f 100644
@@ -95,6 +95,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
 	info.length = len;
 	info.low_limit = mm->mmap_base;
 	info.high_limit = TASK_SIZE;
+	info.random_shift = 0;
 	if (filp || (flags & MAP_SHARED))
 		info.align_mask = MMAP_ALIGN_MASK << PAGE_SHIFT;
 	else
@@ -146,6 +147,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 	info.length = len;
 	info.low_limit = max(PAGE_SIZE, mmap_min_addr);
 	info.high_limit = mm->mmap_base;
+	info.random_shift = 0;
 	if (filp || (flags & MAP_SHARED))
 		info.align_mask = MMAP_ALIGN_MASK << PAGE_SHIFT;
 	else
arch/sh/mm/mmap.c +2 -0
index 6a1a129..d9206c2 100644
@@ -74,6 +74,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
 	info.high_limit = TASK_SIZE;
 	info.align_mask = do_colour_align ? (PAGE_MASK & shm_align_mask) : 0;
 	info.align_offset = pgoff << PAGE_SHIFT;
+	info.random_shift = 0;
 	return vm_unmapped_area(&info);
 }
 
@@ -124,6 +125,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 	info.high_limit = mm->mmap_base;
 	info.align_mask = do_colour_align ? (PAGE_MASK & shm_align_mask) : 0;
 	info.align_offset = pgoff << PAGE_SHIFT;
+	info.random_shift = 0;
 	addr = vm_unmapped_area(&info);
 
 	/*
arch/sparc/kernel/sys_sparc_32.c +1 -0
index 990703b7..af664ba3 100644
@@ -66,6 +66,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
 	info.align_mask = (flags & MAP_SHARED) ?
 		(PAGE_MASK & (SHMLBA - 1)) : 0;
 	info.align_offset = pgoff << PAGE_SHIFT;
+	info.random_shift = 0;
 	return vm_unmapped_area(&info);
 }
 
arch/sparc/kernel/sys_sparc_64.c +2 -0
index 55416db..3d12e3d 100644
@@ -131,6 +131,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
 	info.high_limit = min(task_size, VA_EXCLUDE_START);
 	info.align_mask = do_color_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
 	info.align_offset = pgoff << PAGE_SHIFT;
+	info.random_shift = 0;
 	addr = vm_unmapped_area(&info);
 
 	if ((addr & ~PAGE_MASK) && task_size > VA_EXCLUDE_END) {
@@ -194,6 +195,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 	info.high_limit = mm->mmap_base;
 	info.align_mask = do_color_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
 	info.align_offset = pgoff << PAGE_SHIFT;
+	info.random_shift = 0;
 	addr = vm_unmapped_area(&info);
 
 	/*
arch/sparc/mm/hugetlbpage.c +2 -0
index 0112d69..6d0c032 100644
@@ -43,6 +43,7 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *filp,
 	info.high_limit = min(task_size, VA_EXCLUDE_START);
 	info.align_mask = PAGE_MASK & ~huge_page_mask(h);
 	info.align_offset = 0;
+	info.random_shift = 0;
 	addr = vm_unmapped_area(&info);
 
 	if ((addr & ~PAGE_MASK) && task_size > VA_EXCLUDE_END) {
@@ -75,6 +76,7 @@ hugetlb_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 	info.high_limit = mm->mmap_base;
 	info.align_mask = PAGE_MASK & ~huge_page_mask(h);
 	info.align_offset = 0;
+	info.random_shift = 0;
 	addr = vm_unmapped_area(&info);
 
 	/*
arch/tile/mm/hugetlbpage.c +2 -0
index 0986d42..2b3a9b6 100644
@@ -176,6 +176,7 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file,
 	info.high_limit = TASK_SIZE;
 	info.align_mask = PAGE_MASK & ~huge_page_mask(h);
 	info.align_offset = 0;
+	info.random_shift = 0;
 	return vm_unmapped_area(&info);
 }
 
@@ -193,6 +194,7 @@ static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file,
 	info.high_limit = current->mm->mmap_base;
 	info.align_mask = PAGE_MASK & ~huge_page_mask(h);
 	info.align_offset = 0;
+	info.random_shift = 0;
 	addr = vm_unmapped_area(&info);
 
 	/*
arch/x86/kernel/sys_x86_64.c +4 -0
index 676774b..0eda047 100644
@@ -163,6 +163,8 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
 	info.high_limit = end;
 	info.align_mask = 0;
 	info.align_offset = pgoff << PAGE_SHIFT;
+	info.random_shift = in_compat_syscall() ?
+		256 : 0x1000000;
 	if (filp) {
 		info.align_mask = get_align_mask();
 		info.align_offset += get_align_bits();
@@ -224,6 +226,8 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 
 	info.align_mask = 0;
 	info.align_offset = pgoff << PAGE_SHIFT;
+	info.random_shift = in_compat_syscall() ?
+		256 : 0x1000000;
 	if (filp) {
 		info.align_mask = get_align_mask();
 		info.align_offset += get_align_bits();
arch/x86/mm/hugetlbpage.c +4 -0
index 00b2966..f4f6436 100644
@@ -97,6 +97,8 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file,
 
 	info.align_mask = PAGE_MASK & ~huge_page_mask(h);
 	info.align_offset = 0;
+	info.random_shift = in_compat_syscall() ?
+		256 : 0x1000000;
 	return vm_unmapped_area(&info);
 }
 
@@ -121,6 +123,8 @@ static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file,
 
 	info.align_mask = PAGE_MASK & ~huge_page_mask(h);
 	info.align_offset = 0;
+	info.random_shift = in_compat_syscall() ?
+		256 : 0x1000000;
 	addr = vm_unmapped_area(&info);
 
 	/*
fs/hugetlbfs/inode.c +1 -0
index 8fe1b0a..83e962e 100644
@@ -200,6 +200,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
 	info.high_limit = TASK_SIZE;
 	info.align_mask = PAGE_MASK & ~huge_page_mask(h);
 	info.align_offset = 0;
+	info.random_shift = 0;
 	return vm_unmapped_area(&info);
 }
 #endif
include/linux/mm.h +1 -0
index c716257..f869e6d 100644
@@ -2252,6 +2252,7 @@ struct vm_unmapped_area_info {
 	unsigned long high_limit;
 	unsigned long align_mask;
 	unsigned long align_offset;
+	unsigned long random_shift;
 };
 
 #ifndef CONFIG_MMU
mm/mmap.c +2 -1
index ba9cebb..425fa09 100644
@@ -1938,7 +1938,7 @@ unsigned long unmapped_area_random(struct vm_unmapped_area_info *info)
 	if (gap_end =  gap_start)
 		return gap_start;
 	addr = entropy[1] % (min((gap_end - gap_start) >> PAGE_SHIFT,
-							 0x10000UL));
+							 info->random_shift));
 	addr = gap_end - (addr << PAGE_SHIFT);
 	addr += (info->align_offset - addr) & info->align_mask;
 	return addr;
@@ -2186,6 +2186,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
 	info.low_limit = mm->mmap_base;
 	info.high_limit = TASK_SIZE;
 	info.align_mask = 0;
+	info.random_shift = 0;
 	return vm_unmapped_area(&info);
 }
 #endif
Signature · 1 line
2.7.4
maintainer
#5 lore raw

Re: [RFC PATCH v2 2/2] Architecture defined limit on memory region random shift.

Please add changelogs. An explanation of what a "limit on memory region random shift" is would be nice ;) Why does it exist, why are we doing this, etc. Surely there's something to be said - at present this is just a lump of random code?

author
#6 lore raw

Re: [RFC PATCH v2 2/2] Architecture defined limit on memory region random shift.

Quoted 9 lines · Andrew Morton

Please add changelogs. An explanation of what a "limit on memory region random shift" is would be nice ;) Why does it exist, why are we doing this, etc. Surely there's something to be said - at present this is just a lump of random code?

Sorry, my bad. The main idea of this limit is to decrease possible memory fragmentation. This is not so big problem on 64bit process, but really big for 32 bit processes since may cause failure memory allocation. To control memory fragmentation and protect 32 bit systems (or architectures) this limit was introduce by this patch. It could be also moved to CONFIG_ as well.

author
#7 lore raw

Re: [RFC PATCH v2 2/2] Architecture defined limit on memory region random shift.

In reply to Andrew Morton
Quoted 11 lines · Andrew Morton

Please add changelogs. An explanation of what a "limit on memory region random shift" is would be nice ;) Why does it exist, why are we doing this, etc. Surely there's something to be said - at present this is just a lump of random code?

Sorry, my bad. The main idea of this limit is to decrease possible memory fragmentation. This is not so big problem on 64bit process, but really big for 32 bit processes since may cause failure memory allocation. To control memory fragmentation and protect 32 bit systems (or architectures) this limit was introduce by this patch. It could be also moved to CONFIG_ as well.

maintainer
#8 lore raw
In reply to Ilya Smith
Quoted 4 lines · On Thu, 22 Mar 2018 19:36:36 +0300 Ilya Smith <[email protected]> wrote:

Current implementation doesn't randomize address returned by mmap. All the entropy ends with choosing mmap_base_addr at the process creation. After that mmap build very predictable layout of address space. It allows to bypass ASLR in many cases.

Perhaps some more effort on the problem description would help. *Are* people predicting layouts at present? What problems does this cause? How are they doing this and are there other approaches to solving the problem?

Mainly: what value does this patchset have to our users? This reader is unable to determine that from the information which you have provided. Full details, please.

author
#9 lore raw

Hello, Andrew

Thanks for reading this patch.

Quoted 9 lines · Andrew Morton
Quoted 4 lines · On Thu, 22 Mar 2018 19:36:36 +0300 Ilya Smith <[email protected]> wrote:

Current implementation doesn't randomize address returned by mmap. All the entropy ends with choosing mmap_base_addr at the process creation. After that mmap build very predictable layout of address space. It allows to bypass ASLR in many cases.

Quoted 5 lines

Perhaps some more effort on the problem description would help. *Are* people predicting layouts at present? What problems does this cause? How are they doing this and are there other approaches to solving the problem?

Sorry, I’ve lost it in first version. In short - memory layout could be easily repaired by single leakage. Also any Out of Bounds error may easily be exploited according to current implementation. All because mmap choose address just before previously allocated segment. You can read more about it here:
http://www.openwall.com/lists/oss-security/2018/02/27/5
Some test are available here https://github.com/blackzert/aslur.
To solve the problem Kernel should randomize address on any mmap so attacker could never easily gain needed addresses.

Quoted 3 lines

Mainly: what value does this patchset have to our users? This reader is unable to determine that from the information which you have provided. Full details, please.

The value of this patch is to decrease successful rate of exploitation vulnerable applications.These could be either remote or local vectors.

#10 lore raw
In reply to Ilya Smith
Quoted 5 lines · Ilya Smith

Current implementation doesn't randomize address returned by mmap. All the entropy ends with choosing mmap_base_addr at the process creation. After that mmap build very predictable layout of address space. It allows to bypass ASLR in many cases. This patch make randomization of address on any mmap call.

Why should this be done in the kernel rather than libc? libc is perfectly capable of specifying random numbers in the first argument of mmap.

author
#11 lore raw
Quoted 12 lines · Matthew Wilcox
Quoted 5 lines · Ilya Smith

Current implementation doesn't randomize address returned by mmap. All the entropy ends with choosing mmap_base_addr at the process creation. After that mmap build very predictable layout of address space. It allows to bypass ASLR in many cases. This patch make randomization of address on any mmap call.

Why should this be done in the kernel rather than libc? libc is perfectly capable of specifying random numbers in the first argument of mmap.

Well, there is following reasons:
1. It should be done in any libc implementation, what is not possible IMO;
2. User mode is not that layer which should be responsible for choosing random address or handling entropy;
3. Memory fragmentation is unpredictable in this case

Off course user mode could use random ‘hint’ address, but kernel may discard this address if it is occupied for example and allocate just before closest vma. So this solution doesn’t give that much security like randomization address inside kernel.

#12 lore raw
Quoted 10 lines · Ilya Smith
Quoted 10 lines · Matthew Wilcox
Quoted 5 lines · Ilya Smith

Current implementation doesn't randomize address returned by mmap. All the entropy ends with choosing mmap_base_addr at the process creation. After that mmap build very predictable layout of address space. It allows to bypass ASLR in many cases. This patch make randomization of address on any mmap call.

Quoted 4 lines
Quoted 2 lines

Why should this be done in the kernel rather than libc? libc is perfectly capable of specifying random numbers in the first argument of mmap.

Well, there is following reasons:
1. It should be done in any libc implementation, what is not possible IMO;

Is this really so helpful?

Quoted 2 lines

2. User mode is not that layer which should be responsible for choosing random address or handling entropy;

Why?

Quoted 6 lines

3. Memory fragmentation is unpredictable in this case

Off course user mode could use random ‘hint’ address, but kernel may discard this address if it is occupied for example and allocate just before closest vma. So this solution doesn’t give that much security like randomization address inside kernel.

The userspace can use the new MAP_FIXED_NOREPLACE to probe for the address range atomically and chose a different range on failure.

Signature · 2 lines
Michal Hocko
SUSE Labs
author
#13 lore raw
Quoted 14 lines · Michal Hocko
Quoted 10 lines · Ilya Smith
Quoted 10 lines · Matthew Wilcox
Quoted 5 lines · Ilya Smith

Current implementation doesn't randomize address returned by mmap. All the entropy ends with choosing mmap_base_addr at the process creation. After that mmap build very predictable layout of address space. It allows to bypass ASLR in many cases. This patch make randomization of address on any mmap call.

Quoted 6 lines
Quoted 4 lines
Quoted 2 lines

Why should this be done in the kernel rather than libc? libc is perfectly capable of specifying random numbers in the first argument of mmap.

Well, there is following reasons:
1. It should be done in any libc implementation, what is not possible IMO;

Is this really so helpful?

Yes, ASLR is one of very important mitigation techniques which are really used to protect applications. If there is no ASLR, it is very easy to exploit vulnerable application and compromise the system. We can’t just fix all the vulnerabilities right now, thats why we have mitigations - techniques which are makes exploitation more hard or impossible in some cases.

Thats why it is helpful.

Quoted 5 lines
Quoted 3 lines

2. User mode is not that layer which should be responsible for choosing random address or handling entropy;

Why?

Because of the following reasons:
1. To get random address you should have entropy. These entropy shouldn’t be exposed to attacker anyhow, the best case is to get it from kernel. So this is a syscall.
2. You should have memory map of your process to prevent remapping or big fragmentation. Kernel already has this map. You will got another one in libc. And any non-libc user of mmap (via syscall, etc) will make hole in your map. This one also decrease performance cause you any way call syscall_mmap which will try to find some address for you in worst case, but after you already did some computing on it.
3. The more memory you use in userland for these proposal, the easier for attacker to leak it or use in exploitation techniques.
4. It is so easy to fix Kernel function and so hard to support memory management from userspace.

Quoted 11 lines
Quoted 7 lines

3. Memory fragmentation is unpredictable in this case

Off course user mode could use random ‘hint’ address, but kernel may discard this address if it is occupied for example and allocate just before closest vma. So this solution doesn’t give that much security like randomization address inside kernel.

The userspace can use the new MAP_FIXED_NOREPLACE to probe for the address range atomically and chose a different range on failure.

This algorithm should track current memory. If he doesn’t he may cause infinite loop while trying to choose memory. And each iteration increase time needed on allocation new memory, what is not preferred by any libc library developer.

Thats why I did this patch.

Thanks,
Ilya

#14 lore raw
Quoted 21 lines · Ilya Smith
Quoted 14 lines · Michal Hocko
Quoted 10 lines · Ilya Smith
Quoted 10 lines · Matthew Wilcox
Quoted 5 lines · Ilya Smith

Current implementation doesn't randomize address returned by mmap. All the entropy ends with choosing mmap_base_addr at the process creation. After that mmap build very predictable layout of address space. It allows to bypass ASLR in many cases. This patch make randomization of address on any mmap call.

Quoted 6 lines
Quoted 4 lines
Quoted 2 lines

Why should this be done in the kernel rather than libc? libc is perfectly capable of specifying random numbers in the first argument of mmap.

Well, there is following reasons:
1. It should be done in any libc implementation, what is not possible IMO;

Is this really so helpful?

Quoted 7 lines

Yes, ASLR is one of very important mitigation techniques which are really used to protect applications. If there is no ASLR, it is very easy to exploit vulnerable application and compromise the system. We can’t just fix all the vulnerabilities right now, thats why we have mitigations - techniques which are makes exploitation more hard or impossible in some cases.

Thats why it is helpful.

I am not questioning ASLR in general. I am asking whether we really need per mmap ASLR in general. I can imagine that some environments want to pay the additional price and other side effects, but considering this can be achieved by libc, why to add more code to the kernel?

Quoted 10 lines
Quoted 5 lines
Quoted 3 lines

2. User mode is not that layer which should be responsible for choosing random address or handling entropy;

Why?

Because of the following reasons:
1. To get random address you should have entropy. These entropy shouldn’t be exposed to attacker anyhow, the best case is to get it from kernel. So this is a syscall.

/dev/[u]random is not sufficient?

Quoted 2 lines

2. You should have memory map of your process to prevent remapping or big fragmentation. Kernel already has this map.

/proc/self/maps?

Quoted 5 lines

You will got another one in libc.
And any non-libc user of mmap (via syscall, etc) will make hole in your map. This one also decrease performance cause you any way call syscall_mmap which will try to find some address for you in worst case, but after you already did some computing on it.

I do not understand. a) you should be prepared to pay an additional price for an additional security measures and b) how would anybody punch a hole into your mapping?

Quoted 2 lines

3. The more memory you use in userland for these proposal, the easier for attacker to leak it or use in exploitation techniques.

This is true in general, isn't it? I fail to see how kernel chosen and user chosen ranges would make any difference.

Quoted 2 lines

4. It is so easy to fix Kernel function and so hard to support memory management from userspace.

Well, on the other hand the new layout mode will add a maintenance burden on the kernel and will have to be maintained for ever because it is a user visible ABI.

Quoted 7 lines
Quoted 7 lines
Quoted 6 lines

3. Memory fragmentation is unpredictable in this case

Off course user mode could use random ‘hint’ address, but kernel may discard this address if it is occupied for example and allocate just before closest vma. So this solution doesn’t give that much security like randomization address inside kernel.

Quoted 8 lines
Quoted 3 lines

The userspace can use the new MAP_FIXED_NOREPLACE to probe for the address range atomically and chose a different range on failure.

This algorithm should track current memory. If he doesn’t he may cause infinite loop while trying to choose memory. And each iteration increase time needed on allocation new memory, what is not preferred by any libc library developer.

Well, I am pretty sure userspace can implement proper free ranges tracking...

Signature · 2 lines
Michal Hocko
SUSE Labs
author
#15 lore raw
Quoted 31 lines · Michal Hocko
Quoted 27 lines · Ilya Smith
Quoted 14 lines · Michal Hocko
Quoted 10 lines · Ilya Smith
Quoted 10 lines · Matthew Wilcox
Quoted 5 lines · Ilya Smith

Current implementation doesn't randomize address returned by mmap. All the entropy ends with choosing mmap_base_addr at the process creation. After that mmap build very predictable layout of address space. It allows to bypass ASLR in many cases. This patch make randomization of address on any mmap call.

Quoted 6 lines
Quoted 4 lines
Quoted 2 lines

Why should this be done in the kernel rather than libc? libc is perfectly capable of specifying random numbers in the first argument of mmap.

Well, there is following reasons:
1. It should be done in any libc implementation, what is not possible IMO;

Is this really so helpful?

Yes, ASLR is one of very important mitigation techniques which are really used to protect applications. If there is no ASLR, it is very easy to exploit vulnerable application and compromise the system. We can’t just fix all the vulnerabilities right now, thats why we have mitigations - techniques which are makes exploitation more hard or impossible in some cases.

Quoted 6 lines
Quoted 1 line

Thats why it is helpful.

I am not questioning ASLR in general. I am asking whether we really need per mmap ASLR in general. I can imagine that some environments want to pay the additional price and other side effects, but considering this can be achieved by libc, why to add more code to the kernel?

I believe this is the only one right place for it. Adding these 200+ lines of code we give this feature for any user - on desktop, on server, on IoT device, on SCADA, etc. But if only glibc will implement ‘user-mode-aslr’ IoT and SCADA devices will never get it.

Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 3 lines

2. User mode is not that layer which should be responsible for choosing random address or handling entropy;

Quoted 8 lines
Quoted 6 lines
Quoted 1 line

Why?

Because of the following reasons:
1. To get random address you should have entropy. These entropy shouldn’t be exposed to attacker anyhow, the best case is to get it from kernel. So this is a syscall.

/dev/[u]random is not sufficient?

Using /dev/[u]random makes 3 syscalls - open, read, close. This is a performance issue.

Quoted 5 lines
Quoted 3 lines

2. You should have memory map of your process to prevent remapping or big fragmentation. Kernel already has this map.

/proc/self/maps?

Not any system has /proc and parsing /proc/self/maps is robust so it is the performance issue. libc will have to do it on any mmap. And there is a possible race here - application may mmap/unmap memory with native syscall during other thread reading maps.

Quoted 10 lines
Quoted 5 lines

You will got another one in libc.
And any non-libc user of mmap (via syscall, etc) will make hole in your map. This one also decrease performance cause you any way call syscall_mmap which will try to find some address for you in worst case, but after you already did some computing on it.

I do not understand. a) you should be prepared to pay an additional price for an additional security measures and b) how would anybody punch a hole into your mapping?

I was talking about any code that call mmap directly without libc wrapper.

Quoted 5 lines
Quoted 2 lines

3. The more memory you use in userland for these proposal, the easier for attacker to leak it or use in exploitation techniques.

This is true in general, isn't it? I fail to see how kernel chosen and user chosen ranges would make any difference.

My point here was that libc will have to keep memory representation as a tree and this tree increase attack surface. It could be hidden in kernel as it is right now.

Quoted 7 lines
Quoted 3 lines

4. It is so easy to fix Kernel function and so hard to support memory management from userspace.

Well, on the other hand the new layout mode will add a maintenance burden on the kernel and will have to be maintained for ever because it is a user visible ABI.

Thats why I made this patch as RFC and would like to discuss this ABI here. I made randomize_va_space parameter to allow disable randomisation per whole system. PF_RANDOMIZE flag may disable randomization for concrete process (or process groups?). For architecture I’ve made info.random_shift = 0 , so if your arch has small address space you may disable shifting. I also would like to add some sysctl to allow process/groups to change this value and allow some processes to have shifts bigger then another. Lets discuss it, please.

Quoted 12 lines
Quoted 12 lines
Quoted 11 lines
Quoted 7 lines

3. Memory fragmentation is unpredictable in this case

Off course user mode could use random ‘hint’ address, but kernel may discard this address if it is occupied for example and allocate just before closest vma. So this solution doesn’t give that much security like randomization address inside kernel.

The userspace can use the new MAP_FIXED_NOREPLACE to probe for the address range atomically and chose a different range on failure.

Quoted 7 lines
Quoted 4 lines

This algorithm should track current memory. If he doesn’t he may cause infinite loop while trying to choose memory. And each iteration increase time needed on allocation new memory, what is not preferred by any libc library developer.

Well, I am pretty sure userspace can implement proper free ranges tracking…

I think we need to know what libc developers will say on implementing ASLR in user-mode. I am pretty sure they will say ‘nether’ or ‘some-day’. And problem of ASLR will stay forever.

Thanks,
Ilya

#16 lore raw
Quoted 38 lines · Ilya Smith
Quoted 31 lines · Michal Hocko
Quoted 27 lines · Ilya Smith
Quoted 14 lines · Michal Hocko
Quoted 10 lines · Ilya Smith
Quoted 10 lines · Matthew Wilcox
Quoted 5 lines · Ilya Smith

Current implementation doesn't randomize address returned by mmap. All the entropy ends with choosing mmap_base_addr at the process creation. After that mmap build very predictable layout of address space. It allows to bypass ASLR in many cases. This patch make randomization of address on any mmap call.

Quoted 6 lines
Quoted 4 lines
Quoted 2 lines

Why should this be done in the kernel rather than libc? libc is perfectly capable of specifying random numbers in the first argument of mmap.

Well, there is following reasons:
1. It should be done in any libc implementation, what is not possible IMO;

Is this really so helpful?

Yes, ASLR is one of very important mitigation techniques which are really used to protect applications. If there is no ASLR, it is very easy to exploit vulnerable application and compromise the system. We can’t just fix all the vulnerabilities right now, thats why we have mitigations - techniques which are makes exploitation more hard or impossible in some cases.

Quoted 6 lines
Quoted 1 line

Thats why it is helpful.

I am not questioning ASLR in general. I am asking whether we really need per mmap ASLR in general. I can imagine that some environments want to pay the additional price and other side effects, but considering this can be achieved by libc, why to add more code to the kernel?

Quoted 4 lines

I believe this is the only one right place for it. Adding these 200+ lines of code we give this feature for any user - on desktop, on server, on IoT device, on SCADA, etc. But if only glibc will implement ‘user-mode-aslr’ IoT and SCADA devices will never get it.

I guess it would really help if you could be more specific about the class of security issues this would help to mitigate. My first understanding was that we we need some randomization between program executable segments to reduce the attack space when a single address leaks and you know the segments layout (ordering). But why do we need _all_ mmaps to be randomized. Because that complicates the implementation consirably for different reasons you have mentioned earlier.

Do you have any specific CVE that would be mitigated by this randomization approach?

I am sorry, I am not a security expert to see all the cosequences but a vague - the more randomization the better - sounds rather weak to me.

Signature · 2 lines
Michal Hocko
SUSE Labs
author
#17 lore raw
Quoted 47 lines · Michal Hocko
Quoted 38 lines · Ilya Smith
Quoted 31 lines · Michal Hocko
Quoted 27 lines · Ilya Smith
Quoted 14 lines · Michal Hocko
Quoted 10 lines · Ilya Smith
Quoted 10 lines · Matthew Wilcox
Quoted 5 lines · Ilya Smith

Current implementation doesn't randomize address returned by mmap. All the entropy ends with choosing mmap_base_addr at the process creation. After that mmap build very predictable layout of address space. It allows to bypass ASLR in many cases. This patch make randomization of address on any mmap call.

Quoted 6 lines
Quoted 4 lines
Quoted 2 lines

Why should this be done in the kernel rather than libc? libc is perfectly capable of specifying random numbers in the first argument of mmap.

Well, there is following reasons:
1. It should be done in any libc implementation, what is not possible IMO;

Is this really so helpful?

Yes, ASLR is one of very important mitigation techniques which are really used to protect applications. If there is no ASLR, it is very easy to exploit vulnerable application and compromise the system. We can’t just fix all the vulnerabilities right now, thats why we have mitigations - techniques which are makes exploitation more hard or impossible in some cases.

Quoted 6 lines
Quoted 1 line

Thats why it is helpful.

I am not questioning ASLR in general. I am asking whether we really need per mmap ASLR in general. I can imagine that some environments want to pay the additional price and other side effects, but considering this can be achieved by libc, why to add more code to the kernel?

Quoted 4 lines

I believe this is the only one right place for it. Adding these 200+ lines of code we give this feature for any user - on desktop, on server, on IoT device, on SCADA, etc. But if only glibc will implement ‘user-mode-aslr’ IoT and SCADA devices will never get it.

Quoted 9 lines

I guess it would really help if you could be more specific about the class of security issues this would help to mitigate. My first understanding was that we we need some randomization between program executable segments to reduce the attack space when a single address leaks and you know the segments layout (ordering). But why do we need _all_ mmaps to be randomized. Because that complicates the implementation consirably for different reasons you have mentioned earlier.

There are following reasons:
1) To protect layout if one region was leaked (as you said).
2) To protect against exploitation of Out-of-bounds vulnerabilities in some cases (CWE-125 , CWE-787)
3) To protect against exploitation of Buffer Overflows in some cases (CWE-120)
4) To protect application in cases when attacker need to guess the address (paper ASLR-NG by Hector Marco-Gisbert and Ismael Ripoll-Ripoll) And may be more cases.

Quoted 4 lines

Do you have any specific CVE that would be mitigated by this randomization approach?
I am sorry, I am not a security expert to see all the cosequences but a vague - the more randomization the better - sounds rather weak to me.

It is hard to name concrete CVE number, sorry. Mitigations are made to prevent exploitation but not to fix vulnerabilities. It means good mitigation will make vulnerable application crash but not been compromised in most cases. This means the better randomization, the less successful exploitation rate.

Thanks,
Ilya

#18 lore raw
In reply to Ilya Smith
Quoted 4 lines · Ilya Smith
Quoted 1 line

/dev/[u]random is not sufficient?

Using /dev/[u]random makes 3 syscalls - open, read, close. This is a performance issue.

You may want to take a look at the getrandom(2) system call, which is the recommended way getting secure random numbers from the kernel.

Quoted 6 lines
Quoted 2 lines

Well, I am pretty sure userspace can implement proper free ranges tracking…

I think we need to know what libc developers will say on implementing ASLR in user-mode. I am pretty sure they will say ‘nether’ or ‘some-day’. And problem of ASLR will stay forever.

Why can't you send patches to the libc developers?

Regards,

- Ted

maintainer
#19 lore raw
Quoted 8 lines · Theodore Y. Ts'o
Quoted 4 lines · Ilya Smith
Quoted 1 line

/dev/[u]random is not sufficient?

Using /dev/[u]random makes 3 syscalls - open, read, close. This is a performance issue.

You may want to take a look at the getrandom(2) system call, which is the recommended way getting secure random numbers from the kernel.

Yes, while opening /dev/urandom is not acceptable due to needing an fd, getrandom and existing fallbacks for it have this covered if needed.

Quoted 8 lines
Quoted 6 lines
Quoted 2 lines

Well, I am pretty sure userspace can implement proper free ranges tracking…

I think we need to know what libc developers will say on implementing ASLR in user-mode. I am pretty sure they will say ‘nether’ or ‘some-day’. And problem of ASLR will stay forever.

Why can't you send patches to the libc developers?

I can tell you right now that any patch submitted for musl that depended on trying to duplicate knowledge of the entire virtual address space layout in userspace as part of mmap would be rejected, and I would recommend glibc do the same.

Not only does it vastly increase complexity; it also has all sorts of failure modes (fd exhastion, etc.) which would either introduce new and unwanted ways for mmap to fail, or would force fallback to the normal (no extra randomization) strategy under conditions an attacker could potentially control, defeating the whole purpose. It would also potentially make it easier for an attacker to examine the vm layout for attacks, since it would be recorded in userspace.

There's also the issue of preserving AS-safety of mmap. POSIX does not actually require mmap to be AS-safe, and on musl munmap is not fully AS-safe anyway because of some obscure issues it compensates for, but we may be able to make it AS-safe (this is a low-priority open issue). If mmap were manipulating data structures representing the vm space in userspace, though, the only way to make it anywhere near AS-safe would be to block all signals and take a lock every time mmap or munmap is called. This would significantly increase the cost of each call, especially now that meltdown/spectre mitigations have greatly increased the overhead of each syscall.

Overall, asking userspace to take a lead role in management of process vm space is a radical change in the split of what user and kernel are responsible for, and it really does not make sense as part of a dubious hardening measure. Something this big would need to be really well-motivated.

Rich

author
#20 lore raw
In reply to Theodore Y. Ts'o
Quoted 18 lines · Theodore Y. Ts'o
Quoted 4 lines · Ilya Smith
Quoted 1 line

/dev/[u]random is not sufficient?

Using /dev/[u]random makes 3 syscalls - open, read, close. This is a performance issue.

You may want to take a look at the getrandom(2) system call, which is the recommended way getting secure random numbers from the kernel.

Quoted 6 lines
Quoted 2 lines

Well, I am pretty sure userspace can implement proper free ranges tracking…

I think we need to know what libc developers will say on implementing ASLR in user-mode. I am pretty sure they will say ‘nether’ or ‘some-day’. And problem of ASLR will stay forever.

Quoted 5 lines

Why can't you send patches to the libc developers?

Regards,

- Ted

I still believe the issue is on kernel side, not in library.

Best regards,
Ilya

#21 lore raw
In reply to Ilya Smith
Quoted 38 lines · Ilya Smith
Quoted 31 lines · Michal Hocko
Quoted 27 lines · Ilya Smith
Quoted 14 lines · Michal Hocko
Quoted 10 lines · Ilya Smith
Quoted 10 lines · Matthew Wilcox
Quoted 5 lines · Ilya Smith

Current implementation doesn't randomize address returned by mmap. All the entropy ends with choosing mmap_base_addr at the process creation. After that mmap build very predictable layout of address space. It allows to bypass ASLR in many cases. This patch make randomization of address on any mmap call.

Quoted 6 lines
Quoted 4 lines
Quoted 2 lines

Why should this be done in the kernel rather than libc? libc is perfectly capable of specifying random numbers in the first argument of mmap.

Well, there is following reasons:
1. It should be done in any libc implementation, what is not possible IMO;

Is this really so helpful?

Yes, ASLR is one of very important mitigation techniques which are really used to protect applications. If there is no ASLR, it is very easy to exploit vulnerable application and compromise the system. We can’t just fix all the vulnerabilities right now, thats why we have mitigations - techniques which are makes exploitation more hard or impossible in some cases.

Quoted 6 lines
Quoted 1 line

Thats why it is helpful.

I am not questioning ASLR in general. I am asking whether we really need per mmap ASLR in general. I can imagine that some environments want to pay the additional price and other side effects, but considering this can be achieved by libc, why to add more code to the kernel?

Quoted 4 lines

I believe this is the only one right place for it. Adding these 200+ lines of code we give this feature for any user - on desktop, on server, on IoT device, on SCADA, etc. But if only glibc will implement ‘user-mode-aslr’ IoT and SCADA devices will never get it.

I agree: pushing this off to libc leaves a lot of things unprotected. I think this should live in the kernel. The question I have is about making it maintainable/readable/etc.

The state-of-the-art for ASLR is moving to finer granularity (over just base-address offset), so I'd really like to see this supported in the kernel. We'll be getting there for other things in the future, and I'd like to have a working production example for researchers to study, etc.

-Kees

Signature · 7 lines
Kees Cook
Pixel Security

_______________________________________________
linux-snps-arc mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-snps-arc
#22 lore raw
Quoted 9 lines · Kees Cook

I agree: pushing this off to libc leaves a lot of things unprotected. I think this should live in the kernel. The question I have is about making it maintainable/readable/etc.

The state-of-the-art for ASLR is moving to finer granularity (over just base-address offset), so I'd really like to see this supported in the kernel. We'll be getting there for other things in the future, and I'd like to have a working production example for researchers to study, etc.

One thing we need is to limit the fragmentation of this approach. Even on 64-bit systems, we can easily get into a situation where there isn't space to map a contiguous terabyte.

#23 lore raw
Quoted 11 lines · Matthew Wilcox
Quoted 9 lines · Kees Cook

I agree: pushing this off to libc leaves a lot of things unprotected. I think this should live in the kernel. The question I have is about making it maintainable/readable/etc.

The state-of-the-art for ASLR is moving to finer granularity (over just base-address offset), so I'd really like to see this supported in the kernel. We'll be getting there for other things in the future, and I'd like to have a working production example for researchers to study, etc.

Quoted 3 lines

One thing we need is to limit the fragmentation of this approach. Even on 64-bit systems, we can easily get into a situation where there isn't space to map a contiguous terabyte.

FWIW, I wouldn't expect normal systems to use this. I am curious about fragmentation vs entropy though. Are workloads with a mis of lots of tiny allocations and TB-allocations? AIUI, glibc uses larger mmap() regions for handling tiny mallocs().

-Kees

Signature · 2 lines
Kees Cook
Pixel Security
maintainer
#24 lore raw
In reply to Matthew Wilcox
Quoted 11 lines · Matthew Wilcox
Quoted 9 lines · Kees Cook

I agree: pushing this off to libc leaves a lot of things unprotected. I think this should live in the kernel. The question I have is about making it maintainable/readable/etc.

The state-of-the-art for ASLR is moving to finer granularity (over just base-address offset), so I'd really like to see this supported in the kernel. We'll be getting there for other things in the future, and I'd like to have a working production example for researchers to study, etc.

Quoted 3 lines

One thing we need is to limit the fragmentation of this approach. Even on 64-bit systems, we can easily get into a situation where there isn't space to map a contiguous terabyte.

The default limit of only 65536 VMAs will also quickly come into play if consecutive anon mmaps don't get merged. Of course this can be raised, but it has significant resource and performance (fork) costs.

Rich

#25 lore raw
Quoted 3 lines

The default limit of only 65536 VMAs will also quickly come into play if consecutive anon mmaps don't get merged. Of course this can be raised, but it has significant resource and performance (fork) costs.

Could the random mmap address chooser look for how many existing VMAs have space before/after and the right attributes to merge with the new one you want to create? If this is above some threshold (100?) then pick one of them randomly and allocate the new address so that it will merge from below/above with an existing one.

That should still give you a very high degree of randomness, but prevent out of control numbers of VMAs from being created.

-Tony

author
#26 lore raw
Quoted 6 lines · Tony
Quoted 4 lines

The default limit of only 65536 VMAs will also quickly come into play if consecutive anon mmaps don't get merged. Of course this can be raised, but it has significant resource and performance (fork) costs.

Quoted 8 lines

Could the random mmap address chooser look for how many existing VMAs have space before/after and the right attributes to merge with the new one you want to create? If this is above some threshold (100?) then pick one of them randomly and allocate the new address so that it will merge from below/above with an existing one.

That should still give you a very high degree of randomness, but prevent out of control numbers of VMAs from being created.

I think this wouldn’t work. For example these 100 allocation may happened on process initialization. But when attacker come to the server all his allocations would be made on the predictable offsets from each other. So in result we did nothing just decrease performance of first 100 allocations. I think I can make ioctl to turn off this randomization per process and it could be used if needed. For example if application going to allocate big chunk or make big memory pressure, etc.

Best regards,
Ilya

_______________________________________________
linux-snps-arc mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-snps-arc

author
#27 lore raw
In reply to Matthew Wilcox
Quoted 14 lines · Matthew Wilcox
Quoted 9 lines · Kees Cook

I agree: pushing this off to libc leaves a lot of things unprotected. I think this should live in the kernel. The question I have is about making it maintainable/readable/etc.

The state-of-the-art for ASLR is moving to finer granularity (over just base-address offset), so I'd really like to see this supported in the kernel. We'll be getting there for other things in the future, and I'd like to have a working production example for researchers to study, etc.

Quoted 3 lines

One thing we need is to limit the fragmentation of this approach. Even on 64-bit systems, we can easily get into a situation where there isn't space to map a contiguous terabyte.

As I wrote before, shift_random is introduced to be fragmentation limit. Even without it, the main question here is ‘if we can’t allocate memory with N size bytes, how many bytes we already allocated?’. From these point of view I already showed in previous version of patch that if application uses not so big memory allocations, it will have enough memory to use. If it uses XX Gigabytes or Terabytes memory, this application has all chances to be exploited with fully randomization or without. Since it is much easier to find(or guess) any usable pointer, etc. For the instance you have only 128 terabytes of memory for user space, so probability to exploit this application is 1/128 what is not secure at all. This is very rough estimate but I try to make things easier to understand.

Best regards,
Ilya

_______________________________________________
linux-snps-arc mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-snps-arc

maintainer
#28 lore raw
In reply to Matthew Wilcox
Quoted 9 lines · Matthew Wilcox
Quoted 5 lines · Ilya Smith

Current implementation doesn't randomize address returned by mmap. All the entropy ends with choosing mmap_base_addr at the process creation. After that mmap build very predictable layout of address space. It allows to bypass ASLR in many cases. This patch make randomization of address on any mmap call.

Why should this be done in the kernel rather than libc? libc is perfectly capable of specifying random numbers in the first argument of mmap.

Generally libc does not have a view of the current vm maps, and thus in passing "random numbers", they would have to be uniform across the whole vm space and thus non-uniform once the kernel rounds up to avoid existing mappings. Also this would impose requirements that libc be aware of the kernel's use of the virtual address space and what's available to userspace -- for example, on 32-bit archs whether 2GB, 3GB, or full 4GB (for 32-bit-user-on-64-bit-kernel) is available, and on 64-bit archs where fewer than the full 64 bits are actually valid in addresses, what the actual usable pointer size is. There is currently no clean way of conveying this information to userspace.

Rich

#29 lore raw
Quoted 8 lines · Rich Felker
Quoted 7 lines · Matthew Wilcox
Quoted 5 lines · Ilya Smith

Current implementation doesn't randomize address returned by mmap. All the entropy ends with choosing mmap_base_addr at the process creation. After that mmap build very predictable layout of address space. It allows to bypass ASLR in many cases. This patch make randomization of address on any mmap call.

Quoted 7 lines
Quoted 2 lines

Why should this be done in the kernel rather than libc? libc is perfectly capable of specifying random numbers in the first argument of mmap.

Generally libc does not have a view of the current vm maps, and thus in passing "random numbers", they would have to be uniform across the whole vm space and thus non-uniform once the kernel rounds up to avoid existing mappings.

I'm aware that you're the musl author, but glibc somehow manages to provide etext, edata and end, demonstrating that it does know where at least some of the memory map lies. Virtually everything after that is brought into the address space via mmap, which at least glibc intercepts, so it's entirely possible for a security-conscious libc to know where other things are in the memory map. Not to mention that what we're primarily talking about here are libraries which are dynamically linked and are loaded by ld.so before calling main(); not dlopen() or even regular user mmaps.

Quoted 7 lines

Also this would impose requirements that libc be
aware of the kernel's use of the virtual address space and what's available to userspace -- for example, on 32-bit archs whether 2GB, 3GB, or full 4GB (for 32-bit-user-on-64-bit-kernel) is available, and on 64-bit archs where fewer than the full 64 bits are actually valid in addresses, what the actual usable pointer size is. There is currently no clean way of conveying this information to userspace.

Huh, I thought libc was aware of this. Also, I'd expect a libc-based implementation to restrict itself to, eg, only loading libraries in the bottom 1GB to avoid applications who want to map huge things from running out of unfragmented address space.

maintainer
#30 lore raw
Quoted 12 lines · Matthew Wilcox
Quoted 11 lines · Rich Felker
Quoted 9 lines · Matthew Wilcox
Quoted 5 lines · Ilya Smith

Current implementation doesn't randomize address returned by mmap. All the entropy ends with choosing mmap_base_addr at the process creation. After that mmap build very predictable layout of address space. It allows to bypass ASLR in many cases. This patch make randomization of address on any mmap call.

Why should this be done in the kernel rather than libc? libc is perfectly capable of specifying random numbers in the first argument of mmap.

Quoted 8 lines
Quoted 4 lines

Generally libc does not have a view of the current vm maps, and thus in passing "random numbers", they would have to be uniform across the whole vm space and thus non-uniform once the kernel rounds up to avoid existing mappings.

I'm aware that you're the musl author, but glibc somehow manages to provide etext, edata and end, demonstrating that it does know where at least some of the memory map lies.

Yes, but that's pretty minimal info.

Quoted 2 lines

Virtually everything after that is
brought into the address space via mmap, which at least glibc intercepts,

There's also vdso, the program interpreter (ldso), and theoretically other things the kernel might add. I agree you _could_ track most of this (and all if you want to open /proc/self/maps), but it seems hackish and wrong (violating clean boundaries between userspace and kernel responsibility).

Quoted 8 lines
Quoted 7 lines

Also this would impose requirements that libc be
aware of the kernel's use of the virtual address space and what's available to userspace -- for example, on 32-bit archs whether 2GB, 3GB, or full 4GB (for 32-bit-user-on-64-bit-kernel) is available, and on 64-bit archs where fewer than the full 64 bits are actually valid in addresses, what the actual usable pointer size is. There is currently no clean way of conveying this information to userspace.

Quoted 4 lines

Huh, I thought libc was aware of this. Also, I'd expect a libc-based implementation to restrict itself to, eg, only loading libraries in the bottom 1GB to avoid applications who want to map huge things from running out of unfragmented address space.

That seems like a rather arbitrary expectation and I'm not sure why you'd expect it to result in less fragmentation rather than more. For example if it started from 1GB and worked down, you'd immediately reduce the contiguous free space from ~3GB to ~2GB, and if it started from the bottom and worked up, brk would immediately become unavailable, increasing mmap pressure elsewhere.

Rich

#31 lore raw
Quoted 11 lines · Rich Felker
Quoted 4 lines

Huh, I thought libc was aware of this. Also, I'd expect a libc-based implementation to restrict itself to, eg, only loading libraries in the bottom 1GB to avoid applications who want to map huge things from running out of unfragmented address space.

That seems like a rather arbitrary expectation and I'm not sure why you'd expect it to result in less fragmentation rather than more. For example if it started from 1GB and worked down, you'd immediately reduce the contiguous free space from ~3GB to ~2GB, and if it started from the bottom and worked up, brk would immediately become unavailable, increasing mmap pressure elsewhere.

By *not* limiting yourself to the bottom 1GB, you'll almost immediately fragment the address space even worse. Just looking at 'ls' as a hopefully-good example of a typical app, it maps:

	linux-vdso.so.1 (0x00007ffef5eef000)
	libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007fb3657f5000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb36543b000)
	libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007fb3651c9000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fb364fc5000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fb365c3f000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fb364da7000)

The VDSO wouldn't move, but look at the distribution of mapping 6 things into a 3GB address space in random locations. What are the odds you have a contiguous 1GB chunk of address space? If you restrict yourself to the bottom 1GB before running out of room and falling back to a sequential allocation, you'll prevent a lot of fragmentation.

maintainer
#32 lore raw
Quoted 25 lines · Matthew Wilcox
Quoted 11 lines · Rich Felker
Quoted 4 lines

Huh, I thought libc was aware of this. Also, I'd expect a libc-based implementation to restrict itself to, eg, only loading libraries in the bottom 1GB to avoid applications who want to map huge things from running out of unfragmented address space.

That seems like a rather arbitrary expectation and I'm not sure why you'd expect it to result in less fragmentation rather than more. For example if it started from 1GB and worked down, you'd immediately reduce the contiguous free space from ~3GB to ~2GB, and if it started from the bottom and worked up, brk would immediately become unavailable, increasing mmap pressure elsewhere.

By *not* limiting yourself to the bottom 1GB, you'll almost immediately fragment the address space even worse. Just looking at 'ls' as a hopefully-good example of a typical app, it maps:

	linux-vdso.so.1 (0x00007ffef5eef000)
	libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007fb3657f5000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb36543b000)
	libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007fb3651c9000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fb364fc5000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fb365c3f000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fb364da7000)
Quoted 5 lines

The VDSO wouldn't move, but look at the distribution of mapping 6 things into a 3GB address space in random locations. What are the odds you have a contiguous 1GB chunk of address space? If you restrict yourself to the bottom 1GB before running out of room and falling back to a sequential allocation, you'll prevent a lot of fragmentation.

Oh, you're talking about "with random locations" case. Randomizing each map just hopelessly fragments things no matter what you do on 32-bit. If you reduce the space over which you randomize to the point where it's not fragmenting/killing your available vm space, there are so few degrees of freedom left that it's trivial to brute-force. Maybe "libs randomized in low 1GB, everything else near-sequential in high addresses" works half decently, but I have a hard time believing you can get any ASLR that's significantly better than snake oil in a 32-bit address space, and you certainly do pay a high price in total available vm space.

Rich

#33 lore raw
In reply to Matthew Wilcox
Quoted 12 lines · Matthew Wilcox
Quoted 11 lines · Rich Felker
Quoted 9 lines · Matthew Wilcox
Quoted 5 lines · Ilya Smith

Current implementation doesn't randomize address returned by mmap. All the entropy ends with choosing mmap_base_addr at the process creation. After that mmap build very predictable layout of address space. It allows to bypass ASLR in many cases. This patch make randomization of address on any mmap call.

Why should this be done in the kernel rather than libc? libc is perfectly capable of specifying random numbers in the first argument of mmap.

Quoted 8 lines
Quoted 4 lines

Generally libc does not have a view of the current vm maps, and thus in passing "random numbers", they would have to be uniform across the whole vm space and thus non-uniform once the kernel rounds up to avoid existing mappings.

I'm aware that you're the musl author, but glibc somehow manages to provide etext, edata and end, demonstrating that it does know where at least some of the memory map lies.

You can parse /proc/self/maps, but it's really expensive and disgusting.

Rob

#34 lore raw
In reply to Ilya Smith

Hi!

Quoted 5 lines

Current implementation doesn't randomize address returned by mmap. All the entropy ends with choosing mmap_base_addr at the process creation. After that mmap build very predictable layout of address space. It allows to bypass ASLR in many cases. This patch make randomization of address on any mmap call.

How will this interact with people debugging their application, and getting different behaviours based on memory layout?

strace, strace again, get different results?

Pavel

Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
author
#35 lore raw

Hi

Quoted 10 lines · Pavel Machek

Hi!

Quoted 5 lines

Current implementation doesn't randomize address returned by mmap. All the entropy ends with choosing mmap_base_addr at the process creation. After that mmap build very predictable layout of address space. It allows to bypass ASLR in many cases. This patch make randomization of address on any mmap call.

Quoted 5 lines

How will this interact with people debugging their application, and getting different behaviours based on memory layout?

strace, strace again, get different results?

Honestly I’m confused about your question. If the only one way for debugging application is to use predictable mmap behaviour, then something went wrong in this live and we should stop using computers at all.

Thanks,
Ilya

#36 lore raw
Quoted 15 lines · Ilya Smith

Hi

Quoted 13 lines · Pavel Machek

Hi!

Quoted 5 lines

Current implementation doesn't randomize address returned by mmap. All the entropy ends with choosing mmap_base_addr at the process creation. After that mmap build very predictable layout of address space. It allows to bypass ASLR in many cases. This patch make randomization of address on any mmap call.

How will this interact with people debugging their application, and getting different behaviours based on memory layout?

Quoted 6 lines
Quoted 2 lines

strace, strace again, get different results?

Honestly I’m confused about your question. If the only one way for debugging application is to use predictable mmap behaviour, then something went wrong in this live and we should stop using computers at all.

I'm not saying "only way". I'm saying one way, and you are breaking that. There's advanced stuff like debuggers going "back in time".

Pavel

Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
author
#37 lore raw
Quoted 22 lines · Pavel Machek
Quoted 18 lines · Ilya Smith

Hi

Quoted 15 lines · Pavel Machek

Hi!

Quoted 5 lines

Current implementation doesn't randomize address returned by mmap. All the entropy ends with choosing mmap_base_addr at the process creation. After that mmap build very predictable layout of address space. It allows to bypass ASLR in many cases. This patch make randomization of address on any mmap call.

How will this interact with people debugging their application, and getting different behaviours based on memory layout?

strace, strace again, get different results?

Quoted 7 lines
Quoted 3 lines

Honestly I’m confused about your question. If the only one way for debugging application is to use predictable mmap behaviour, then something went wrong in this live and we should stop using computers at all.

I'm not saying "only way". I'm saying one way, and you are breaking that. There's advanced stuff like debuggers going "back in time".

Correct me if I wrong, when you run gdb for instance and try to debug some application, gdb will disable randomization. This behaviour works with gdb
command: set disable-randomization on. As I know, gdb remove flag PF_RANDOMIZE from current personality thats how it disables ASLR for debugging process. According to my patch, flag PF_RANDOMIZE is checked before calling unmapped_area_random. So I don’t breaking debugging. If you talking about the case, when your application crashes under customer environment and you want to debug it; in this case layout of memory is what you don’t control at all and you have to understand what is where. So for debugging memory process layout is not what you should care of.

Thanks,
Ilya

maintainer
#38 lore raw
In reply to Pavel Machek
Quoted 8 lines · Pavel Machek

Hi!

Quoted 5 lines

Current implementation doesn't randomize address returned by mmap. All the entropy ends with choosing mmap_base_addr at the process creation. After that mmap build very predictable layout of address space. It allows to bypass ASLR in many cases. This patch make randomization of address on any mmap call.

Quoted 4 lines

How will this interact with people debugging their application, and getting different behaviours based on memory layout?

strace, strace again, get different results?

Normally gdb disables ASLR for the process when invoking a program to debug. I don't see why that would be terribly useful with strace but you can do the same if you want.

Rich