Date: Thu, 27 Apr 2023 18:20:12 GMT From: Ed Maste <emaste@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Subject: git: 9e4ae81971f7 - stable/13 - link_elf: fix SysV hash function overflow Message-ID: <202304271820.33RIKCqv069930@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by emaste: URL: https://cgit.FreeBSD.org/src/commit/?id=9e4ae81971f7b85982c73c1b29424149b56f38dd commit 9e4ae81971f7b85982c73c1b29424149b56f38dd Author: Ed Maste <emaste@FreeBSD.org> AuthorDate: 2023-04-12 14:04:27 +0000 Commit: Ed Maste <emaste@FreeBSD.org> CommitDate: 2023-04-27 17:05:28 +0000 link_elf: fix SysV hash function overflow Quoting from https://maskray.me/blog/2023-04-12-elf-hash-function: The System V Application Binary Interface (generic ABI) specifies the ELF object file format. When producing an output executable or shared object needing a dynamic symbol table (.dynsym), a linker generates a .hash section with type SHT_HASH to hold a symbol hash table. A DT_HASH tag is produced to hold the address of .hash. The function is supposed to return a value no larger than 0x0fffffff. Unfortunately, there is a bug. When unsigned long consists of more than 32 bits, the return value may be larger than UINT32_MAX. For instance, elf_hash((const unsigned char *)"\xff\x0f\x0f\x0f\x0f\x0f\x12") returns 0x100000002, which is clearly unintended, as the function should behave the same way regardless of whether long represents a 32-bit integer or a 64-bit integer. Reviewed by: kib, Fangrui Song Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D39517 (cherry picked from commit 2ef2c26f3f132af33f6f12cd7b27d4dbbd7fa435) --- sys/kern/link_elf.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c index 245c8697cf79..3c06c8c79108 100644 --- a/sys/kern/link_elf.c +++ b/sys/kern/link_elf.c @@ -1481,23 +1481,20 @@ relocate_file(elf_file_t ef) } /* - * Hash function for symbol table lookup. Don't even think about changing - * this. It is specified by the System V ABI. + * SysV hash function for symbol table lookup. It is specified by the + * System V ABI. */ -static unsigned long +static Elf32_Word elf_hash(const char *name) { - const unsigned char *p = (const unsigned char *) name; - unsigned long h = 0; - unsigned long g; + const unsigned char *p = (const unsigned char *)name; + Elf32_Word h = 0; while (*p != '\0') { h = (h << 4) + *p++; - if ((g = h & 0xf0000000) != 0) - h ^= g >> 24; - h &= ~g; + h ^= (h >> 24) & 0xf0; } - return (h); + return (h & 0x0fffffff); } static int @@ -1508,7 +1505,7 @@ link_elf_lookup_symbol1(linker_file_t lf, const char *name, c_linker_sym_t *sym, unsigned long symnum; const Elf_Sym* symp; const char *strp; - unsigned long hash; + Elf32_Word hash; /* If we don't have a hash, bail. */ if (ef->buckets == NULL || ef->nbuckets == 0) {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202304271820.33RIKCqv069930>