mirror of
https://github.com/torvalds/linux.git
synced 2026-05-25 15:41:52 +02:00
execve fix for v6.15-rc7
- binfmt_elf: Move brk for static PIE even if ASLR disabled -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQRSPkdeREjth1dHnSE2KwveOeQkuwUCaCS8WQAKCRA2KwveOeQk u2XQAQDmhWxSh1m16/N3Utlph0h1+YpzJaJltYmrb4IV7w/WKgD/W7o1359gzhw4 VfDc6nEbjpf678pAUc+seLnX82OYwwI= =da0V -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
1a80a098c6
|
|
@ -830,6 +830,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
|
|||
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;
|
||||
|
|
@ -1097,15 +1098,19 @@ static int load_elf_binary(struct linux_binprm *bprm)
|
|||
/* 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
|
||||
|
|
@ -1118,6 +1123,9 @@ static int load_elf_binary(struct linux_binprm *bprm)
|
|||
* 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. */
|
||||
|
|
@ -1234,8 +1242,6 @@ static int load_elf_binary(struct linux_binprm *bprm)
|
|||
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,
|
||||
|
|
@ -1291,27 +1297,44 @@ static int load_elf_binary(struct linux_binprm *bprm)
|
|||
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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user