Skip to content

Commit 1a80a09

Browse files
committed
Merge tag 'execve-v6.15-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux
Pull execve fix from Kees Cook: "This fixes a corner case for ASLR-disabled static-PIE brk collision with vdso allocations: - binfmt_elf: Move brk for static PIE even if ASLR disabled" * tag 'execve-v6.15-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux: binfmt_elf: Move brk for static PIE even if ASLR disabled
2 parents 00f281f + 11854fe commit 1a80a09

File tree

1 file changed

+47
-24
lines changed

1 file changed

+47
-24
lines changed

fs/binfmt_elf.c

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)