From: Michael Tremer Date: Sun, 5 Mar 2023 15:48:20 +0000 (+0000) Subject: build: Move SSP check into the build process X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2dcb43e7573bd8d6cd3f93b8c7c5b65167f05e35;p=people%2Fstevee%2Fpakfire.git build: Move SSP check into the build process Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/build.c b/src/libpakfire/build.c index 7b05b7b6..5a971817 100644 --- a/src/libpakfire/build.c +++ b/src/libpakfire/build.c @@ -1134,6 +1134,42 @@ static int pakfire_build_post_check_broken_symlinks( PAKFIRE_BUILD_ERROR_IF_NOT_EMPTY); } +static int __pakfire_build_post_check_stack_smashing_protection( + 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; + + 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_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; + + return 0; } static int pakfire_build_run_post_build_checks(struct pakfire_build* build) { @@ -1174,6 +1210,11 @@ static int pakfire_build_run_post_build_checks(struct pakfire_build* build) { if (r) goto ERROR; + // Check hardening + r = pakfire_build_post_check_hardening(build, filelist); + if (r) + goto ERROR; + ERROR: if (filelist) pakfire_filelist_unref(filelist); diff --git a/src/libpakfire/file.c b/src/libpakfire/file.c index d1cedb90..a0ed895d 100644 --- a/src/libpakfire/file.c +++ b/src/libpakfire/file.c @@ -1383,3 +1383,110 @@ PAKFIRE_EXPORT int pakfire_file_matches(struct pakfire_file* file, const char* p return -1; } } + +/* + ELF Stuff +*/ + +static int pakfire_file_open_elf(struct pakfire_file* file, + int (*callback)(struct pakfire_file* file, Elf* elf, void* data), void* data) { + FILE* f = NULL; + Elf* elf = NULL; + int r; + + // Don't run this for non-ELF files + if (!pakfire_file_matches_class(file, PAKFIRE_FILE_ELF)) { + errno = EINVAL; + return 1; + } + + // Setup libelf + r = setup_libelf(file->pakfire); + if (r) + return r; + + // Open the file + f = fopen(file->abspath, "r"); + if (!f) { + ERROR(file->pakfire, "Could not open %s: %m\n", file->abspath); + return 1; + } + + // Parse the ELF header + elf = elf_begin(fileno(f), ELF_C_READ, NULL); + if (!elf) { + ERROR(file->pakfire, "Could not open ELF file: %s\n", elf_errmsg(-1)); + r = 1; + goto ERROR; + } + + // Check if this is an ELF file + switch (elf_kind(elf)) { + case ELF_K_ELF: + break; + + default: + ERROR(file->pakfire, "%s is not an ELF object\n", file->path); + r = 1; + goto ERROR; + } + + // Call the callback + r = callback(file, elf, data); + +ERROR: + if (elf) + elf_end(elf); + if (f) + fclose(f); + + return r; +} + +static int __pakfire_file_has_stack_smashing_protection( + struct pakfire_file* file, Elf* elf, void* data) { + Elf_Scn* section = NULL; + GElf_Shdr section_header; + Elf_Data* elf_data = NULL; + GElf_Sym symbol; + const char* name = NULL; + + // Walk through all sections + for (;;) { + section = elf_nextscn(elf, section); + if (!section) + return 0; + + // Fetch the section header + gelf_getshdr(section, §ion_header); + + // Break if we found the symbol table + if (section_header.sh_type == SHT_SYMTAB) + break; + } + + // Fetch a pointer to the section data + elf_data = elf_getdata(section, NULL); + + // Walk through all symbols + for (unsigned int i = 0; i < section_header.sh_size / section_header.sh_entsize; i++) { + gelf_getsym(elf_data, i, &symbol); + + // Fetch the symbol name + name = elf_strptr(elf, section_header.sh_link, symbol.st_name); + + // Skip empty section names + if (!name || !*name) + continue; + + // Check if there is a symbol called "__stack_chk_fail" + if (pakfire_string_startswith(name, "__stack_chk_fail")) + return 1; + } + + 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); +} diff --git a/src/libpakfire/include/pakfire/file.h b/src/libpakfire/include/pakfire/file.h index dc26fa84..ae10cd2c 100644 --- a/src/libpakfire/include/pakfire/file.h +++ b/src/libpakfire/include/pakfire/file.h @@ -135,6 +135,11 @@ int pakfire_file_matches_class(struct pakfire_file* file, const int class); int pakfire_file_verify(struct pakfire_file* file, int* status); +/* + Hardening Checks +*/ +int pakfire_file_has_stack_smashing_protection(struct pakfire_file* file); + #endif #endif /* PAKFIRE_FILE_H */ diff --git a/src/scripts/check-hardening b/src/scripts/check-hardening index 50bb6c31..fe392ea8 100644 --- a/src/scripts/check-hardening +++ b/src/scripts/check-hardening @@ -33,7 +33,6 @@ main() { return 1 fi - local missing_ssp=() local no_pie=() local exec_stack=() local not_relro=() @@ -58,11 +57,6 @@ main() { continue fi - # Does this file have stack smashing protection enabled? - if ! readelf -s "${file}" 2>/dev/null | grep -q "__stack_chk_fail"; then - missing_ssp+=( "${file}" ) - fi - # Is this file built with -fPIC? if readelf -h "${file}" 2>/dev/null | grep -qE "Type:[[:space:]]*EXEC"; then no_pie+=( "${file}" ) @@ -90,16 +84,6 @@ main() { local r=0 - # Log files without SSP - if [ "${#missing_ssp[@]}" -gt 0 ]; then - error "The following files do not have stack-smashing protection enabled:" - for file in ${missing_ssp[@]}; do - error " ${file/${buildroot}/}" - done - - r=1 - fi - # Log files without PIE if [ "${#no_pie[@]}" -gt 0 ]; then error "The following files have not been compiled as place-independent executables:"