From: Michael Tremer Date: Wed, 1 Jan 2025 17:39:04 +0000 (+0000) Subject: ELF: Move SSP check X-Git-Tag: 0.9.30~597 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=45d9ba436745c0da67207a81458101e4f8513fe3;p=pakfire.git ELF: Move SSP check Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/elf.c b/src/libpakfire/elf.c index 833e2fefb..27b78b319 100644 --- a/src/libpakfire/elf.c +++ b/src/libpakfire/elf.c @@ -300,6 +300,62 @@ int pakfire_elf_is_pie(struct pakfire_elf* self) { return 0; } +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; + int r; + + // Fetch the symbol table + r = pakfire_elf_get_section(self, SHT_SYMTAB, &symtab, &shdr, &data); + if (r) { + DEBUG(self->ctx, "%s has no symbol table\n", self->path); + return 0; + } + + // Count any global functions + 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); + + // Fetch the symbol name + name = elf_strptr(self->elf, shdr.sh_link, symbol.st_name); + + // Skip empty section names + if (!name || !*name) + continue; + + // Exit if there is a symbol called "__stack_chk_fail" + if (pakfire_string_startswith(name, "__stack_chk_fail")) + return 1; + + // Or if the symbol is called __stack_chk_guard + else if (pakfire_string_startswith(name, "__stack_chk_guard")) + return 1; + + // Or if the symbol is called __intel_security_cookie + else if (pakfire_string_startswith(name, "__intel_security_cookie")) + return 1; + + // Count any global functions + if ((ELF64_ST_BIND(symbol.st_info) == STB_GLOBAL) && + (ELF64_ST_TYPE(symbol.st_info) == STT_FUNC)) + counter++; + } + + // If we have something that does not have an exported function, we just assume yes + if (!counter) { + DEBUG(self->ctx, "%s has no functions. Skipping SSP check.\n", self->path); + return 1; + } + + return 0; +} + int pakfire_elf_is_stripped(struct pakfire_elf* self) { Elf_Scn* symtab = NULL; diff --git a/src/libpakfire/include/pakfire/elf.h b/src/libpakfire/include/pakfire/elf.h index b97b6a501..54f3713c7 100644 --- a/src/libpakfire/include/pakfire/elf.h +++ b/src/libpakfire/include/pakfire/elf.h @@ -43,6 +43,7 @@ const char* pakfire_elf_build_id(struct pakfire_elf* self); const char* pakfire_elf_debuglink(struct pakfire_elf* self); int pakfire_elf_is_pie(struct pakfire_elf* self); +int pakfire_elf_has_ssp(struct pakfire_elf* self); int pakfire_elf_is_stripped(struct pakfire_elf* self); #endif /* PAKFIRE_PRIVATE */ diff --git a/src/libpakfire/linter-file.c b/src/libpakfire/linter-file.c index 42f92c55b..e8b623701 100644 --- a/src/libpakfire/linter-file.c +++ b/src/libpakfire/linter-file.c @@ -455,13 +455,6 @@ static int pakfire_linter_file_check_pie(struct pakfire_linter_file* lfile) { } static int pakfire_linter_file_check_ssp(struct pakfire_linter_file* lfile) { - Elf_Scn* symtab = NULL; - GElf_Shdr shdr; - Elf_Data* elf_data = NULL; - GElf_Sym symbol; - const char* name = NULL; - int r; - // This check will be skipped for these files static const char* whitelist[] = { "/usr/lib64/libgcc_s.so.*", @@ -481,54 +474,11 @@ static int pakfire_linter_file_check_ssp(struct pakfire_linter_file* lfile) { } } - // Fetch the symbol table - r = pakfire_linter_file_get_elf_section(lfile, SHT_SYMTAB, &symtab, &shdr, &elf_data); - if (r) { - DEBUG(lfile->ctx, "%s has no symbol table\n", lfile->path); - return 1; - } - - // Count any global functions - size_t counter = 0; - - // Walk through all symbols - for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) { - gelf_getsym(elf_data, i, &symbol); - - // Fetch the symbol name - name = elf_strptr(lfile->elf, shdr.sh_link, symbol.st_name); - - // Skip empty section names - if (!name || !*name) - continue; - - // Exit if there is a symbol called "__stack_chk_fail" - if (pakfire_string_startswith(name, "__stack_chk_fail")) - return 0; - - // Or if the symbol is called __stack_chk_guard - else if (pakfire_string_startswith(name, "__stack_chk_guard")) - return 0; - - // Or if the symbol is called __intel_security_cookie - else if (pakfire_string_startswith(name, "__intel_security_cookie")) - return 0; - - // Count any global functions - if ((ELF64_ST_BIND(symbol.st_info) == STB_GLOBAL) && - (ELF64_ST_TYPE(symbol.st_info) == STT_FUNC)) - counter++; - } - - // We do not perform the check for libraries that do not contain any functions. - // Some packages use shared libraries to provide data. - if (!counter) { - DEBUG(lfile->ctx, "%s: File has no functions. Skipping SSP check.\n", lfile->path); - return 0; - } + // Report an error if there is not SSP + if (!pakfire_elf_has_ssp(lfile->_elf)) + return pakfire_linter_file_error(lfile, "Missing Stack Smashing Protection"); - // The file does not seem to have SSP enabled - return pakfire_linter_file_error(lfile, "Missing Stack Smashing Protection"); + return 0; } static int pakfire_linter_file_check_execstack(struct pakfire_linter_file* lfile) {