There has to be a specific way of randomizing brk() as well, as there are some heap implementations other than glibc's default (ptmalloc) that might not rely on brk(), leaving direct use of brk() unprotected to predictable address space if only va_randomize_space = 1 is used.
This is also important because attackers could craft shellcodes using direct SYS_brk system calls to map memory with a predicted address space to work on.
A quick look into the Linux kernel source code suggests setting ASLR to mode 2 does only just that: randomizes the start of the dynamic memory mapping address space:
https://github.com/torvalds/linux/blob/master/fs/binfmt_elf.c#L1110-L1123
<!-- language: lang-c -->
if ((current->flags & PF_RANDOMIZE) && (randomize_va_space > 1)) {
/*
* For architectures with ELF randomization, when executing
* a loader directly (i.e. no interpreter listed in ELF
* headers), move the brk area out of the mmap region
* (since it grows up, and may collide early with the stack
* growing down), and into the unused ELF_ET_DYN_BASE region.
*/
if (IS_ENABLED(CONFIG_ARCH_HAS_ELF_RANDOMIZE) &&
elf_ex->e_type == ET_DYN && !interpreter) {
mm->brk = mm->start_brk = ELF_ET_DYN_BASE;
}
mm->brk = mm->start_brk = arch_randomize_brk(mm);
#ifdef compat_brk_randomized
current->brk_randomized = 1;
#endif
}
https://github.com/torvalds/linux/blob/master/mm/mmap.c#L212-L213
<!-- language: lang-c -->
if (current->brk_randomized)
min_brk = mm->start_brk;