From nobody Tue May 19 06:53:38 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 4gKQPH0nN8z6dh44 for ; Tue, 19 May 2026 06:53:39 +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 4gKQPG6Bgrz3hjg for ; Tue, 19 May 2026 06:53:38 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1779173618; 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=jRZUHDuc67NJatJ5cRfxKFEuoDKMw1IFQiAbjodvA10=; b=IUjT3tPchhKn73RPdMCKItXu8e6WLairoXNCVrtTez96nC9YpGFtKBOoYx1DOCizkOZb5O BGmHWoRtWoZRzHqgTVPHmzWRW6e58e1pIpgvADRO5vpQYyCQ/UvP62J2mamuQrunJceubm wBr+r8cec3EZg4cECUs/XrCjlUpjy/yOHZUPyZ4CO6BvVOhyz7yMAWU52ZSyf/QyLoNAYe 0xP02H7Ejzq8JzronZ03fp0bJhhM9dWoyjzfsNenddg0yWKr8g33kOuO8tPVlJEzckY12q AEaVVr019Yjzn9GepauDcqEzsVdML8RdHffkjyl4CGV2obz7sXE7loFAM6MV1A== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1779173618; a=rsa-sha256; cv=none; b=eBe0Ew8dnroP1qO3faMtZhp0NedAs59uBltRtPdkdyfs54lxqwHJG+iXz3DWSbKmqabbhK lL8/E5zp962RS5J8MGjGagjwes2kFHjdEatr9U0gh5FHDoTSpbFZiony307HnFIf91kTgq 8VFpAu1B9tVzUXkmWoG4QBgNTXkgOWKp0fs/wIQmGVRgbXbMv2che0aYg9Tl0mQS3J9+LQ kymvJAvamV4CJDafQ/EyEGEZ0YtP9YeC9NOWkfUQlTT6gZTEZeJRkSQi+VNB7iTYITcRR1 v4UO5wPq2WLuCAlHMhF/MfGXfI8boM25YqibKQrc1xlysUEDW5z+2tK2xbBNTQ== 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=1779173618; 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=jRZUHDuc67NJatJ5cRfxKFEuoDKMw1IFQiAbjodvA10=; b=N8uz15pypKOzGe+7yXTwh1xysRuwsCiGRlVMknWSfh9iIq3tu04UZCPXhWFDRQP8Kps5Us mFnZ/4sPhP/KOMGOMze3w44lpvMb9MCFnLsG7y337zesCn4uIJEhLuFEbm4sclJEjO20eU MRtJMt0klCmgzO0hwf4APc4MGGBOx0/wka0kb3byqo1ZhXuJeoLY3a+z5rAUQe20PP80NY N6YrHp/pwT9/+ZAiUHQjol2uECnlCu0rH0n3OrKGP/t9llOu6RF+fFYMdCqvtaljPh+StK T/qKHSSQQOZUbcF7W5ZBaOMC3uPnQTD8LETDoh8DKlwNZZhEo1W5iDW1KEtDXQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gKQPG5ggkz14C8 for ; Tue, 19 May 2026 06:53:38 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 23d77 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Tue, 19 May 2026 06:53:38 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Dag-Erling=?utf-8?Q? Sm=C3=B8rg?=rav Subject: git: 4617a6cb82a6 - main - 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/main X-Git-Reftype: branch X-Git-Commit: 4617a6cb82a673b02257257c1f5f8a3c8d2bb943 Auto-Submitted: auto-generated Date: Tue, 19 May 2026 06:53:38 +0000 Message-Id: <6a0c08f2.23d77.5dd90a92@gitrepo.freebsd.org> The branch main has been updated by des: URL: https://cgit.FreeBSD.org/src/commit/?id=4617a6cb82a673b02257257c1f5f8a3c8d2bb943 commit 4617a6cb82a673b02257257c1f5f8a3c8d2bb943 Author: Dag-Erling Smørgrav AuthorDate: 2026-05-19 06:52:53 +0000 Commit: Dag-Erling Smørgrav CommitDate: 2026-05-19 06:53:35 +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 --- lib/libc/gen/nlist.3 | 8 +-- lib/libc/gen/nlist.c | 150 ++++++++++++++++++++++++++++----------------------- 2 files changed, 87 insertions(+), 71 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 ebf4ae92641a..06034dc8ee1a 100644 --- a/lib/libc/gen/nlist.c +++ b/lib/libc/gen/nlist.c @@ -36,8 +36,9 @@ #include #include -#include #include +#include +#include #include #include #include @@ -85,6 +86,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); /* @@ -121,22 +124,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) @@ -158,39 +158,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 @@ -210,46 +177,93 @@ __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); } } } - done: - errsave = errno; - if (strtab != NULL) - munmap(strtab, symstrsize); - if (shdr != NULL) - munmap(shdr, shdr_size); - errno = errsave; return (nent); }