From: Michael Tremer Date: Thu, 2 Jan 2025 16:19:40 +0000 (+0000) Subject: ELF: Base the SSP check on the dynamic section X-Git-Tag: 0.9.30~588 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=55e384128fc47da671de4e97d456296b1031c70f;p=pakfire.git ELF: Base the SSP check on the dynamic section This works even if we have fully stripped the binary. Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/elf.c b/src/libpakfire/elf.c index 1a495c5ec..d0faadb50 100644 --- a/src/libpakfire/elf.c +++ b/src/libpakfire/elf.c @@ -261,9 +261,20 @@ const char* pakfire_elf_debuglink(struct pakfire_elf* self) { } static int pakfire_elf_get_section(struct pakfire_elf* self, - const Elf64_Word type, Elf_Scn** section, GElf_Shdr* header, Elf_Data** data) { + const Elf64_Word type, const char* name, Elf_Scn** section, GElf_Shdr* header, Elf_Data** data) { + const char* sname = NULL; Elf_Scn* s = NULL; GElf_Shdr shdr; + int r; + + size_t shstrndx = 0; + + // Find the strings + r = elf_getshdrstrndx(self->elf, &shstrndx); + if (r < 0) { + ERROR(self->ctx, "elf_getshdrstrndx() failed: %s\n", elf_errmsg(-1)); + return r; + } // Walk through all sections for (;;) { @@ -276,6 +287,18 @@ static int pakfire_elf_get_section(struct pakfire_elf* self, // Return any matching sections if (shdr.sh_type == type) { + // If we have a name, check it too + if (name) { + sname = elf_strptr(self->elf, shstrndx, shdr.sh_name); + if (!sname) + continue; + + // Skip if the name does not match + if (!pakfire_string_equals(name, sname)) + continue; + } + + // Return a pointer to the section *section = s; // Send header if requested @@ -341,7 +364,7 @@ static int pakfire_elf_dyn_walk(struct pakfire_elf* self, int r; // Find the dynamic linking information - r = pakfire_elf_get_section(self, SHT_DYNAMIC, &dynamic, &shdr, &elf_data); + r = pakfire_elf_get_section(self, SHT_DYNAMIC, NULL, &dynamic, &shdr, &elf_data); if (r) { DEBUG(self->ctx, "%s does not have a dynamic section\n", self->path); return r; @@ -377,17 +400,30 @@ int pakfire_elf_is_pie(struct pakfire_elf* self) { } int pakfire_elf_has_ssp(struct pakfire_elf* self) { - const char* name = NULL; - Elf_Scn* symtab = NULL; - GElf_Shdr shdr; - Elf_Data* data = NULL; - GElf_Sym symbol; + GElf_Sym symbol = {}; int r; - // Fetch the symbol table - r = pakfire_elf_get_section(self, SHT_SYMTAB, &symtab, &shdr, &data); + // .dynsym + Elf_Scn* dynsym = NULL; + GElf_Shdr symhdr = {}; + Elf_Data* symdata = NULL; + + // .dynstr + Elf_Scn* dynstr = NULL; + GElf_Shdr strhdr = {}; + Elf_Data* strdata = NULL; + + // Fetch .dynsym + r = pakfire_elf_get_section(self, SHT_DYNSYM, NULL, &dynsym, &symhdr, &symdata); + if (r) { + DEBUG(self->ctx, "%s has no .dynsym section\n", self->path); + return 0; + } + + // Fetch .dynstr + r = pakfire_elf_get_section(self, SHT_STRTAB, ".dynstr", &dynstr, &strhdr, &strdata); if (r) { - DEBUG(self->ctx, "%s has no symbol table\n", self->path); + DEBUG(self->ctx, "%s has no .dynstr section\n", self->path); return 0; } @@ -395,11 +431,11 @@ int pakfire_elf_has_ssp(struct pakfire_elf* self) { size_t counter = 0; // Walk through all symbols - for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) { - gelf_getsym(data, i, &symbol); + for (unsigned int i = 0; i < symhdr.sh_size / symhdr.sh_entsize; i++) { + gelf_getsym(symdata, i, &symbol); // Fetch the symbol name - name = elf_strptr(self->elf, shdr.sh_link, symbol.st_name); + const char* name = elf_strptr(self->elf, elf_ndxscn(dynstr), symbol.st_name); // Skip empty section names if (!name || !*name) @@ -769,5 +805,5 @@ int pakfire_elf_is_stripped(struct pakfire_elf* self) { } // Fetch the symbol table - return pakfire_elf_get_section(self, SHT_SYMTAB, &symtab, NULL, NULL); + return pakfire_elf_get_section(self, SHT_SYMTAB, NULL, &symtab, NULL, NULL); }