From: Adhemerval Zanella Date: Mon, 6 Jul 2026 19:56:12 +0000 (-0300) Subject: elf: Bound the tunable cache string table against the mapping size X-Git-Tag: glibc-2.44~46 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3d3cd10c4ec8bf5fb48faaad8c0acea3da225a35;p=thirdparty%2Fglibc.git elf: Bound the tunable cache string table against the mapping size _dl_load_cache_tunables bounds each entry's string offsets against [s_start, start + cache_new->len_strings], but len_strings is an unvalidated 32-bit field from ld.so.cache and s_start/s_end were int. A corrupt cache with an oversized len_strings could make s_end exceed the mapping (or overflow), letting an offset point outside the mmap; the following strcmp/__strdup would then read unmapped memory. Compute the offsets as size_t and clamp s_end to cachesize, matching how the regular library lookup bounds string offsets against the mapping size. Checked on x86_64-linux-gnu and i686-linux-gnu. Reviewed-by: DJ Delorie --- diff --git a/elf/dl-cache.c b/elf/dl-cache.c index d05afe2700..5d8d3cae90 100644 --- a/elf/dl-cache.c +++ b/elf/dl-cache.c @@ -17,6 +17,7 @@ . */ #include +#include #include #include #include @@ -649,9 +650,16 @@ _dl_load_cache_tunables (const char **data) != (void *) & tec[count]) return NULL; - /* Validate each entry. */ - int s_start = (const char *) (&cache_new->libs[cache_new->nlibs]) - *data; - int s_end = s_start + cache_new->len_strings; + /* Validate each entry. The string table lies between the file entries + and the end of the mapping; clamp its end to CACHESIZE so that a bogus + len_strings cannot make an offset point outside the mapped file. */ + size_t s_start = (const char *) (&cache_new->libs[cache_new->nlibs]) - *data; + size_t s_end; + if (s_start >= cachesize + || INT_ADD_WRAPV (s_start, cache_new->len_strings, &s_end)) + return NULL; + if (s_end > cachesize) + s_end = cachesize; for (i = 0; i < count; i ++) { if (thc->tunables[i].name_offset < s_start