]> git.ipfire.org Git - pakfire.git/commitdiff
linter: Move the SSP check
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 26 Oct 2024 09:56:58 +0000 (09:56 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 26 Oct 2024 09:56:58 +0000 (09:56 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/file.c
src/libpakfire/include/pakfire/file.h
src/libpakfire/linter-file.c

index af129bb8d7240e7119a6fe014b4cfa0c72984991..b26242ae9bf010546ff9475ec336b9c1e176a784 100644 (file)
@@ -752,13 +752,6 @@ char* pakfire_file_dump(struct pakfire_file* file, int flags) {
                                goto ERROR;
                }
 
-               // Stack-smashing Protection
-               if (file->issues & PAKFIRE_FILE_MISSING_SSP) {
-                       r = asprintf(&buffer, "%s [MISSING-SSP]", buffer);
-                       if (r < 0)
-                               goto ERROR;
-               }
-
                // Executable Stack
                if (file->issues & PAKFIRE_FILE_EXECSTACK) {
                        r = asprintf(&buffer, "%s [EXECSTACK]", buffer);
@@ -2035,88 +2028,6 @@ static int pakfire_file_check_debuginfo(struct pakfire_file* file) {
        return pakfire_file_open_elf(file, __pakfire_file_check_debuginfo, NULL);
 }
 
-static int __pakfire_file_check_ssp(
-               struct pakfire_file* file, Elf* elf, void* data) {
-       Elf_Scn* symtab = NULL;
-       GElf_Shdr shdr;
-       Elf_Data* elf_data = NULL;
-       GElf_Sym symbol;
-       const char* name = NULL;
-       int r;
-
-       // Fetch the symbol table
-       r = pakfire_file_get_elf_section(file, elf, SHT_SYMTAB, &symtab, &shdr, &elf_data);
-       if (r) {
-               ERROR(file->ctx, "%s has no symbol table\n", pakfire_file_get_path(file));
-               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(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;
-
-               // 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(file->ctx, "%s: File has no functions. Skipping SSP check.\n",
-                       pakfire_file_get_path(file));
-               return 0;
-       }
-
-       // The file does not seem to have SSP enabled
-       file->issues |= PAKFIRE_FILE_MISSING_SSP;
-
-       return 0;
-}
-
-static int pakfire_file_check_ssp(struct pakfire_file* file) {
-       // This check will be skipped for these files
-       static const char* whitelist[] = {
-               "/usr/lib64/libgcc_s.so.*",
-               "/usr/lib64/libmvec.so.*",
-               NULL,
-       };
-
-       // Do not perform this check for runtime linkers
-       if (pakfire_file_matches_class(file, PAKFIRE_FILE_RUNTIME_LINKER))
-               return 0;
-
-       // We cannot perform this check if we don't have debuginfo
-       if (file->issues & PAKFIRE_FILE_MISSING_DEBUGINFO)
-               return 0;
-
-       // Check if this file is whitelisted
-       for (const char** path = whitelist; *path; path++) {
-               if (pakfire_file_matches(file, *path)) {
-                       DEBUG(file->ctx, "Skipping SSP check for whitelisted file %s\n",
-                               pakfire_file_get_path(file));
-                       return 0;
-               }
-       }
-
-       return pakfire_file_open_elf(file, __pakfire_file_check_ssp, NULL);
-}
-
 static int __pakfire_file_check_execstack(
                struct pakfire_file* file, Elf* elf, void* data) {
        GElf_Phdr phdr;
@@ -2828,11 +2739,6 @@ int pakfire_file_check(struct pakfire_file* file, int* issues) {
                        if (r)
                                return r;
 
-                       // Check for SSP
-                       r = pakfire_file_check_ssp(file);
-                       if (r)
-                               return r;
-
                        // Check for executable stacks
                        r = pakfire_file_check_execstack(file);
                        if (r)
index 326fd4d3c1552342d589a78f36370a9d2e35e153..d60b8f2592c2329c56cb5073d9c930dca4493eb3 100644 (file)
@@ -188,7 +188,6 @@ int pakfire_file_verify(struct pakfire_file* file, int* status);
 enum pakfire_file_check_issues {
        PAKFIRE_FILE_FHS_ERROR           = (1 << 0),
        PAKFIRE_FILE_MISSING_DEBUGINFO   = (1 << 1),
-       PAKFIRE_FILE_MISSING_SSP         = (1 << 2),
        PAKFIRE_FILE_EXECSTACK           = (1 << 4),
        PAKFIRE_FILE_NO_RELRO            = (1 << 5),
        PAKFIRE_FILE_HAS_RUNPATH         = (1 << 6),
index 879d93708437afd283ee35841a731839f6d401f8..64fa588ed09dec77f3117357c8f29c5705691ac0 100644 (file)
@@ -28,6 +28,7 @@
 #include <pakfire/file.h>
 #include <pakfire/linter.h>
 #include <pakfire/linter-file.h>
+#include <pakfire/string.h>
 
 struct pakfire_linter_file {
        struct pakfire_ctx* ctx;
@@ -239,6 +240,41 @@ static int pakfire_linter_file_get_elf_type(struct pakfire_linter_file* lfile) {
        return type;
 }
 
+static int pakfire_linter_file_get_elf_section(struct pakfire_linter_file* lfile,
+               Elf* elf, const Elf64_Word type, Elf_Scn** section, GElf_Shdr* header, Elf_Data** data) {
+       Elf_Scn* s = NULL;
+
+       GElf_Shdr shdr;
+
+       // Walk through all sections
+       for (;;) {
+               s = elf_nextscn(elf, s);
+               if (!s)
+                       break;
+
+               // Fetch the section header
+               gelf_getshdr(s, &shdr);
+
+               // Return any matching sections
+               if (shdr.sh_type == type) {
+                       *section = s;
+
+                       // Send header if requested
+                       if (header)
+                               gelf_getshdr(s, header);
+
+                       // Send data if requested
+                       if (data)
+                               *data = elf_getdata(s, NULL);
+
+                       return 0;
+               }
+       }
+
+       // No section found
+       return 1;
+}
+
 static int pakfire_linter_file_check_pie(struct pakfire_linter_file* lfile) {
        switch (pakfire_linter_file_get_elf_type(lfile)) {
                // Shared Object files are good
@@ -253,6 +289,81 @@ static int pakfire_linter_file_check_pie(struct pakfire_linter_file* lfile) {
        return pakfire_linter_error(lfile->linter, "%s is not PIE", lfile->path);
 }
 
+static int __pakfire_linter_file_check_ssp(
+               struct pakfire_linter_file* lfile, Elf* elf, void* data) {
+       Elf_Scn* symtab = NULL;
+       GElf_Shdr shdr;
+       Elf_Data* elf_data = NULL;
+       GElf_Sym symbol;
+       const char* name = NULL;
+       int r;
+
+       // Fetch the symbol table
+       r = pakfire_linter_file_get_elf_section(lfile, elf, SHT_SYMTAB, &symtab, &shdr, &elf_data);
+       if (r) {
+               ERROR(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(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;
+
+               // 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;
+       }
+
+       // The file does not seem to have SSP enabled
+       return pakfire_linter_error(lfile->linter,
+               "%s does not have Stack Smashing Protection", lfile->path);
+}
+
+static int pakfire_linter_file_check_ssp(struct pakfire_linter_file* lfile) {
+       // This check will be skipped for these files
+       static const char* whitelist[] = {
+               "/usr/lib64/libgcc_s.so.*",
+               "/usr/lib64/libmvec.so.*",
+               NULL,
+       };
+
+       // Do not perform this check for runtime linkers
+       if (pakfire_file_matches(lfile->file, "/usr/lib*/ld-*.so*"))
+               return 0;
+
+       // Check if this file is whitelisted
+       for (const char** path = whitelist; *path; path++) {
+               if (pakfire_file_matches(lfile->file, *path)) {
+                       DEBUG(lfile->ctx, "Skipping SSP check for whitelisted file %s\n", lfile->path);
+                       return 0;
+               }
+       }
+
+       return pakfire_linter_file_elf(lfile, __pakfire_linter_file_check_ssp, NULL);
+}
+
 int pakfire_linter_file_lint(struct pakfire_linter_file* lfile) {
        int r = 0;
 
@@ -262,6 +373,11 @@ int pakfire_linter_file_lint(struct pakfire_linter_file* lfile) {
                r = pakfire_linter_file_check_pie(lfile);
                if (r < 0)
                        return r;
+
+               // Check SSP
+               r = pakfire_linter_file_check_ssp(lfile);
+               if (r < 0)
+                       return r;
        }
 
        return 0;