diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index e3969223c170..b889c4a14866 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -84,8 +84,6 @@ #define ELF_NOTE_ROUNDSIZE 4 #define OLD_EI_BRAND 8 -#define ELF_OFFPAGE_PHNUM 128 - /* * ELF_ABI_NAME is a string name of the ELF ABI. ELF_ABI_ID is used * to build variable names. @@ -229,6 +227,11 @@ SYSCTL_BOOL(ELF_NODE_OID, OID_AUTO, allow_wx, CTLFLAG_RWTUN, &__elfN(allow_wx), 0, "Allow pages to be mapped simultaneously writable and executable"); +static u_int __elfN(phnums) = 128; +SYSCTL_UINT(ELF_NODE_OID, OID_AUTO, phnums, + CTLFLAG_RWTUN, &__elfN(phnums), 0, + "Max number of program headers to accept"); + static const Elf_Brandinfo *elf_brand_list[MAX_BRANDS]; #define aligned(a, t) (rounddown2((u_long)(a), sizeof(t)) == (u_long)(a)) @@ -855,17 +858,14 @@ __elfN(load_file)(struct thread *td, const char *file, u_long *addr, goto fail; } - if (!aligned(imgp->image_header + hdr->e_phoff, Elf_Addr)) { + if (!aligned(imgp->image_header + hdr->e_phoff, Elf_Addr) || + hdr->e_phnum > __elfN(phnums)) { error = ENOEXEC; goto fail; } if (__elfN(phdr_in_zero_page)(hdr)) { phdr = (const Elf_Phdr *)(imgp->image_header + hdr->e_phoff); } else { - if (hdr->e_phnum > ELF_OFFPAGE_PHNUM) { - error = ENOEXEC; - goto fail; - } VOP_UNLOCK(imgp->vp); phdr = m_phdrs = malloc(hdr->e_phnum * sizeof(Elf_Phdr), M_TEMP, M_WAITOK | M_ZERO); @@ -1165,11 +1165,13 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) uprintf("PHDRS wrap\n"); return (ENOEXEC); } + if (hdr->e_phnum > __elfN(phnums)) { + uprintf("Too many program headers (%u, %u max)\n", + hdr->e_phnum, __elfN(phnums)); + return (ENOEXEC); + } if (__elfN(phdr_in_zero_page)(hdr)) { phdr = (const Elf_Phdr *)(imgp->image_header + hdr->e_phoff); - } else if (hdr->e_phnum > ELF_OFFPAGE_PHNUM) { - uprintf("Too many program headers\n"); - return (ENOEXEC); } else { VOP_UNLOCK(imgp->vp); phdr = m_phdrs = malloc(hdr->e_phnum * sizeof(Elf_Phdr),