]> git.ipfire.org Git - people/stevee/pakfire.git/commitdiff
build: Refactor hardening checks
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 7 Mar 2023 11:05:00 +0000 (11:05 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 9 Mar 2023 13:44:41 +0000 (13:44 +0000)
Instead of calling many different checks, this will now check once
and store any issues that have been identified.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/build.c
src/libpakfire/file.c
src/libpakfire/filelist.c
src/libpakfire/include/pakfire/file.h
src/libpakfire/include/pakfire/filelist.h
src/libpakfire/packager.c

index 42f30bac4f8008c9015694a50e759ff1842217d5..ece4b31364e1c44c58f378bbc55f61b312fe3402 100644 (file)
@@ -1023,7 +1023,7 @@ static int pakfire_build_post_process_files(struct pakfire_build* build,
                        INFO(build->pakfire, "%s\n", description);
 
                // Show all files which will be removed
-               pakfire_filelist_dump(removees, 0);
+               pakfire_filelist_dump(removees, PAKFIRE_FILE_DUMP_FULL|PAKFIRE_FILE_DUMP_HARDENING);
 
                // Remove all files on the removee list
                if (flags & PAKFIRE_BUILD_CLEANUP_FILES) {
@@ -1138,42 +1138,23 @@ static int pakfire_build_post_check_broken_symlinks(
        Hardening
 */
 
-static int __pakfire_build_post_check_stack_smashing_protection(
+static int __pakfire_build_post_check_hardening(
                struct pakfire* pakfire, struct pakfire_file* file, void* data) {
        struct pakfire_filelist* broken = (struct pakfire_filelist*)data;
+       int issues = 0;
        int r;
 
        // Skip anything that isn't an ELF file
        if (!pakfire_file_matches_class(file, PAKFIRE_FILE_ELF))
                return 0;
 
-       if (!pakfire_file_has_stack_smashing_protection(file)) {
-               r = pakfire_filelist_add(broken, file);
-               if (r)
-                       return r;
-       }
-
-       return 0;
-}
-
-static int pakfire_build_post_check_stack_smashing_protection(
-               struct pakfire_build* build, struct pakfire_filelist* filelist) {
-       return pakfire_build_post_process_files(build, filelist,
-               "Stack-smashing Protection is missing:",
-               __pakfire_build_post_check_stack_smashing_protection,
-               PAKFIRE_BUILD_ERROR_IF_NOT_EMPTY);
-}
-
-static int __pakfire_build_post_check_shared_object_type(
-               struct pakfire* pakfire, struct pakfire_file* file, void* data) {
-       struct pakfire_filelist* broken = (struct pakfire_filelist*)data;
-       int r;
-
-       // Skip anything that isn't an ELF file
-       if (!pakfire_file_matches_class(file, PAKFIRE_FILE_ELF))
-               return 0;
+       // Check hardening
+       r = pakfire_file_check_hardening(file, &issues);
+       if (r)
+               return r;
 
-       if (!pakfire_file_is_position_independent(file)) {
+       // If any issues have been found, consider this file to be on the list
+       if (issues) {
                r = pakfire_filelist_add(broken, file);
                if (r)
                        return r;
@@ -1182,29 +1163,14 @@ static int __pakfire_build_post_check_shared_object_type(
        return 0;
 }
 
-static int pakfire_build_post_check_shared_object_type(
-               struct pakfire_build* build, struct pakfire_filelist* filelist) {
-       return pakfire_build_post_process_files(build, filelist,
-               "These files have not been built with -fPIC:",
-               __pakfire_build_post_check_shared_object_type,
-               PAKFIRE_BUILD_ERROR_IF_NOT_EMPTY);
-}
-
 static int pakfire_build_post_check_hardening(
                struct pakfire_build* build, struct pakfire_filelist* filelist) {
-       int r;
-
-       // Stack-smashing Protector
-       r = pakfire_build_post_check_stack_smashing_protection(build, filelist);
-       if (r)
-               return r;
-
-       // Check shared object type
-       r = pakfire_build_post_check_shared_object_type(build, filelist);
-       if (r)
-               return r;
-
-       return 0;
+       return pakfire_build_post_process_files(
+               build,
+               filelist,
+               "Hardening Issues:",
+               __pakfire_build_post_check_hardening,
+               PAKFIRE_BUILD_ERROR_IF_NOT_EMPTY);
 }
 
 static int pakfire_build_run_post_build_checks(struct pakfire_build* build) {
@@ -1748,7 +1714,7 @@ ERROR:
 
 static int __pakfire_build_unpackaged_file(struct pakfire* pakfire,
                struct pakfire_file* file, void* p) {
-       char* s = pakfire_file_dump(file);
+       char* s = pakfire_file_dump(file, PAKFIRE_FILE_DUMP_FULL);
        if (s) {
                ERROR(pakfire, "%s\n", s);
                free(s);
index 8a91a3859837e75959bd9d33062a1cbf851a6257..e1922dcb67e6e9f37312f2644d55cc69158e05aa 100644 (file)
@@ -85,6 +85,10 @@ struct pakfire_file {
        // Verification Status
        int verify_status;
 
+       // Hardening Issues
+       int hardening_issues;
+       int hardening_check_done:1;
+
        #warning TODO capabilities, config, data
        // capabilities
        //int is_configfile;
@@ -492,41 +496,93 @@ static int __pakfire_file_strmode(struct pakfire_file* file, char* s, const size
        return 0;
 }
 
-char* pakfire_file_dump(struct pakfire_file* file) {
-       char* buffer = NULL;
+char* pakfire_file_dump(struct pakfire_file* file, int flags) {
+       char* buffer = "";
        int r;
 
        char mode[12];
        char time[32];
 
        // Format mode
-       r = pakfire_file_strmode(file, mode);
-       if (r)
-               return NULL;
+       if (flags & PAKFIRE_FILE_DUMP_MODE) {
+               r = pakfire_file_strmode(file, mode);
+               if (r)
+                       goto ERROR;
+
+               r = asprintf(&buffer, "%s %s", buffer, mode);
+               if (r < 0)
+                       goto ERROR;
+       }
+
+       // Format ownership
+       if (flags & PAKFIRE_FILE_DUMP_OWNERSHIP) {
+               r = asprintf(&buffer, "%s %s/%s", buffer, file->uname, file->gname);
+               if (r < 0)
+                       goto ERROR;
+       }
+
+       // Format size
+       if (flags & PAKFIRE_FILE_DUMP_SIZE) {
+               r = asprintf(&buffer, "%s %8zu", buffer, file->st.st_size);
+               if (r < 0)
+                       goto ERROR;
+       }
 
        // Format time
-       r = pakfire_strftime(time, "%Y-%m-%d %H:%M", file->st.st_ctime);
-       if (r)
-               return NULL;
+       if (flags & PAKFIRE_FILE_DUMP_TIME) {
+               r = pakfire_strftime(time, "%Y-%m-%d %H:%M", file->st.st_ctime);
+               if (r)
+                       goto ERROR;
+
+               r = asprintf(&buffer, "%s %s", buffer, time);
+               if (r < 0)
+                       goto ERROR;
+       }
 
-       // Put everything together
-       r = asprintf(&buffer, "%s %s/%s %8zu %s %s",
-               mode, file->uname, file->gname, file->st.st_size, time, file->path);
+       // Format path
+       r = asprintf(&buffer, "%s %s", buffer, file->path);
        if (r < 0)
-               return NULL;
+               goto ERROR;
 
        // Append symlink target
-       switch (pakfire_file_get_type(file)) {
-               case S_IFLNK:
-                       r = asprintf(&buffer, "%s -> %s", buffer, file->symlink);
-                       if (r < 0)
-                               return NULL;
+       if (flags & PAKFIRE_FILE_DUMP_LINK_TARGETS) {
+               switch (pakfire_file_get_type(file)) {
+                       case S_IFLNK:
+                               r = asprintf(&buffer, "%s -> %s", buffer, file->symlink);
+                               if (r < 0)
+                                       return NULL;
 
-               default:
-                       break;
+                       default:
+                               break;
+               }
+       }
+
+       // Hardning Status
+       if (flags & PAKFIRE_FILE_DUMP_HARDENING) {
+               if (pakfire_file_matches_class(file, PAKFIRE_FILE_ELF)) {
+                       // Stack-smashing Protection
+                       if (file->hardening_issues & PAKFIRE_FILE_NO_SSP) {
+                               r = asprintf(&buffer, "%s [NO-SSP]", buffer);
+                               if (r < 0)
+                                       goto ERROR;
+                       }
+
+                       // Position-independent Executable
+                       if (file->hardening_issues & PAKFIRE_FILE_NO_PIE) {
+                               r = asprintf(&buffer, "%s [NO-PIE]", buffer);
+                               if (r < 0)
+                                       goto ERROR;
+                       }
+               }
        }
 
        return buffer;
+
+ERROR:
+       if (buffer)
+               free(buffer);
+
+       return NULL;
 }
 
 PAKFIRE_EXPORT int pakfire_file_cmp(struct pakfire_file* file1, struct pakfire_file* file2) {
@@ -1443,7 +1499,7 @@ ERROR:
        return r;
 }
 
-static int __pakfire_file_has_stack_smashing_protection(
+static int __pakfire_file_hardening_check_ssp(
                struct pakfire_file* file, Elf* elf, void* data) {
        Elf_Scn* section = NULL;
        GElf_Shdr section_header;
@@ -1455,7 +1511,7 @@ static int __pakfire_file_has_stack_smashing_protection(
        for (;;) {
                section = elf_nextscn(elf, section);
                if (!section)
-                       return 0;
+                       return 1;
 
                // Fetch the section header
                gelf_getshdr(section, &section_header);
@@ -1479,40 +1535,72 @@ static int __pakfire_file_has_stack_smashing_protection(
                if (!name || !*name)
                        continue;
 
-               // Check if there is a symbol called "__stack_chk_fail"
+               // Exit if there is a symbol called "__stack_chk_fail"
                if (pakfire_string_startswith(name, "__stack_chk_fail"))
-                       return 1;
+                       return 0;
        }
 
+       // The file does not seem to have SSP enabled
+       file->hardening_issues |= PAKFIRE_FILE_NO_SSP;
+
        return 0;
 }
 
-int pakfire_file_has_stack_smashing_protection(struct pakfire_file* file) {
-       return pakfire_file_open_elf(file, __pakfire_file_has_stack_smashing_protection, NULL);
+static int pakfire_file_hardening_check_ssp(struct pakfire_file* file) {
+       return pakfire_file_open_elf(file, __pakfire_file_hardening_check_ssp, NULL);
 }
 
-static int __pakfire_file_is_position_independent(
+static int __pakfire_file_hardening_check_pie(
                struct pakfire_file* file, Elf* elf, void* data) {
        GElf_Ehdr eheader;
 
        // Fetch the ELF header
        if (!gelf_getehdr(elf, &eheader)) {
                ERROR(file->pakfire, "Could not parse ELF header: %s\n", elf_errmsg(-1));
-               return -1;
+               return 1;
        }
 
        // Check for the correct header type
        switch (eheader.e_type) {
+               // Dynamic Objects are good
                case ET_DYN:
-                       return 1;
+                       break;
 
+               // Anything else is bad
                default:
+                       file->hardening_issues |= PAKFIRE_FILE_NO_PIE;
                        break;
        }
 
        return 0;
 }
 
-int pakfire_file_is_position_independent(struct pakfire_file* file) {
-       return pakfire_file_open_elf(file, __pakfire_file_is_position_independent, NULL);
+static int pakfire_file_hardening_check_pie(struct pakfire_file* file) {
+       return pakfire_file_open_elf(file, __pakfire_file_hardening_check_pie, NULL);
+}
+
+int pakfire_file_check_hardening(struct pakfire_file* file, int* issues) {
+       int r;
+
+       // Return previous result if this has been run before
+       if (!file->hardening_check_done) {
+               // Check for SSP
+               r = pakfire_file_hardening_check_ssp(file);
+               if (r)
+                       return r;
+
+               // Check for PIE
+               r = pakfire_file_hardening_check_pie(file);
+               if (r)
+                       return r;
+
+               // All checks done
+               file->hardening_check_done = 1;
+       }
+
+       // Return any issues
+       if (issues)
+               *issues = file->hardening_issues;
+
+       return 0;
 }
index 2525f58fe2697ce7be4d2539d1af0f3b327b2dba..0c3ddad630b5ab34f20266cdd312ebc839f76510 100644 (file)
@@ -423,30 +423,20 @@ int pakfire_filelist_walk(struct pakfire_filelist* list,
 }
 
 static int __pakfire_filelist_dump(
-               struct pakfire* pakfire, struct pakfire_file* file, void* p) {
-       const int debug = *(int*)p;
+               struct pakfire* pakfire, struct pakfire_file* file, void* data) {
+       int* flags = (int*)data;
 
-       char* s = pakfire_file_dump(file);
+       char* s = pakfire_file_dump(file, *flags);
        if (s) {
-               if (debug)
-                       DEBUG(pakfire, "%s\n", s);
-               else
-                       INFO(pakfire, "%s\n", s);
-
+               INFO(pakfire, "%s\n", s);
                free(s);
        }
 
        return 0;
 }
 
-int pakfire_filelist_dump(struct pakfire_filelist* list, int debug) {
-#ifndef ENABLE_DEBUG
-       // Avoid walking through the entire filelist in non-debug mode
-       if (debug)
-               return 0;
-#endif
-
-       return pakfire_filelist_walk(list, __pakfire_filelist_dump, &debug);
+int pakfire_filelist_dump(struct pakfire_filelist* list, int flags) {
+       return pakfire_filelist_walk(list, __pakfire_filelist_dump, &flags);
 }
 
 /*
index ae10cd2cbe8fcb5bc59ed70b27c88e0ed51ab05b..206d3d46e0f48fbf672344e7ba9cf41890f019d5 100644 (file)
@@ -35,8 +35,6 @@ int pakfire_file_create(struct pakfire_file** file, struct pakfire* pakfire);
 struct pakfire_file* pakfire_file_ref(struct pakfire_file* file);
 struct pakfire_file* pakfire_file_unref(struct pakfire_file* file);
 
-char* pakfire_file_dump(struct pakfire_file* file);
-
 int pakfire_file_cmp(struct pakfire_file* file1, struct pakfire_file* file2);
 
 const char* pakfire_file_get_path(struct pakfire_file* file);
@@ -118,6 +116,24 @@ int pakfire_file_create_from_archive_entry(struct pakfire_file** file, struct pa
        struct archive_entry* entry);
 struct archive_entry* pakfire_file_archive_entry(struct pakfire_file* file, int digest_types);
 
+enum pakfire_file_dump_flags {
+       PAKFIRE_FILE_DUMP_MODE         = (1 << 0),
+       PAKFIRE_FILE_DUMP_SIZE         = (1 << 1),
+       PAKFIRE_FILE_DUMP_TIME         = (1 << 2),
+       PAKFIRE_FILE_DUMP_OWNERSHIP    = (1 << 3),
+       PAKFIRE_FILE_DUMP_LINK_TARGETS = (1 << 4),
+       PAKFIRE_FILE_DUMP_HARDENING    = (1 << 5),
+
+       PAKFIRE_FILE_DUMP_FULL = \
+               PAKFIRE_FILE_DUMP_MODE | \
+               PAKFIRE_FILE_DUMP_SIZE | \
+               PAKFIRE_FILE_DUMP_TIME | \
+               PAKFIRE_FILE_DUMP_OWNERSHIP | \
+               PAKFIRE_FILE_DUMP_LINK_TARGETS,
+};
+
+char* pakfire_file_dump(struct pakfire_file* file, int flags);
+
 const char* pakfire_file_get_abspath(struct pakfire_file* file);
 int pakfire_file_set_abspath(struct pakfire_file* file, const char* path);
 
@@ -138,7 +154,12 @@ int pakfire_file_verify(struct pakfire_file* file, int* status);
 /*
        Hardening Checks
 */
-int pakfire_file_has_stack_smashing_protection(struct pakfire_file* file);
+enum pakfire_file_hardening_flags {
+       PAKFIRE_FILE_NO_SSP          = (1 << 0),
+       PAKFIRE_FILE_NO_PIE          = (1 << 1),
+};
+
+int pakfire_file_check_hardening(struct pakfire_file* file, int* issues);
 
 #endif
 
index f347dd6baaec1198495c830ea295f40e9fc5ea69..0a129fb23ea60509bfe5e930f4ed7298359684f1 100644 (file)
@@ -57,7 +57,7 @@ typedef int (*pakfire_filelist_walk_callback)
 
 int pakfire_filelist_walk(struct pakfire_filelist* list,
        pakfire_filelist_walk_callback callback, void* data);
-int pakfire_filelist_dump(struct pakfire_filelist* list, int debug);
+int pakfire_filelist_dump(struct pakfire_filelist* list, int flags);
 
 int pakfire_filelist_verify(struct pakfire_filelist* list, struct pakfire_filelist* errors);
 
index 8e6ddc1942b92128ab57991bbd7cf2e7d6bf153e..5bacd0259322c863ef29b706fb2cbf874dec0bc9 100644 (file)
@@ -385,15 +385,6 @@ int pakfire_packager_finish(struct pakfire_packager* packager, FILE* f) {
                        goto ERROR;
        }
 
-#ifdef ENABLE_DEBUG
-       DEBUG(packager->pakfire, "Filelist:\n");
-
-       // Dump filelist
-       r = pakfire_filelist_dump(packager->filelist, 1);
-       if (r)
-               goto ERROR;
-#endif
-
        // Add filelist
        r = pakfire_package_set_filelist(packager->pkg, packager->filelist);
        if (r)