From nobody Thu Jun 4 00:36:19 2026 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4gW5GW4yzlz6h5tM for ; Thu, 04 Jun 2026 00:36:19 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R13" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4gW5GW43FTz3pty for ; Thu, 04 Jun 2026 00:36:19 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1780533379; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=FDmpKF+U21M5+WRc+klBpG6n3fnwMVx1D+8/+iK7cao=; b=fxYR6y8aScAzlPzm57SU33IevP2xlSe4G5tmMdraRE4Uvne02go0kfQEi2IOn/R7ZWJKrt Rvimp1kZeNelZFPkOlbN7R7kr5i/Hj4Zxuy+AW5OE1e+4oYhXaLfSnKeNUqwnpWwptB5x8 EAHuoOoJRhPmmXcq7hL+qAZ7JH2UuHGG0drvn9YHcfVGCfiVC/71G/rxqlM3QRmzsSL9Un MxIfBguP+VW5b7rrgIulDVrrFej1TWKWHJ7ziMd7QG9g/uFC2wujkxcm8XDLXcf3Hx1rQl vx+XORwK7/YgPDSRrIbbxkGviPoYSn4yzHtgE5XPHIcMoMvSZOgMpfT/Zf0KmA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1780533379; a=rsa-sha256; cv=none; b=rbuWfWvlNB/40N7O+nreIahFD/CGt2HBwuc02jQ0D63UJbvmStkOHMYLlfHd+u4S6wkgXC 7MP1pgpzQZY3VhEc4Q/MkNb8UG3LVHQGBYJP+Yl6oMCM7KWAsJEMrrPCM2sTZ6hxmIqPez vVyI0FTIbuF4pJEhckt9atxPyAr7D1nU/t4I3PzWU4XGjfHaedSel126Qm+3BijQIKHSEx bNHOczoWTh0xQCCh2seXXODFGN9wuCMXfWJQyYtQT3W91Ms/RkhYH4+/lQsDc16ewQ1rD0 bXH2ZQ5xedh2L5G07f2IuRqBiOAZqu33YDf6oH2JMcOMCAERoNPvA8b9ejUbAw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1780533379; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=FDmpKF+U21M5+WRc+klBpG6n3fnwMVx1D+8/+iK7cao=; b=qV1TVml2Yby3RhS4zL0P2/VLPoCWJEzCNYutFdTxpHkZvUOCVpv6lpdlZ1j3e3el3mLRh/ qGicTnq461y7RjbNDE04nz6cZW6AYBKcou8tsBwRaBSzjloWUk6CicDoYiW08Utrol8FBp CCsEKui6ecvNSFaSkjy0eqvX2xxtI9bJLaklpGDOcSdxFipB8DzPIx22sGF4I9Mm4FBsnl o0scRRGY6k3vdKSgh4S0jRxunghn158msOgFi97gyc0SRjM/waXQdRXbfWAxm/dtRl7hP5 xVDTHtcDy2MgVCK3d9+3kskntH363HdhH1OpFTQJVZEZsoVm9/1n61l+CAjoGA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gW5GW3SLlzbj7 for ; Thu, 04 Jun 2026 00:36:19 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 206c3 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Thu, 04 Jun 2026 00:36:19 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Konstantin Belousov Subject: git: 2fa4a6b79f7b - stable/15 - imgact_elf: read program headers if not contained in the first page List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kib X-Git-Repository: src X-Git-Refname: refs/heads/stable/15 X-Git-Reftype: branch X-Git-Commit: 2fa4a6b79f7b00caa206d1bd52cb0253988f2f6a Auto-Submitted: auto-generated Date: Thu, 04 Jun 2026 00:36:19 +0000 Message-Id: <6a20c883.206c3.3b973587@gitrepo.freebsd.org> The branch stable/15 has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=2fa4a6b79f7b00caa206d1bd52cb0253988f2f6a commit 2fa4a6b79f7b00caa206d1bd52cb0253988f2f6a Author: Konstantin Belousov AuthorDate: 2026-05-28 09:06:33 +0000 Commit: Konstantin Belousov CommitDate: 2026-06-04 00:34:42 +0000 imgact_elf: read program headers if not contained in the first page PR: 295629 (cherry picked from commit 804daf166406a1b0e22f93b9417b90ed7d3aa1ae) --- sys/kern/imgact_elf.c | 91 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 62 insertions(+), 29 deletions(-) diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index 21db327d27f4..9b5215d9217a 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -84,6 +84,8 @@ #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. @@ -93,7 +95,7 @@ static int __elfN(check_header)(const Elf_Ehdr *hdr); static const Elf_Brandinfo *__elfN(get_brandinfo)(struct image_params *imgp, - const char *interp, int32_t *osrel, uint32_t *fctl0); + const Elf_Phdr *phdr, const char *interp, int32_t *osrel, uint32_t *fctl0); static int __elfN(load_file)(struct thread *td, const char *file, u_long *addr, u_long *entry); static int __elfN(load_section)(const struct image_params *imgp, @@ -103,7 +105,7 @@ static int __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp); static bool __elfN(freebsd_trans_osrel)(const Elf_Note *note, int32_t *osrel); static bool kfreebsd_trans_osrel(const Elf_Note *note, int32_t *osrel); -static bool __elfN(check_note)(struct image_params *imgp, +static bool __elfN(check_note)(struct image_params *imgp, const Elf_Phdr *phdr, const Elf_Brandnote *checknote, int32_t *osrel, bool *has_fctl0, uint32_t *fctl0); static vm_prot_t __elfN(trans_prot)(Elf_Word); @@ -339,8 +341,8 @@ __elfN(brand_inuse)(const Elf_Brandinfo *entry) } static const Elf_Brandinfo * -__elfN(get_brandinfo)(struct image_params *imgp, const char *interp, - int32_t *osrel, uint32_t *fctl0) +__elfN(get_brandinfo)(struct image_params *imgp, const Elf_Phdr *phdr, + const char *interp, int32_t *osrel, uint32_t *fctl0) { const Elf_Ehdr *hdr = (const Elf_Ehdr *)imgp->image_header; const Elf_Brandinfo *bi, *bi_m; @@ -369,8 +371,8 @@ __elfN(get_brandinfo)(struct image_params *imgp, const char *interp, has_fctl0 = false; *fctl0 = 0; *osrel = 0; - ret = __elfN(check_note)(imgp, bi->brand_note, osrel, - &has_fctl0, fctl0); + ret = __elfN(check_note)(imgp, phdr, bi->brand_note, + osrel, &has_fctl0, fctl0); /* Give brand a chance to veto check_note's guess */ if (ret && bi->header_supported) { ret = bi->header_supported(imgp, osrel, @@ -787,12 +789,13 @@ __elfN(load_file)(struct thread *td, const char *file, u_long *addr, struct nameidata nd; struct vattr attr; struct image_params image_params; - } *tempdata; + } *tempdata = NULL; const Elf_Ehdr *hdr = NULL; const Elf_Phdr *phdr = NULL; struct nameidata *nd; struct vattr *attr; struct image_params *imgp; + void *m_phdrs = NULL; u_long rbase; u_long base_addr = 0; int error; @@ -852,16 +855,27 @@ __elfN(load_file)(struct thread *td, const char *file, u_long *addr, goto fail; } - /* Only support headers that fit within first page for now */ - if (!__elfN(phdr_in_zero_page)(hdr)) { + if (!aligned(imgp->image_header + hdr->e_phoff, Elf_Addr)) { error = ENOEXEC; goto fail; } - - phdr = (const Elf_Phdr *)(imgp->image_header + hdr->e_phoff); - if (!aligned(phdr, Elf_Addr)) { - 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); + vn_lock(imgp->vp, LK_SHARED | LK_RETRY); + error = vn_rdwr(UIO_READ, imgp->vp, m_phdrs, + hdr->e_phnum * sizeof(Elf_Phdr), hdr->e_phoff, + UIO_SYSSPACE, IO_NODELOCKED, imgp->td->td_ucred, + NOCRED, NULL, imgp->td); + if (error != 0) + goto fail; } error = __elfN(load_sections)(imgp, hdr, phdr, rbase, &base_addr); @@ -883,6 +897,7 @@ fail: VOP_UNSET_TEXT_CHECKED(nd->ni_vp); vput(nd->ni_vp); } + free(m_phdrs, M_TEMP); free(tempdata, M_TEMP); return (error); @@ -1108,6 +1123,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) char *interp; const Elf_Brandinfo *brand_info; struct sysentvec *sv; + void *m_phdrs; u_long addr, baddr, entry, proghdr; u_long maxalign, maxsalign, mapsz, maxv, maxv1, anon_loc; uint32_t fctl0; @@ -1132,16 +1148,6 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) * detected an ELF file. */ - if (!__elfN(phdr_in_zero_page)(hdr)) { - uprintf("Program headers not in the first page\n"); - return (ENOEXEC); - } - phdr = (const Elf_Phdr *)(imgp->image_header + hdr->e_phoff); - if (!aligned(phdr, Elf_Addr)) { - uprintf("Unaligned program headers\n"); - return (ENOEXEC); - } - n = error = 0; baddr = 0; osrel = 0; @@ -1149,6 +1155,33 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) entry = proghdr = 0; interp = NULL; free_interp = false; + m_phdrs = NULL; + + if (!aligned(imgp->image_header + hdr->e_phoff, Elf_Addr)) { + uprintf("Unaligned program headers\n"); + return (ENOEXEC); + } + if (hdr->e_phoff + hdr->e_phnum * hdr->e_phentsize < hdr->e_phoff) { + uprintf("PHDRS wrap\n"); + 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), + M_TEMP, M_WAITOK | M_ZERO); + vn_lock(imgp->vp, LK_SHARED | LK_RETRY); + error = vn_rdwr(UIO_READ, imgp->vp, m_phdrs, + hdr->e_phnum * sizeof(Elf_Phdr), hdr->e_phoff, + UIO_SYSSPACE, IO_NODELOCKED, imgp->td->td_ucred, + NOCRED, NULL, imgp->td); + if (error != 0) + goto ret; + } /* * Somewhat arbitrary, limit accepted max alignment for the @@ -1230,7 +1263,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) } } - brand_info = __elfN(get_brandinfo)(imgp, interp, &osrel, &fctl0); + brand_info = __elfN(get_brandinfo)(imgp, phdr, interp, &osrel, &fctl0); if (brand_info == NULL) { uprintf("ELF binary type \"%u\" not known.\n", hdr->e_ident[EI_OSABI]); @@ -1434,6 +1467,7 @@ ret: ASSERT_VOP_LOCKED(imgp->vp, "skipped relock"); if (free_interp) free(interp, M_TEMP); + free(m_phdrs, M_TEMP); return (error); } @@ -2914,17 +2948,16 @@ note_fctl_cb(const Elf_Note *note, void *arg0, bool *res) * as for headers. */ static bool -__elfN(check_note)(struct image_params *imgp, const Elf_Brandnote *brandnote, - int32_t *osrel, bool *has_fctl0, uint32_t *fctl0) +__elfN(check_note)(struct image_params *imgp, const Elf_Phdr *phdr, + const Elf_Brandnote *brandnote, int32_t *osrel, bool *has_fctl0, + uint32_t *fctl0) { - const Elf_Phdr *phdr; const Elf_Ehdr *hdr; struct brandnote_cb_arg b_arg; struct fctl_cb_arg f_arg; int i, j; hdr = (const Elf_Ehdr *)imgp->image_header; - phdr = (const Elf_Phdr *)(imgp->image_header + hdr->e_phoff); b_arg.brandnote = brandnote; b_arg.osrel = osrel; f_arg.has_fctl0 = has_fctl0;