@@ -830,6 +830,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
830830 struct elf_phdr * elf_ppnt , * elf_phdata , * interp_elf_phdata = NULL ;
831831 struct elf_phdr * elf_property_phdata = NULL ;
832832 unsigned long elf_brk ;
833+ bool brk_moved = false;
833834 int retval , i ;
834835 unsigned long elf_entry ;
835836 unsigned long e_entry ;
@@ -1097,15 +1098,19 @@ static int load_elf_binary(struct linux_binprm *bprm)
10971098 /* Calculate any requested alignment. */
10981099 alignment = maximum_alignment (elf_phdata , elf_ex -> e_phnum );
10991100
1100- /*
1101- * There are effectively two types of ET_DYN
1102- * binaries: programs (i.e. PIE: ET_DYN with PT_INTERP)
1103- * and loaders (ET_DYN without PT_INTERP, since they
1104- * _are_ the ELF interpreter). The loaders must
1105- * be loaded away from programs since the program
1106- * may otherwise collide with the loader (especially
1107- * for ET_EXEC which does not have a randomized
1108- * position). For example to handle invocations of
1101+ /**
1102+ * DOC: PIE handling
1103+ *
1104+ * There are effectively two types of ET_DYN ELF
1105+ * binaries: programs (i.e. PIE: ET_DYN with
1106+ * PT_INTERP) and loaders (i.e. static PIE: ET_DYN
1107+ * without PT_INTERP, usually the ELF interpreter
1108+ * itself). Loaders must be loaded away from programs
1109+ * since the program may otherwise collide with the
1110+ * loader (especially for ET_EXEC which does not have
1111+ * a randomized position).
1112+ *
1113+ * For example, to handle invocations of
11091114 * "./ld.so someprog" to test out a new version of
11101115 * the loader, the subsequent program that the
11111116 * loader loads must avoid the loader itself, so
@@ -1118,6 +1123,9 @@ static int load_elf_binary(struct linux_binprm *bprm)
11181123 * ELF_ET_DYN_BASE and loaders are loaded into the
11191124 * independently randomized mmap region (0 load_bias
11201125 * without MAP_FIXED nor MAP_FIXED_NOREPLACE).
1126+ *
1127+ * See below for "brk" handling details, which is
1128+ * also affected by program vs loader and ASLR.
11211129 */
11221130 if (interpreter ) {
11231131 /* On ET_DYN with PT_INTERP, we do the ASLR. */
@@ -1234,8 +1242,6 @@ static int load_elf_binary(struct linux_binprm *bprm)
12341242 start_data += load_bias ;
12351243 end_data += load_bias ;
12361244
1237- current -> mm -> start_brk = current -> mm -> brk = ELF_PAGEALIGN (elf_brk );
1238-
12391245 if (interpreter ) {
12401246 elf_entry = load_elf_interp (interp_elf_ex ,
12411247 interpreter ,
@@ -1291,27 +1297,44 @@ static int load_elf_binary(struct linux_binprm *bprm)
12911297 mm -> end_data = end_data ;
12921298 mm -> start_stack = bprm -> p ;
12931299
1294- if ((current -> flags & PF_RANDOMIZE ) && (snapshot_randomize_va_space > 1 )) {
1300+ /**
1301+ * DOC: "brk" handling
1302+ *
1303+ * For architectures with ELF randomization, when executing a
1304+ * loader directly (i.e. static PIE: ET_DYN without PT_INTERP),
1305+ * move the brk area out of the mmap region and into the unused
1306+ * ELF_ET_DYN_BASE region. Since "brk" grows up it may collide
1307+ * early with the stack growing down or other regions being put
1308+ * into the mmap region by the kernel (e.g. vdso).
1309+ *
1310+ * In the CONFIG_COMPAT_BRK case, though, everything is turned
1311+ * off because we're not allowed to move the brk at all.
1312+ */
1313+ if (!IS_ENABLED (CONFIG_COMPAT_BRK ) &&
1314+ IS_ENABLED (CONFIG_ARCH_HAS_ELF_RANDOMIZE ) &&
1315+ elf_ex -> e_type == ET_DYN && !interpreter ) {
1316+ elf_brk = ELF_ET_DYN_BASE ;
1317+ /* This counts as moving the brk, so let brk(2) know. */
1318+ brk_moved = true;
1319+ }
1320+ mm -> start_brk = mm -> brk = ELF_PAGEALIGN (elf_brk );
1321+
1322+ if ((current -> flags & PF_RANDOMIZE ) && snapshot_randomize_va_space > 1 ) {
12951323 /*
1296- * For architectures with ELF randomization, when executing
1297- * a loader directly (i.e. no interpreter listed in ELF
1298- * headers), move the brk area out of the mmap region
1299- * (since it grows up, and may collide early with the stack
1300- * growing down), and into the unused ELF_ET_DYN_BASE region.
1324+ * If we didn't move the brk to ELF_ET_DYN_BASE (above),
1325+ * leave a gap between .bss and brk.
13011326 */
1302- if (IS_ENABLED (CONFIG_ARCH_HAS_ELF_RANDOMIZE ) &&
1303- elf_ex -> e_type == ET_DYN && !interpreter ) {
1304- mm -> brk = mm -> start_brk = ELF_ET_DYN_BASE ;
1305- } else {
1306- /* Otherwise leave a gap between .bss and brk. */
1327+ if (!brk_moved )
13071328 mm -> brk = mm -> start_brk = mm -> brk + PAGE_SIZE ;
1308- }
13091329
13101330 mm -> brk = mm -> start_brk = arch_randomize_brk (mm );
1331+ brk_moved = true;
1332+ }
1333+
13111334#ifdef compat_brk_randomized
1335+ if (brk_moved )
13121336 current -> brk_randomized = 1 ;
13131337#endif
1314- }
13151338
13161339 if (current -> personality & MMAP_PAGE_ZERO ) {
13171340 /* Why this, you ask??? Well SVr4 maps page 0 as read-only,
0 commit comments