[PATCH 1/8] elf: Bound the tunable cache string table against the mapping size
Adhemerval Zanella
adhemerval.zanella@linaro.org
Mon Jul 6 21:14:37 GMT 2026
_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.
---
elf/dl-cache.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/elf/dl-cache.c b/elf/dl-cache.c
index d05afe27004..5d8d3cae908 100644
--- a/elf/dl-cache.c
+++ b/elf/dl-cache.c
@@ -17,6 +17,7 @@
<https://www.gnu.org/licenses/>. */
#include <assert.h>
+#include <intprops.h>
#include <unistd.h>
#include <ldsodefs.h>
#include <sys/mman.h>
@@ -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
--
2.43.0
More information about the Libc-alpha
mailing list