struct elf_phdr *elf_ppnt, *elf_phdata, *interp_elf_phdata = NULL;
        struct elf_phdr *elf_property_phdata = NULL;
        unsigned long elf_brk;
+       bool brk_moved = false;
        int retval, i;
        unsigned long elf_entry;
        unsigned long e_entry;
                        /* Calculate any requested alignment. */
                        alignment = maximum_alignment(elf_phdata, elf_ex->e_phnum);
 
-                       /*
-                        * There are effectively two types of ET_DYN
-                        * binaries: programs (i.e. PIE: ET_DYN with PT_INTERP)
-                        * and loaders (ET_DYN without PT_INTERP, since they
-                        * _are_ the ELF interpreter). The loaders must
-                        * be loaded away from programs since the program
-                        * may otherwise collide with the loader (especially
-                        * for ET_EXEC which does not have a randomized
-                        * position). For example to handle invocations of
+                       /**
+                        * DOC: PIE handling
+                        *
+                        * There are effectively two types of ET_DYN ELF
+                        * binaries: programs (i.e. PIE: ET_DYN with
+                        * PT_INTERP) and loaders (i.e. static PIE: ET_DYN
+                        * without PT_INTERP, usually the ELF interpreter
+                        * itself). Loaders must be loaded away from programs
+                        * since the program may otherwise collide with the
+                        * loader (especially for ET_EXEC which does not have
+                        * a randomized position).
+                        *
+                        * For example, to handle invocations of
                         * "./ld.so someprog" to test out a new version of
                         * the loader, the subsequent program that the
                         * loader loads must avoid the loader itself, so
                         * ELF_ET_DYN_BASE and loaders are loaded into the
                         * independently randomized mmap region (0 load_bias
                         * without MAP_FIXED nor MAP_FIXED_NOREPLACE).
+                        *
+                        * See below for "brk" handling details, which is
+                        * also affected by program vs loader and ASLR.
                         */
                        if (interpreter) {
                                /* On ET_DYN with PT_INTERP, we do the ASLR. */
        start_data += load_bias;
        end_data += load_bias;
 
-       current->mm->start_brk = current->mm->brk = ELF_PAGEALIGN(elf_brk);
-
        if (interpreter) {
                elf_entry = load_elf_interp(interp_elf_ex,
                                            interpreter,
        mm->end_data = end_data;
        mm->start_stack = bprm->p;
 
-       if ((current->flags & PF_RANDOMIZE) && (snapshot_randomize_va_space > 1)) {
+       /**
+        * DOC: "brk" handling
+        *
+        * For architectures with ELF randomization, when executing a
+        * loader directly (i.e. static PIE: ET_DYN without PT_INTERP),
+        * move the brk area out of the mmap region and into the unused
+        * ELF_ET_DYN_BASE region. Since "brk" grows up it may collide
+        * early with the stack growing down or other regions being put
+        * into the mmap region by the kernel (e.g. vdso).
+        *
+        * In the CONFIG_COMPAT_BRK case, though, everything is turned
+        * off because we're not allowed to move the brk at all.
+        */
+       if (!IS_ENABLED(CONFIG_COMPAT_BRK) &&
+           IS_ENABLED(CONFIG_ARCH_HAS_ELF_RANDOMIZE) &&
+           elf_ex->e_type == ET_DYN && !interpreter) {
+               elf_brk = ELF_ET_DYN_BASE;
+               /* This counts as moving the brk, so let brk(2) know. */
+               brk_moved = true;
+       }
+       mm->start_brk = mm->brk = ELF_PAGEALIGN(elf_brk);
+
+       if ((current->flags & PF_RANDOMIZE) && snapshot_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 we didn't move the brk to ELF_ET_DYN_BASE (above),
+                * leave a gap between .bss and brk.
                 */
-               if (IS_ENABLED(CONFIG_ARCH_HAS_ELF_RANDOMIZE) &&
-                   elf_ex->e_type == ET_DYN && !interpreter) {
-                       mm->brk = mm->start_brk = ELF_ET_DYN_BASE;
-               } else {
-                       /* Otherwise leave a gap between .bss and brk. */
+               if (!brk_moved)
                        mm->brk = mm->start_brk = mm->brk + PAGE_SIZE;
-               }
 
                mm->brk = mm->start_brk = arch_randomize_brk(mm);
+               brk_moved = true;
+       }
+
 #ifdef compat_brk_randomized
+       if (brk_moved)
                current->brk_randomized = 1;
 #endif
-       }
 
        if (current->personality & MMAP_PAGE_ZERO) {
                /* Why this, you ask???  Well SVr4 maps page 0 as read-only,