From b0d434efd4454d2f95928e84a560d8c1093f298f Mon Sep 17 00:00:00 2001 From: andy Date: Tue, 29 Jul 2025 01:54:33 +0000 Subject: [PATCH] backport patches from glibc upstream (cherry picked from commit 7b5ce78175c85944e9d4ca8166b0fa1b676d8567) --- ...ort-Fix-UB-on__dl_map_object_from_fd.patch | 29 ++ ...f-symbol-versions-which-hash-to-zero.patch | 302 ++++++++++++++++++ glibc.spec | 8 +- 3 files changed, 338 insertions(+), 1 deletion(-) create mode 100644 backport-Fix-UB-on__dl_map_object_from_fd.patch create mode 100644 backport-Fix-handling-of-symbol-versions-which-hash-to-zero.patch diff --git a/backport-Fix-UB-on__dl_map_object_from_fd.patch b/backport-Fix-UB-on__dl_map_object_from_fd.patch new file mode 100644 index 0000000..72f3751 --- /dev/null +++ b/backport-Fix-UB-on__dl_map_object_from_fd.patch @@ -0,0 +1,29 @@ +From e529bfe8dee4bfde3ac74927b5b7b8df65cf3bb0 Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Wed, 7 May 2025 11:17:29 -0300 +Subject: [PATCH] elf: Fix UB on _dl_map_object_from_fd + +On 32-bit architecture ubsan triggers: + +UBSAN: Undefined behaviour in dl-load.c:1345:54 pointer index expression with base 0x00612508 overflowed to 0xf7c3a508 + +Use explicit uintptr_t operation instead. +Reviewed-by: Florian Weimer +--- + elf/dl-load.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/elf/dl-load.c b/elf/dl-load.c +index bf29ec725d..6e26ef0583 100644 +@@ -1359,7 +1359,7 @@ cannot enable executable stack as shared object requires"); + + /* Adjust the address of the TLS initialization image. */ + if (l->l_tls_initimage != NULL) +- l->l_tls_initimage = (char *) l->l_tls_initimage + l->l_addr; ++ l->l_tls_initimage = (void*)((uintptr_t)l->l_tls_initimage + l->l_addr); + + /* Process program headers again after load segments are mapped in + case processing requires accessing those segments. Scan program +-- +2.43.7 + diff --git a/backport-Fix-handling-of-symbol-versions-which-hash-to-zero.patch b/backport-Fix-handling-of-symbol-versions-which-hash-to-zero.patch new file mode 100644 index 0000000..2c44e42 --- /dev/null +++ b/backport-Fix-handling-of-symbol-versions-which-hash-to-zero.patch @@ -0,0 +1,302 @@ +From 46d31980943d8be2f421c1e3276b265c7552636e Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Fri, 7 Mar 2025 17:37:50 +0100 +Subject: [PATCH] elf: Fix handling of symbol versions which hash to zero (bug + 29190) + +This was found through code inspection. No application impact is +known. + +Reviewed-by: Adhemerval Zanella +--- + elf/Makefile | 21 ++++++++++ + elf/dl-lookup.c | 22 ++++++++--- + elf/dl-version.c | 7 ++++ + elf/tst-version-hash-zero-linkmod.c | 22 +++++++++++ + elf/tst-version-hash-zero-linkmod.map | 7 ++++ + elf/tst-version-hash-zero-mod.c | 20 ++++++++++ + elf/tst-version-hash-zero-mod.map | 13 +++++++ + elf/tst-version-hash-zero-refmod.c | 23 +++++++++++ + elf/tst-version-hash-zero.c | 56 +++++++++++++++++++++++++++ + 9 files changed, 185 insertions(+), 6 deletions(-) + create mode 100644 elf/tst-version-hash-zero-linkmod.c + create mode 100644 elf/tst-version-hash-zero-linkmod.map + create mode 100644 elf/tst-version-hash-zero-mod.c + create mode 100644 elf/tst-version-hash-zero-mod.map + create mode 100644 elf/tst-version-hash-zero-refmod.c + create mode 100644 elf/tst-version-hash-zero.c + +diff --git a/elf/Makefile b/elf/Makefile +index 190c90b6..c3396728 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -472,6 +472,7 @@ tests += \ + tst-unique2 \ + tst-unwind-ctor \ + tst-unwind-main \ ++ tst-version-hash-zero \ + unload3 \ + unload4 \ + unload5 \ +@@ -941,6 +942,9 @@ modules-names += \ + tst-unique2mod1 \ + tst-unique2mod2 \ + tst-unwind-ctor-lib \ ++ tst-version-hash-zero-linkmod \ ++ tst-version-hash-zero-mod \ ++ tst-version-hash-zero-refmod \ + unload2dep \ + unload2mod \ + unload3mod1 \ +@@ -3082,3 +3086,20 @@ tst-rtld-no-malloc-audit-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so + tst-rtld-no-malloc-preload-ENV = LD_PRELOAD=$(objpfx)tst-auditmod1.so + + $(objpfx)tst-dlopen-sgid.out: $(objpfx)tst-dlopen-sgid-mod.so ++ ++$(objpfx)tst-version-hash-zero.out: \ ++ $(objpfx)tst-version-hash-zero-mod.so \ ++ $(objpfx)tst-version-hash-zero-refmod.so ++LDFLAGS-tst-version-hash-zero-mod.so = \ ++ -Wl,--version-script=tst-version-hash-zero-mod.map ++# The run-time test module tst-version-hash-zero-refmod.so is linked ++# to a stub module, tst-version-hash-zero-linkmod.so, to produce an ++# expected relocation error. ++$(objpfx)tst-version-hash-zero-refmod.so: \ ++ $(objpfx)tst-version-hash-zero-linkmod.so ++LDFLAGS-tst-version-hash-zero-linkmod.so = \ ++ -Wl,--version-script=tst-version-hash-zero-linkmod.map \ ++ -Wl,--soname=tst-version-hash-zero-mod.so ++$(objpfx)tst-version-hash-zero-refmod.so: \ ++ $(objpfx)tst-version-hash-zero-linkmod.so ++tst-version-hash-zero-refmod.so-no-z-defs = yes +diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c +index a8f48fed..437d7c23 100644 +--- a/elf/dl-lookup.c ++++ b/elf/dl-lookup.c +@@ -114,12 +114,22 @@ check_match (const char *const undef_name, + /* We can match the version information or use the + default one if it is not hidden. */ + ElfW(Half) ndx = verstab[symidx] & 0x7fff; +- if ((map->l_versions[ndx].hash != version->hash +- || strcmp (map->l_versions[ndx].name, version->name)) +- && (version->hidden || map->l_versions[ndx].hash +- || (verstab[symidx] & 0x8000))) +- /* It's not the version we want. */ +- return NULL; ++ if (map->l_versions[ndx].hash == version->hash ++ && strcmp (map->l_versions[ndx].name, version->name) == 0) ++ /* This is an exact version match. Return the symbol below. */ ++ ; ++ else ++ { ++ if (!version->hidden ++ && map->l_versions[ndx].name[0] == '\0' ++ && (verstab[symidx] & 0x8000) == 0 ++ && (*num_versions)++ == 0) ++ /* This is the global default version. Store it as a ++ fallback match. */ ++ *versioned_sym = sym; ++ ++ return NULL; ++ } + } + } + else +diff --git a/elf/dl-version.c b/elf/dl-version.c +index 5b8693de..3beff739 100644 +--- a/elf/dl-version.c ++++ b/elf/dl-version.c +@@ -357,6 +357,13 @@ _dl_check_map_versions (struct link_map *map, int verbose, int trace_mode) + ent = (ElfW(Verdef) *) ((char *) ent + ent->vd_next); + } + } ++ ++ /* The empty string has ELF hash zero. This avoids a NULL check ++ before the version string comparison in check_match in ++ dl-lookup.c. */ ++ for (unsigned int i = 0; i < map->l_nversions; ++i) ++ if (map->l_versions[i].name == NULL) ++ map->l_versions[i].name = ""; + } + + /* When there is a DT_VERNEED entry with libc.so on DT_NEEDED, issue +diff --git a/elf/tst-version-hash-zero-linkmod.c b/elf/tst-version-hash-zero-linkmod.c +new file mode 100644 +index 0000000000..15e2506d01 +--- /dev/null ++++ b/elf/tst-version-hash-zero-linkmod.c +@@ -0,0 +1,22 @@ ++/* Stub module for linking tst-version-hash-zero-refmod.so. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public License as ++ published by the Free Software Foundation; either version 2.1 of the ++ License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; see the file COPYING.LIB. If ++ not, see . */ ++ ++/* The version script assigns a different symbol version for the stub ++ module. Loading the module with the incorrect version is expected ++ to fail. */ ++#include "tst-version-hash-zero-mod.c" +diff --git a/elf/tst-version-hash-zero-linkmod.map b/elf/tst-version-hash-zero-linkmod.map +new file mode 100644 +index 0000000000..2dba7c22d7 +--- /dev/null ++++ b/elf/tst-version-hash-zero-linkmod.map +@@ -0,0 +1,7 @@ ++Base { ++ local: *; ++}; ++ ++OTHER_VERSION { ++ global: global_variable; ++} Base; +diff --git a/elf/tst-version-hash-zero-mod.c b/elf/tst-version-hash-zero-mod.c +new file mode 100644 +index 0000000000..ac6b0dc4a5 +--- /dev/null ++++ b/elf/tst-version-hash-zero-mod.c +@@ -0,0 +1,20 @@ ++/* Test module with a zero version symbol hash. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public License as ++ published by the Free Software Foundation; either version 2.1 of the ++ License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; see the file COPYING.LIB. If ++ not, see . */ ++ ++/* The symbol version is assigned by version script. */ ++int global_variable; +diff --git a/elf/tst-version-hash-zero-mod.map b/elf/tst-version-hash-zero-mod.map +new file mode 100644 +index 0000000000..41eaff7914 +--- /dev/null ++++ b/elf/tst-version-hash-zero-mod.map +@@ -0,0 +1,13 @@ ++Base { ++ local: *; ++}; ++ ++/* Define the version so that tst-version-hash-zero-refmod.so passes ++ the initial symbol version check. */ ++OTHER_VERSION { ++} Base; ++ ++/* This version string hashes to zero. */ ++PPPPPPPPPPPP { ++ global: global_variable; ++} Base; +diff --git a/elf/tst-version-hash-zero-refmod.c b/elf/tst-version-hash-zero-refmod.c +new file mode 100644 +index 0000000000..cd8b3dcef5 +--- /dev/null ++++ b/elf/tst-version-hash-zero-refmod.c +@@ -0,0 +1,23 @@ ++/* Test module that triggers a relocation failure in tst-version-hash-zero. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public License as ++ published by the Free Software Foundation; either version 2.1 of the ++ License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; see the file COPYING.LIB. If ++ not, see . */ ++ ++/* This is bound to global_variable@@OTHER_VERSION via ++ tst-version-hash-zero-linkmod.so, but at run time, only ++ global_variable@PPPPPPPPPPPP exists. */ ++extern int global_variable; ++int *pointer_variable = &global_variable; +diff --git a/elf/tst-version-hash-zero.c b/elf/tst-version-hash-zero.c +new file mode 100644 +index 0000000000..66a0db4f51 +--- /dev/null ++++ b/elf/tst-version-hash-zero.c +@@ -0,0 +1,56 @@ ++/* Symbols with version hash zero should not match any version (bug 29190). ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public License as ++ published by the Free Software Foundation; either version 2.1 of the ++ License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; see the file COPYING.LIB. If ++ not, see . */ ++ ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ void *handle = xdlopen ("tst-version-hash-zero-mod.so", RTLD_NOW); ++ ++ /* This used to crash because some struct r_found_version entries ++ with hash zero did not have valid version strings. */ ++ TEST_VERIFY (xdlvsym (handle, "global_variable", "PPPPPPPPPPPP") != NULL); ++ ++ /* Consistency check. */ ++ TEST_VERIFY (xdlsym (handle, "global_variable") ++ == xdlvsym (handle, "global_variable", "PPPPPPPPPPPP")); ++ ++ /* This symbol version is supposed to be missing. */ ++ TEST_VERIFY (dlvsym (handle, "global_variable", "OTHER_VERSION") == NULL); ++ ++ /* tst-version-hash-zero-refmod.so references ++ global_variable@@OTHER_VERSION and is expected to fail to load. ++ dlvsym sets the hidden flag during lookup. Relocation does not, ++ so this exercises a different failure case. */ ++ TEST_VERIFY_EXIT (dlopen ("tst-version-hash-zero-refmod.so", RTLD_NOW) ++ == NULL); ++ const char *message = dlerror (); ++ if (strstr (message, ++ ": undefined symbol: global_variable, version OTHER_VERSION") ++ == NULL) ++ FAIL_EXIT1 ("unexpected dlopen failure: %s", message); ++ ++ xdlclose (handle); ++ return 0; ++} ++ ++#include +-- +2.43.7 + diff --git a/glibc.spec b/glibc.spec index 611d132..280a98b 100644 --- a/glibc.spec +++ b/glibc.spec @@ -67,7 +67,7 @@ ############################################################################## Name: glibc Version: 2.38 -Release: 63 +Release: 64 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -352,6 +352,8 @@ Patch9036: fix-CVE-2019-1010023.patch Patch9037: Using-__memcpy_generic-when-kunpeng920-with-tsv120-m.patch Patch9038: Using-__memmove_generic-when-kunpeng920-with-tsv120-m.patch Patch9039: revert-aarch64-Use-memcpy_simd-as-the-default-memcpy.patch +Patch9040: backport-Fix-UB-on__dl_map_object_from_fd.patch +Patch9041: backport-Fix-handling-of-symbol-versions-which-hash-to-zero.patch Provides: ldconfig rtld(GNU_HASH) bundled(gnulib) @@ -1532,6 +1534,10 @@ fi %endif %changelog +* Tue Jul 29 2025 andy - 2.38-64 +- elf: Fix UB on _dl_map_object_from_fd +- elf: Fix handling of symbol versions which hash to zero + * Mon Jul 14 2025 Qingqing Li - 2.38-63 - malloc: cleanup casts in tst-calloc - malloc: obscure calloc use in tst-calloc -- Gitee