]> git.ipfire.org Git - pakfire.git/commitdiff
ELF: Move SSP check
authorMichael Tremer <michael.tremer@ipfire.org>
Wed, 1 Jan 2025 17:39:04 +0000 (17:39 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Wed, 1 Jan 2025 17:39:33 +0000 (17:39 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/elf.c
src/libpakfire/include/pakfire/elf.h
src/libpakfire/linter-file.c

index 833e2fefb5b4ef1b5517ecc0bfeba1417f803255..27b78b319fc0ecef4e52fab8d94e24a257918304 100644 (file)
@@ -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;
 
index b97b6a501231832d6214288eeaba57f1dc26e3b3..54f3713c7807b3a5cf3d202182acea7e853bcc96 100644 (file)
@@ -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 */
index 42f92c55b3b17a51a0bdf2c27a29051d32c22d54..e8b6237013bd27b2c6594bf876dcd3a107470506 100644 (file)
@@ -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) {