From: Michael Tremer Date: Tue, 7 Mar 2023 11:05:00 +0000 (+0000) Subject: build: Refactor hardening checks X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f7f4492159492c9bfcc1334e338201564ade5c00;p=people%2Fstevee%2Fpakfire.git build: Refactor hardening checks Instead of calling many different checks, this will now check once and store any issues that have been identified. Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/build.c b/src/libpakfire/build.c index 42f30bac..ece4b313 100644 --- a/src/libpakfire/build.c +++ b/src/libpakfire/build.c @@ -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); diff --git a/src/libpakfire/file.c b/src/libpakfire/file.c index 8a91a385..e1922dcb 100644 --- a/src/libpakfire/file.c +++ b/src/libpakfire/file.c @@ -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, §ion_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; } diff --git a/src/libpakfire/filelist.c b/src/libpakfire/filelist.c index 2525f58f..0c3ddad6 100644 --- a/src/libpakfire/filelist.c +++ b/src/libpakfire/filelist.c @@ -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); } /* diff --git a/src/libpakfire/include/pakfire/file.h b/src/libpakfire/include/pakfire/file.h index ae10cd2c..206d3d46 100644 --- a/src/libpakfire/include/pakfire/file.h +++ b/src/libpakfire/include/pakfire/file.h @@ -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 diff --git a/src/libpakfire/include/pakfire/filelist.h b/src/libpakfire/include/pakfire/filelist.h index f347dd6b..0a129fb2 100644 --- a/src/libpakfire/include/pakfire/filelist.h +++ b/src/libpakfire/include/pakfire/filelist.h @@ -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); diff --git a/src/libpakfire/packager.c b/src/libpakfire/packager.c index 8e6ddc19..5bacd025 100644 --- a/src/libpakfire/packager.c +++ b/src/libpakfire/packager.c @@ -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)