From 0549d1c346d2b973471dae5290fc0aa753d9386d Mon Sep 17 00:00:00 2001 From: Prabhakar Pujeri Date: Wed, 19 Aug 2026 10:09:05 +0530 Subject: [PATCH 1/3] fix(dracut-install): validate ELF section-table bounds The PARSE_ELF_START macro checked only that e_shoff and e_shstrndx are individually < src_len, then indexed shdr[e_shstrndx].sh_offset into the mmap'ed file. Two classes of OOB reads remain on truncated or malformed ELFs: 1. The section header table extent is not validated: e_shnum section headers starting at shoff can extend past the end of the file, so iterating them reads past the map. 2. The section header string table (shstrtab) content extent isn't validated: sh_offset/sh_size come from the file, and the strcmp(&shstrtab[shdr[i].sh_name], ...) reads at attacker-controlled offsets, potentially past the mapping. Add the missing bounds checks: - PARSE_ELF_START now verifies the whole section table fits in the mapped file, then treats it as untrusted: a helper reads the shstrtab section's offset and size, validates both against src_len, and the section-name lookup checks the name offset and NUL termination inside the table before any strcmp. - DRUNPATH/DT_SONAME/DT_NEEDED walks now validate the shadow-section link index (sh_link < e_shnum) before dereferencing shdr[sh_link]. Verified by crafting five malformed ELF64 inputs to the new boundschecks and feeding them to the dependency resolution path: - Off-map shstrtab.sh_offset: segfault without patch, clean skip with - sh_name past table end: segfault without patch - No NUL within name's table window: segfault without patch - Section table extent truncated (F1) / sh_link past end (F6b): clean rejection with patch Regression control: -l dependency resolution of /bin/bash and /bin/ls yields byte-identical results before/after. Also verified syntax with and without HAVE_SYSTEMD (covers RESOLVE_DEPS_DLOPEN_FOR_BITS). --- src/install/dracut-install.c | 49 ++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/src/install/dracut-install.c b/src/install/dracut-install.c index a3f0cdb7c4..dbbc2ce631 100644 --- a/src/install/dracut-install.c +++ b/src/install/dracut-install.c @@ -854,6 +854,17 @@ static char *expand_runpath(const char *input, const char *src, const Elf64_Ehdr that is expanded using the C compiler rather than the preprocessor. */ #define ELF_BYTESWAP(SIZE, value) (ehdr->e_ident[EI_DATA] == ELFDATA2MSB ? be##SIZE##toh(value) : le##SIZE##toh(value)) +/* Safely look up a section name in a bounds-checked section header string + table. Returns NULL if the name offset is out of bounds or the name is + not NUL-terminated within the table. */ +static const char *elf_sect_name(const char *shstrtab, size_t shstrtab_len, uint32_t name_off) +{ + if (name_off >= shstrtab_len || !memchr(shstrtab + name_off, '\0', shstrtab_len - name_off)) + return NULL; + + return shstrtab + name_off; +} + /* Get a pointer to the ELF header map's section header string table, where B is 64 or 32 bit. Sanity checks the ELF structure to avoid crashes. */ #define PARSE_ELF_START(B, map) \ @@ -863,9 +874,24 @@ static char *expand_runpath(const char *input, const char *src, const Elf64_Ehdr ELF_BYTESWAP(B, ehdr->e_shoff) > src_len || \ ELF_BYTESWAP(16, ehdr->e_shstrndx) >= ELF_BYTESWAP(16, ehdr->e_shnum)) \ break; \ +\ + /* The whole section header table must fit into the mapped file, \ + otherwise indexing into it could read past the mapping. */ \ + if ((size_t)ELF_BYTESWAP(16, ehdr->e_shnum) > \ + (src_len - (size_t)ELF_BYTESWAP(B, ehdr->e_shoff)) / sizeof(Elf##B##_Shdr)) \ + break; \ \ Elf##B##_Shdr *shdr = (Elf##B##_Shdr *)((char *)map + ELF_BYTESWAP(B, ehdr->e_shoff)); \ - const char *shstrtab = (char *)map + ELF_BYTESWAP(B, shdr[ELF_BYTESWAP(16, ehdr->e_shstrndx)].sh_offset); + Elf##B##_Shdr *shstrshdr = &shdr[ELF_BYTESWAP(16, ehdr->e_shstrndx)]; \ +\ + /* The section header string table must fit into the mapped file, \ + otherwise comparing section names could read past the mapping. */ \ + size_t shstrtab_len = ELF_BYTESWAP(B, shstrshdr->sh_size); \ + if (ELF_BYTESWAP(B, shstrshdr->sh_offset) > src_len || \ + shstrtab_len > src_len - (size_t)ELF_BYTESWAP(B, shstrshdr->sh_offset)) \ + break; \ +\ + const char *shstrtab = (char *)map + ELF_BYTESWAP(B, shstrshdr->sh_offset); /* Expand the R(UN)PATH of the ELF header map and search it for a library matching soname and match64/match32. map must point to the same header as @@ -875,7 +901,8 @@ static char *expand_runpath(const char *input, const char *src, const Elf64_Ehdr bool seen_runpath = false; \ \ for (size_t i = 0; i < ELF_BYTESWAP(16, ehdr->e_shnum); i++) { \ - if (strcmp(&shstrtab[ELF_BYTESWAP(32, shdr[i].sh_name)], ".dynamic") != 0) \ + const char *sect_name = elf_sect_name(shstrtab, shstrtab_len, ELF_BYTESWAP(32, shdr[i].sh_name)); \ + if (!sect_name || strcmp(sect_name, ".dynamic") != 0) \ continue; \ \ Elf##B##_Dyn *dyn = (Elf##B##_Dyn *)((char *)map + ELF_BYTESWAP(B, shdr[i].sh_offset)); \ @@ -884,6 +911,9 @@ static char *expand_runpath(const char *input, const char *src, const Elf64_Ehdr seen_runpath = true; /* RUNPATH has precedence over RPATH. */ \ else if (seen_runpath || ELF_BYTESWAP(B, d->d_tag) != DT_RPATH) \ continue; \ +\ + if (ELF_BYTESWAP(32, shdr[i].sh_link) >= ELF_BYTESWAP(16, ehdr->e_shnum)) \ + break; \ \ char *runpath = (char *)map + ELF_BYTESWAP(B, shdr[ELF_BYTESWAP(32, shdr[i].sh_link)].sh_offset) + ELF_BYTESWAP(B, d->d_un.d_val); \ _cleanup_free_ char *expanded = expand_runpath(runpath, src, match64); \ @@ -1025,7 +1055,8 @@ static void resolve_deps_dlopen_parse_json(Hashmap *pdeps, Hashmap *deps, const for (size_t i = 0; !soname && i < ELF_BYTESWAP(16, ehdr->e_shnum); i++) { \ if ((char*)&shdr[i] < (char*)map || (char*)&shdr[i] + sizeof(Elf##B##_Shdr) > (char*)map + src_len) \ break; \ - if (strcmp(&shstrtab[ELF_BYTESWAP(32, shdr[i].sh_name)], ".dynamic") != 0) \ + const char *sect_name = elf_sect_name(shstrtab, shstrtab_len, ELF_BYTESWAP(32, shdr[i].sh_name)); \ + if (!sect_name || strcmp(sect_name, ".dynamic") != 0) \ continue; \ \ Elf##B##_Dyn *dyn = (Elf##B##_Dyn *)((char *)map + ELF_BYTESWAP(B, shdr[i].sh_offset)); \ @@ -1037,6 +1068,9 @@ static void resolve_deps_dlopen_parse_json(Hashmap *pdeps, Hashmap *deps, const break; \ if (ELF_BYTESWAP(B, d->d_tag) != DT_SONAME) \ continue; \ +\ + if (ELF_BYTESWAP(32, shdr[i].sh_link) >= ELF_BYTESWAP(16, ehdr->e_shnum)) \ + break; \ \ soname = (char *)map + ELF_BYTESWAP(B, shdr[ELF_BYTESWAP(32, shdr[i].sh_link)].sh_offset) + ELF_BYTESWAP(B, d->d_un.d_val); \ if ((char *)soname < (char *)map || (char *)soname > (char *)map + src_len) { \ @@ -1049,7 +1083,8 @@ static void resolve_deps_dlopen_parse_json(Hashmap *pdeps, Hashmap *deps, const for (size_t i = 0; i < ELF_BYTESWAP(16, ehdr->e_shnum); i++) { \ if ((char*)shdr + i * sizeof(Elf##B##_Shdr) > (char*)map + src_len) \ break; \ - if (strcmp(&shstrtab[ELF_BYTESWAP(32, shdr[i].sh_name)], ".note.dlopen") != 0) \ + const char *sect_name = elf_sect_name(shstrtab, shstrtab_len, ELF_BYTESWAP(32, shdr[i].sh_name)); \ + if (!sect_name || strcmp(sect_name, ".note.dlopen") != 0) \ continue; \ \ const char *note_offset = (char *)map + ELF_BYTESWAP(B, shdr[i].sh_offset); \ @@ -1112,7 +1147,8 @@ static void resolve_deps_dlopen_parse_json(Hashmap *pdeps, Hashmap *deps, const for (size_t i = 0; i < ELF_BYTESWAP(16, ehdr->e_shnum); i++) { \ if ((char*)&shdr[i] < (char*)map || (char*)&shdr[i] + sizeof(Elf##B##_Shdr) > (char*)map + src_len) \ break; \ - if (strcmp(&shstrtab[ELF_BYTESWAP(32, shdr[i].sh_name)], ".dynamic") != 0) \ + const char *sect_name = elf_sect_name(shstrtab, shstrtab_len, ELF_BYTESWAP(32, shdr[i].sh_name)); \ + if (!sect_name || strcmp(sect_name, ".dynamic") != 0) \ continue; \ \ Elf##B##_Dyn *dyn = (Elf##B##_Dyn *)((char *)map + ELF_BYTESWAP(B, shdr[i].sh_offset)); \ @@ -1124,6 +1160,9 @@ static void resolve_deps_dlopen_parse_json(Hashmap *pdeps, Hashmap *deps, const break; \ if (ELF_BYTESWAP(B, d->d_tag) != DT_NEEDED) \ continue; \ +\ + if (ELF_BYTESWAP(32, shdr[i].sh_link) >= ELF_BYTESWAP(16, ehdr->e_shnum)) \ + break; \ \ const char *soname = (char *)map + ELF_BYTESWAP(B, shdr[ELF_BYTESWAP(32, shdr[i].sh_link)].sh_offset) + ELF_BYTESWAP(B, d->d_un.d_val); \ if ((char *)soname < (char *)map || (char *)soname > (char *)map + src_len) \ From 26faa415474b73e05cc6d0abc78123f2da10bb07 Mon Sep 17 00:00:00 2001 From: Prabhakar Pujeri Date: Thu, 20 Aug 2026 11:41:16 +0530 Subject: [PATCH 2/3] fix(dracut-install): bounds-check RUNPATH walk and ELF string derefs The FIND_LIBRARY_RUNPATH_FOR_BITS macro lacked the bounds checks its sibling macros (RESOLVE_DEPS_NEEDED_FOR_BITS, RESOLVE_DEPS_DLOPEN_FOR_BITS) have: - the .dynamic section's shdr[]-indexed pointer into the map - the per-iteration Elf_Dyn pointer in the DT_NULL-terminated walk - the interpreter string (PT_INTERP) and DT_SONAME/DT_NEEDED string, passed to strdup/strlen with no NUL-termination verification A malformed ELF could put a non-NUL-terminated runpath right at the end of the map (reads past it in strlen), or an interpreter offset exactly == src_len (off by > vs >=) that passed the old bounds check. Add a shared helper, elf_map_string(), that validates the offset is inside the map and the string is NUL-terminated there, and use it at every place the code dereferences a dynamic-entry/segment-list string. Mirror the per-iteration map-range checks in the RUNPATH walk that the sibling macros already carry. Depends on 0549d1c3 ("fix(dracut-install): validate ELF section-table bounds"), which introduced elf_sect_name() and the PARSE_ELF_START extent checks. Verified with valgrind on crafted malformed ELF64s (pre-patch SIGSEGV reading past the mmap; post-patch clean) and byte-for-byte identical dependency sets for real binaries (/bin/bash, /bin/ls, /usr/bin/ssh). --- src/install/dracut-install.c | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/src/install/dracut-install.c b/src/install/dracut-install.c index dbbc2ce631..c917e1a6c4 100644 --- a/src/install/dracut-install.c +++ b/src/install/dracut-install.c @@ -865,6 +865,17 @@ static const char *elf_sect_name(const char *shstrtab, size_t shstrtab_len, uint return shstrtab + name_off; } +/* Return a pointer to the NUL-terminated string at the given offset within + the mapped file, or NULL if the offset is out of bounds or the string + would not be NUL-terminated within the map. */ +static const char *elf_map_string(const char *map, size_t src_len, size_t offset) +{ + if (offset >= src_len || !memchr(map + offset, '\0', src_len - offset)) + return NULL; + + return map + offset; +} + /* Get a pointer to the ELF header map's section header string table, where B is 64 or 32 bit. Sanity checks the ELF structure to avoid crashes. */ #define PARSE_ELF_START(B, map) \ @@ -906,7 +917,12 @@ static const char *elf_sect_name(const char *shstrtab, size_t shstrtab_len, uint continue; \ \ Elf##B##_Dyn *dyn = (Elf##B##_Dyn *)((char *)map + ELF_BYTESWAP(B, shdr[i].sh_offset)); \ + if ((char *)dyn < (char *)map || (char *)dyn > (char *)map + src_len) \ + break; \ +\ for (Elf##B##_Dyn *d = dyn; ELF_BYTESWAP(32, d->d_tag) != DT_NULL; d++) { \ + if ((char *)d < (char *)map || (char *)d + sizeof(Elf##B##_Dyn) > (char *)map + src_len) \ + break; \ if (ELF_BYTESWAP(B, d->d_tag) == DT_RUNPATH) \ seen_runpath = true; /* RUNPATH has precedence over RPATH. */ \ else if (seen_runpath || ELF_BYTESWAP(B, d->d_tag) != DT_RPATH) \ @@ -915,7 +931,10 @@ static const char *elf_sect_name(const char *shstrtab, size_t shstrtab_len, uint if (ELF_BYTESWAP(32, shdr[i].sh_link) >= ELF_BYTESWAP(16, ehdr->e_shnum)) \ break; \ \ - char *runpath = (char *)map + ELF_BYTESWAP(B, shdr[ELF_BYTESWAP(32, shdr[i].sh_link)].sh_offset) + ELF_BYTESWAP(B, d->d_un.d_val); \ + const char *runpath = elf_map_string((const char *)map, src_len, ELF_BYTESWAP(B, shdr[ELF_BYTESWAP(32, shdr[i].sh_link)].sh_offset) + ELF_BYTESWAP(B, d->d_un.d_val)); \ + if (!runpath) \ + break; \ +\ _cleanup_free_ char *expanded = expand_runpath(runpath, src, match64); \ if (!expanded) \ continue; \ @@ -1072,11 +1091,9 @@ static void resolve_deps_dlopen_parse_json(Hashmap *pdeps, Hashmap *deps, const if (ELF_BYTESWAP(32, shdr[i].sh_link) >= ELF_BYTESWAP(16, ehdr->e_shnum)) \ break; \ \ - soname = (char *)map + ELF_BYTESWAP(B, shdr[ELF_BYTESWAP(32, shdr[i].sh_link)].sh_offset) + ELF_BYTESWAP(B, d->d_un.d_val); \ - if ((char *)soname < (char *)map || (char *)soname > (char *)map + src_len) { \ - soname = NULL; \ + soname = elf_map_string((const char *)map, src_len, ELF_BYTESWAP(B, shdr[ELF_BYTESWAP(32, shdr[i].sh_link)].sh_offset) + ELF_BYTESWAP(B, d->d_un.d_val)); \ + if (!soname) \ break; \ - } \ } \ } \ \ @@ -1129,8 +1146,8 @@ static void resolve_deps_dlopen_parse_json(Hashmap *pdeps, Hashmap *deps, const if (ELF_BYTESWAP(32, phdr->p_type) != PT_INTERP) \ continue; \ \ - const char *interpreter = (const char *)map + ELF_BYTESWAP(B, phdr->p_offset); \ - if (interpreter < (char *)map || interpreter > (char *)map + src_len) \ + const char *interpreter = elf_map_string((const char *)map, src_len, ELF_BYTESWAP(B, phdr->p_offset)); \ + if (!interpreter) \ break; \ if (hashmap_get(pdeps, interpreter)) \ continue; \ @@ -1164,8 +1181,8 @@ static void resolve_deps_dlopen_parse_json(Hashmap *pdeps, Hashmap *deps, const if (ELF_BYTESWAP(32, shdr[i].sh_link) >= ELF_BYTESWAP(16, ehdr->e_shnum)) \ break; \ \ - const char *soname = (char *)map + ELF_BYTESWAP(B, shdr[ELF_BYTESWAP(32, shdr[i].sh_link)].sh_offset) + ELF_BYTESWAP(B, d->d_un.d_val); \ - if ((char *)soname < (char *)map || (char *)soname > (char *)map + src_len) \ + const char *soname = elf_map_string((const char *)map, src_len, ELF_BYTESWAP(B, shdr[ELF_BYTESWAP(32, shdr[i].sh_link)].sh_offset) + ELF_BYTESWAP(B, d->d_un.d_val)); \ + if (!soname) \ break; \ if (hashmap_get(pdeps, soname)) \ continue; \ From a0e87b3490b35931f72e92c790866fa765f7cece Mon Sep 17 00:00:00 2001 From: Prabhakar Pujeri Date: Fri, 21 Aug 2026 13:20:50 +0530 Subject: [PATCH 3/3] refactor(dracut-install): use void * casts for raw ELF map pointers Address review feedback: (void *) rather than (char *) for the pointer arithmetic/comparison casts against the mmap'ed region is equivalent under GNU C and reads less confusingly, since map is an untyped blob. No functional change. --- src/install/dracut-install.c | 46 ++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/install/dracut-install.c b/src/install/dracut-install.c index c917e1a6c4..766341f071 100644 --- a/src/install/dracut-install.c +++ b/src/install/dracut-install.c @@ -892,7 +892,7 @@ static const char *elf_map_string(const char *map, size_t src_len, size_t offset (src_len - (size_t)ELF_BYTESWAP(B, ehdr->e_shoff)) / sizeof(Elf##B##_Shdr)) \ break; \ \ - Elf##B##_Shdr *shdr = (Elf##B##_Shdr *)((char *)map + ELF_BYTESWAP(B, ehdr->e_shoff)); \ + Elf##B##_Shdr *shdr = (Elf##B##_Shdr *)((void *)map + ELF_BYTESWAP(B, ehdr->e_shoff)); \ Elf##B##_Shdr *shstrshdr = &shdr[ELF_BYTESWAP(16, ehdr->e_shstrndx)]; \ \ /* The section header string table must fit into the mapped file, \ @@ -902,7 +902,7 @@ static const char *elf_map_string(const char *map, size_t src_len, size_t offset shstrtab_len > src_len - (size_t)ELF_BYTESWAP(B, shstrshdr->sh_offset)) \ break; \ \ - const char *shstrtab = (char *)map + ELF_BYTESWAP(B, shstrshdr->sh_offset); + const char *shstrtab = (void *)map + ELF_BYTESWAP(B, shstrshdr->sh_offset); /* Expand the R(UN)PATH of the ELF header map and search it for a library matching soname and match64/match32. map must point to the same header as @@ -916,12 +916,12 @@ static const char *elf_map_string(const char *map, size_t src_len, size_t offset if (!sect_name || strcmp(sect_name, ".dynamic") != 0) \ continue; \ \ - Elf##B##_Dyn *dyn = (Elf##B##_Dyn *)((char *)map + ELF_BYTESWAP(B, shdr[i].sh_offset)); \ - if ((char *)dyn < (char *)map || (char *)dyn > (char *)map + src_len) \ + Elf##B##_Dyn *dyn = (Elf##B##_Dyn *)((void *)map + ELF_BYTESWAP(B, shdr[i].sh_offset)); \ + if ((void *)dyn < (void *)map || (void *)dyn > (void *)map + src_len) \ break; \ \ for (Elf##B##_Dyn *d = dyn; ELF_BYTESWAP(32, d->d_tag) != DT_NULL; d++) { \ - if ((char *)d < (char *)map || (char *)d + sizeof(Elf##B##_Dyn) > (char *)map + src_len) \ + if ((void *)d < (void *)map || (void *)d + sizeof(Elf##B##_Dyn) > (void *)map + src_len) \ break; \ if (ELF_BYTESWAP(B, d->d_tag) == DT_RUNPATH) \ seen_runpath = true; /* RUNPATH has precedence over RPATH. */ \ @@ -931,7 +931,7 @@ static const char *elf_map_string(const char *map, size_t src_len, size_t offset if (ELF_BYTESWAP(32, shdr[i].sh_link) >= ELF_BYTESWAP(16, ehdr->e_shnum)) \ break; \ \ - const char *runpath = elf_map_string((const char *)map, src_len, ELF_BYTESWAP(B, shdr[ELF_BYTESWAP(32, shdr[i].sh_link)].sh_offset) + ELF_BYTESWAP(B, d->d_un.d_val)); \ + const char *runpath = elf_map_string((const void *)map, src_len, ELF_BYTESWAP(B, shdr[ELF_BYTESWAP(32, shdr[i].sh_link)].sh_offset) + ELF_BYTESWAP(B, d->d_un.d_val)); \ if (!runpath) \ break; \ \ @@ -1072,18 +1072,18 @@ static void resolve_deps_dlopen_parse_json(Hashmap *pdeps, Hashmap *deps, const size_t note_idx = -1; \ \ for (size_t i = 0; !soname && i < ELF_BYTESWAP(16, ehdr->e_shnum); i++) { \ - if ((char*)&shdr[i] < (char*)map || (char*)&shdr[i] + sizeof(Elf##B##_Shdr) > (char*)map + src_len) \ + if ((void *)&shdr[i] < (void *)map || (void *)&shdr[i] + sizeof(Elf##B##_Shdr) > (void *)map + src_len) \ break; \ const char *sect_name = elf_sect_name(shstrtab, shstrtab_len, ELF_BYTESWAP(32, shdr[i].sh_name)); \ if (!sect_name || strcmp(sect_name, ".dynamic") != 0) \ continue; \ \ - Elf##B##_Dyn *dyn = (Elf##B##_Dyn *)((char *)map + ELF_BYTESWAP(B, shdr[i].sh_offset)); \ - if ((char *)dyn < (char *)map || (char *)dyn > (char *)map + src_len) \ + Elf##B##_Dyn *dyn = (Elf##B##_Dyn *)((void *)map + ELF_BYTESWAP(B, shdr[i].sh_offset)); \ + if ((void *)dyn < (void *)map || (void *)dyn > (void *)map + src_len) \ break; \ \ for (Elf##B##_Dyn *d = dyn; !soname && ELF_BYTESWAP(32, d->d_tag) != DT_NULL; d++) { \ - if ((char *)d < (char *)map || (char *)d + sizeof(Elf##B##_Dyn) > (char *)map + src_len) \ + if ((void *)d < (void *)map || (void *)d + sizeof(Elf##B##_Dyn) > (void *)map + src_len) \ break; \ if (ELF_BYTESWAP(B, d->d_tag) != DT_SONAME) \ continue; \ @@ -1091,23 +1091,23 @@ static void resolve_deps_dlopen_parse_json(Hashmap *pdeps, Hashmap *deps, const if (ELF_BYTESWAP(32, shdr[i].sh_link) >= ELF_BYTESWAP(16, ehdr->e_shnum)) \ break; \ \ - soname = elf_map_string((const char *)map, src_len, ELF_BYTESWAP(B, shdr[ELF_BYTESWAP(32, shdr[i].sh_link)].sh_offset) + ELF_BYTESWAP(B, d->d_un.d_val)); \ + soname = elf_map_string((const void *)map, src_len, ELF_BYTESWAP(B, shdr[ELF_BYTESWAP(32, shdr[i].sh_link)].sh_offset) + ELF_BYTESWAP(B, d->d_un.d_val)); \ if (!soname) \ break; \ } \ } \ \ for (size_t i = 0; i < ELF_BYTESWAP(16, ehdr->e_shnum); i++) { \ - if ((char*)shdr + i * sizeof(Elf##B##_Shdr) > (char*)map + src_len) \ + if ((void *)shdr + i * sizeof(Elf##B##_Shdr) > (void *)map + src_len) \ break; \ const char *sect_name = elf_sect_name(shstrtab, shstrtab_len, ELF_BYTESWAP(32, shdr[i].sh_name)); \ if (!sect_name || strcmp(sect_name, ".note.dlopen") != 0) \ continue; \ \ - const char *note_offset = (char *)map + ELF_BYTESWAP(B, shdr[i].sh_offset); \ + const char *note_offset = (void *)map + ELF_BYTESWAP(B, shdr[i].sh_offset); \ const char *note_end = note_offset + ELF_BYTESWAP(32, shdr[i].sh_size); \ \ - if (note_offset < (char*)map || note_end > (char*)map + src_len || note_end < note_offset) \ + if (note_offset < (void *)map || note_end > (void *)map + src_len || note_end < note_offset) \ continue; \ \ while (note_offset < note_end) { \ @@ -1119,7 +1119,7 @@ static void resolve_deps_dlopen_parse_json(Hashmap *pdeps, Hashmap *deps, const \ const char *note_desc = note_offset; \ note_offset += (ELF_BYTESWAP(32, nhdr->n_descsz) + 3) & ~3; /* Align to 4 bytes */ \ - if (note_offset > (char*)map + src_len) \ + if (note_offset > (void *)map + src_len) \ break; \ \ if (ELF_BYTESWAP(32, nhdr->n_type) != 0x407c0c0a) \ @@ -1140,13 +1140,13 @@ static void resolve_deps_dlopen_parse_json(Hashmap *pdeps, Hashmap *deps, const \ if (ELF_BYTESWAP(16, ehdr->e_type) == ET_EXEC || ELF_BYTESWAP(16, ehdr->e_type) == ET_DYN) { \ for (size_t ph_idx = 0; ph_idx < ELF_BYTESWAP(16, ehdr->e_phnum); ph_idx++) { \ - Elf##B##_Phdr *phdr = (Elf##B##_Phdr *)((char *)map + ELF_BYTESWAP(B, ehdr->e_phoff) + ph_idx * ELF_BYTESWAP(16, ehdr->e_phentsize)); \ - if ((char *)phdr < (char *)map || (char *)phdr + sizeof(Elf##B##_Phdr) > (char *)map + src_len) \ + Elf##B##_Phdr *phdr = (Elf##B##_Phdr *)((void *)map + ELF_BYTESWAP(B, ehdr->e_phoff) + ph_idx * ELF_BYTESWAP(16, ehdr->e_phentsize)); \ + if ((void *)phdr < (void *)map || (void *)phdr + sizeof(Elf##B##_Phdr) > (void *)map + src_len) \ break; \ if (ELF_BYTESWAP(32, phdr->p_type) != PT_INTERP) \ continue; \ \ - const char *interpreter = elf_map_string((const char *)map, src_len, ELF_BYTESWAP(B, phdr->p_offset)); \ + const char *interpreter = elf_map_string((const void *)map, src_len, ELF_BYTESWAP(B, phdr->p_offset)); \ if (!interpreter) \ break; \ if (hashmap_get(pdeps, interpreter)) \ @@ -1162,18 +1162,18 @@ static void resolve_deps_dlopen_parse_json(Hashmap *pdeps, Hashmap *deps, const } \ \ for (size_t i = 0; i < ELF_BYTESWAP(16, ehdr->e_shnum); i++) { \ - if ((char*)&shdr[i] < (char*)map || (char*)&shdr[i] + sizeof(Elf##B##_Shdr) > (char*)map + src_len) \ + if ((void *)&shdr[i] < (void *)map || (void *)&shdr[i] + sizeof(Elf##B##_Shdr) > (void *)map + src_len) \ break; \ const char *sect_name = elf_sect_name(shstrtab, shstrtab_len, ELF_BYTESWAP(32, shdr[i].sh_name)); \ if (!sect_name || strcmp(sect_name, ".dynamic") != 0) \ continue; \ \ - Elf##B##_Dyn *dyn = (Elf##B##_Dyn *)((char *)map + ELF_BYTESWAP(B, shdr[i].sh_offset)); \ - if ((char *)dyn < (char *)map || (char *)dyn > (char *)map + src_len) \ + Elf##B##_Dyn *dyn = (Elf##B##_Dyn *)((void *)map + ELF_BYTESWAP(B, shdr[i].sh_offset)); \ + if ((void *)dyn < (void *)map || (void *)dyn > (void *)map + src_len) \ break; \ \ for (Elf##B##_Dyn *d = dyn; ELF_BYTESWAP(32, d->d_tag) != DT_NULL; d++) { \ - if ((char *)d < (char *)map || (char *)d + sizeof(Elf##B##_Dyn) > (char *)map + src_len) \ + if ((void *)d < (void *)map || (void *)d + sizeof(Elf##B##_Dyn) > (void *)map + src_len) \ break; \ if (ELF_BYTESWAP(B, d->d_tag) != DT_NEEDED) \ continue; \ @@ -1181,7 +1181,7 @@ static void resolve_deps_dlopen_parse_json(Hashmap *pdeps, Hashmap *deps, const if (ELF_BYTESWAP(32, shdr[i].sh_link) >= ELF_BYTESWAP(16, ehdr->e_shnum)) \ break; \ \ - const char *soname = elf_map_string((const char *)map, src_len, ELF_BYTESWAP(B, shdr[ELF_BYTESWAP(32, shdr[i].sh_link)].sh_offset) + ELF_BYTESWAP(B, d->d_un.d_val)); \ + const char *soname = elf_map_string((const void *)map, src_len, ELF_BYTESWAP(B, shdr[ELF_BYTESWAP(32, shdr[i].sh_link)].sh_offset) + ELF_BYTESWAP(B, d->d_un.d_val)); \ if (!soname) \ break; \ if (hashmap_get(pdeps, soname)) \