From nobody Wed May 27 09:03:40 2026 X-Original-To: dev-commits-src-all@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 4gQNvd0Pfgz6fhXd for ; Wed, 27 May 2026 09:03:41 +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 4gQNvc3GDDz3X41 for ; Wed, 27 May 2026 09:03:40 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1779872620; 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=6jsE52d23GIc0wvqo3NSqLZioovNjAAFqrcGShYaEzI=; b=Yc9E+zqJGb33N3t95pdjTkM6Y84YnOg8xfIqYhB+3BhxY6xsAodBd2kNMkpL/8HHNRxTa7 6KUXH1nKhU2R3wJZQupnLo03VM9JagX2o/M74+09q1TvqfvLKQl/SdOnv7t1GIPuBkk0O7 MhRdlIKPZVGKJ/qaHjRXUWumMCnyqtap0IV5yMM+Ms02JqEOz1E5sKfRuT74yJBfZY3pYC Pr9LH0K2qr+fOv9hRnkz+ExUmUnFZtuKA3r3pc9tFFRKtoDcPFsUBfLWXgrTUAuQRI4gF7 ATU/Le9EMAKTVwnq+rlX+ub9O04XNRK/u2RWMhbrqjR5j3ibgpPiO+5SJaVgiA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1779872620; a=rsa-sha256; cv=none; b=XKc2Btu9RoomQurfmKv//pEUMsLkAM6xbV8lcmd9OFAH8wxJwW/El8NtIQkAXuOJHj4Goq wzkdYiUxG3ejb5UN+cuGOJQKhTFM9myJ3ZBgpv5RQ1NgMmrvU+b4nlFEwYqh+6RSxk30P6 CRLYjPOaGWAQh+KtsGXta4D81GIgL3z6cIhlq6kPybvYdBmvOZrbppjEhNfPYBXCMefTLF 0LH45WE79PYqbyo2ub4ciC436B55zsJiqScmtfCVX+TmGyFt4Gm5afwH/dju9ulu6mZ0fT ud1PTbHQ/DiYT4OHb/h4ihZ8U1xTHCc2BdfSmraHXkPRVIG9QSDnT9iAkVAQqA== 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=1779872620; 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=6jsE52d23GIc0wvqo3NSqLZioovNjAAFqrcGShYaEzI=; b=w4fPm4JVnjH7dWeg+174z2B88vAEKgFJup/SDrF9YUyerXQf5V4qdRfeLfQWNF+zv+tCUg TpGPj7TzWNzTijiFo2os3DzMYVO0YPc4gib2+hiHR/QZ3IQGxhO8NQkTGqWtEVYgTRgmEs ixp557wwrjxFHh3B9dXzA7UwILND9GG6zeMvFHLbtWx8hCTFfSuMtG88ty/t0eTIz+Wyxt suypjIqO6hytpN/FSzGs+/xtcla/da/zuuWUU7O7ieBQYJrMTTqmp2Z61Sdqs0ne0z2Mf2 KYquB+N0ZpzdOM3LfCoKNkEeVIg5zOeCnX3o8BJtfwYlIHrVqPKTF/8+dErjgQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gQNvc2g7KzstL for ; Wed, 27 May 2026 09:03:40 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 25dbb by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Wed, 27 May 2026 09:03:40 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Dag-Erling=?utf-8?Q? Sm=C3=B8rg?=rav Subject: git: 5999b12bf908 - stable/14 - nlist: Handle multiple symbol tables List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@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: des X-Git-Repository: src X-Git-Refname: refs/heads/stable/14 X-Git-Reftype: branch X-Git-Commit: 5999b12bf908689da72c8b0044176c66d03a723e Auto-Submitted: auto-generated Date: Wed, 27 May 2026 09:03:40 +0000 Message-Id: <6a16b36c.25dbb.76f85f56@gitrepo.freebsd.org> The branch stable/14 has been updated by des: URL: https://cgit.FreeBSD.org/src/commit/?id=5999b12bf908689da72c8b0044176c66d03a723e commit 5999b12bf908689da72c8b0044176c66d03a723e Author: Dag-Erling Smørgrav AuthorDate: 2026-05-19 06:52:53 +0000 Commit: Dag-Erling Smørgrav CommitDate: 2026-05-27 09:03:28 +0000 nlist: Handle multiple symbol tables * Instead of looking for and stopping at the first SHT_SYMTAB section, iterate over all SHT_DYNSYM and SHT_SYMTAB sections until we've either found all our symbols or run out. * Perform bounds checks on section and string table offsets and sizes before attempting to mmap() the string table. * Perform bounds checks on individual symbol table entries before attempting to access the corresponding strings. * Stop treating _Foo and Foo as the same symbol. This unbreaks OpenSSH which uses nlist(3) to verify PKCS#11 providers. PR: 295336 MFC after: 1 week Fixes: 77909f597881 ("Initial elf nlist support [...]") Fixes: 644b4646c7ac ("OpenSSH: Update to 10.1p1") Reviewed by: kib, emaste Differential Revision: https://reviews.freebsd.org/D57034 (cherry picked from commit 4617a6cb82a673b02257257c1f5f8a3c8d2bb943) nlist: Decrement nent on match PR: 295336 MFC after: 1 week Fixes: 4617a6cb82a6 ("nlist: Handle multiple symbol tables") (cherry picked from commit e9cbbf04d6fe24b3a207cf085122def72145742e) --- lib/libc/gen/nlist.3 | 8 +-- lib/libc/gen/nlist.c | 150 ++++++++++++++++++++++++++++----------------------- 2 files changed, 88 insertions(+), 70 deletions(-) diff --git a/lib/libc/gen/nlist.3 b/lib/libc/gen/nlist.3 index 6aefd95e3b51..4912180e9bcd 100644 --- a/lib/libc/gen/nlist.3 +++ b/lib/libc/gen/nlist.3 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd May 18, 2026 +.Dd May 19, 2026 .Dt NLIST 3 .Os .Sh NAME @@ -45,9 +45,11 @@ Its use is discouraged. The .Fn nlist function -retrieves name list entries from the +retrieves name list entries from .Xr elf 5 -section with type +sections with type +.Dv SHT_DYNSYM +or .Dv SHT_SYMTAB in an ELF object (for example, an executable file or shared library). The argument diff --git a/lib/libc/gen/nlist.c b/lib/libc/gen/nlist.c index 0e00d8d23f99..ad63318f7653 100644 --- a/lib/libc/gen/nlist.c +++ b/lib/libc/gen/nlist.c @@ -38,8 +38,9 @@ __SCCSID("@(#)nlist.c 8.1 (Berkeley) 6/4/93"); #include #include -#include #include +#include +#include #include #include #include @@ -87,6 +88,8 @@ __fdnlist(int fd, struct nlist *list) #define ISLAST(p) (p->n_un.n_name == 0 || p->n_un.n_name[0] == 0) +static int elf_scan_symtab(Elf_Shdr *, int, int, off_t, size_t, char *, size_t, + struct nlist *, int); static void elf_sym_to_nlist(struct nlist *, Elf_Sym *, Elf_Shdr *, int); /* @@ -123,22 +126,19 @@ int __elf_fdnlist(int fd, struct nlist *list) { struct nlist *p; - Elf_Off symoff = 0, symstroff = 0; - Elf_Size symsize = 0, symstrsize = 0; - Elf_Ssize cc, i; + Elf_Off symoff = 0, stroff = 0; + Elf_Size symsize = 0, strsize = 0; + Elf_Ssize i; int nent = -1; int errsave; - Elf_Sym sbuf[1024]; - Elf_Sym *s; Elf_Ehdr ehdr; - char *strtab = NULL; - Elf_Shdr *shdr = NULL; + Elf_Shdr *shdr; Elf_Size shdr_size; void *base; struct stat st; /* Make sure obj is OK */ - if (lseek(fd, (off_t)0, SEEK_SET) == -1 || + if (lseek(fd, 0, SEEK_SET) == -1 || _read(fd, &ehdr, sizeof(Elf_Ehdr)) != sizeof(Elf_Ehdr) || !__elf_is_okay__(&ehdr) || _fstat(fd, &st) < 0) @@ -160,39 +160,6 @@ __elf_fdnlist(int fd, struct nlist *list) return (-1); shdr = (Elf_Shdr *)base; - /* - * Find the symbol table entry and it's corresponding - * string table entry. Version 1.1 of the ABI states - * that there is only one symbol table but that this - * could change in the future. - */ - for (i = 0; i < ehdr.e_shnum; i++) { - if (shdr[i].sh_type == SHT_SYMTAB) { - symoff = shdr[i].sh_offset; - symsize = shdr[i].sh_size; - symstroff = shdr[shdr[i].sh_link].sh_offset; - symstrsize = shdr[shdr[i].sh_link].sh_size; - break; - } - } - - /* Check for files too large to mmap. */ - if (symstrsize > SIZE_T_MAX) { - errno = EFBIG; - goto done; - } - /* - * Map string table into our address space. This gives us - * an easy way to randomly access all the strings, without - * making the memory allocation permanent as with malloc/free - * (i.e., munmap will return it to the system). - */ - base = mmap(NULL, (size_t)symstrsize, PROT_READ, MAP_PRIVATE, fd, - (off_t)symstroff); - if (base == MAP_FAILED) - goto done; - strtab = (char *)base; - /* * clean out any left-over information for all valid entries. * Type and value defined to be 0 if not found; historical @@ -212,46 +179,95 @@ __elf_fdnlist(int fd, struct nlist *list) ++nent; } - /* Don't process any further if object is stripped. */ - if (symoff == 0) - goto done; - - if (lseek(fd, (off_t) symoff, SEEK_SET) == -1) { - nent = -1; - goto done; + /* + * Find the symbol table entry and it's corresponding + * string table entry. Version 1.1 of the ABI states + * that there is only one symbol table but that this + * could change in the future. + */ + for (i = 0; nent > 0 && i < ehdr.e_shnum; i++) { + if (shdr[i].sh_type != SHT_SYMTAB && + shdr[i].sh_type != SHT_DYNSYM) + continue; + symoff = shdr[i].sh_offset; + symsize = shdr[i].sh_size; + stroff = shdr[shdr[i].sh_link].sh_offset; + strsize = shdr[shdr[i].sh_link].sh_size; + + /* + * Skip this section if it or its string table is empty or + * extends beyond the end of the file, or if the string + * table is too large to map into memory. + */ + if (symoff == 0 || symsize == 0 || + symsize > SIZE_MAX - symoff || + symoff + symsize > st.st_size || + stroff == 0 || strsize == 0 || + strsize > SIZE_MAX - stroff || + stroff + strsize > st.st_size) { + errno = ENOENT; + continue; + } + + /* + * Map string table into our address space. This gives us + * an easy way to randomly access all the strings, without + * making the memory allocation permanent as with + * malloc/free (i.e., munmap will return it to the + * system). + */ + base = mmap(NULL, (size_t)strsize, PROT_READ, + MAP_PRIVATE, fd, (off_t)stroff); + if (base == MAP_FAILED) + continue; + + nent = elf_scan_symtab(shdr, ehdr.e_shnum, fd, symoff, symsize, + base, strsize, list, nent); + + errsave = errno; + munmap(base, strsize); + errno = errsave; } + errsave = errno; + munmap(shdr, shdr_size); + errno = errsave; + return (nent); +} + +static int +elf_scan_symtab(Elf_Shdr *shdr, int shnum, int fd, off_t symoff, size_t symsize, + char *strtab, size_t strsize, struct nlist *list, int nent) +{ + Elf_Sym sbuf[1024]; + Elf_Sym *s; + char *name; + struct nlist *p; + Elf_Ssize cc; + size_t slen; + if (lseek(fd, symoff, SEEK_SET) == -1) + return (-1); while (symsize > 0 && nent > 0) { cc = MIN(symsize, sizeof(sbuf)); if (_read(fd, sbuf, cc) != cc) break; symsize -= cc; for (s = sbuf; cc > 0 && nent > 0; ++s, cc -= sizeof(*s)) { - char *name; - struct nlist *p; - + if (s->st_name >= strsize) + continue; name = strtab + s->st_name; if (name[0] == '\0') continue; - for (p = list; !ISLAST(p); p++) { - if ((p->n_un.n_name[0] == '_' && - strcmp(name, p->n_un.n_name+1) == 0) - || strcmp(name, p->n_un.n_name) == 0) { - elf_sym_to_nlist(p, s, shdr, - ehdr.e_shnum); - if (--nent <= 0) - break; + slen = strnlen(name, strsize - s->st_name); + for (p = list; nent > 0 && !ISLAST(p); p++) { + if (strncmp(name, p->n_un.n_name, slen) == 0 && + p->n_un.n_name[slen] == '\0') { + elf_sym_to_nlist(p, s, shdr, shnum); + --nent; } } } } - done: - errsave = errno; - if (strtab != NULL) - munmap(strtab, symstrsize); - if (shdr != NULL) - munmap(shdr, shdr_size); - errno = errsave; return (nent); }