From dae43e1fa4d1057334c84ff7e65d88ac37484b4f Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Tue, 7 Mar 2023 11:40:42 +0000 Subject: [PATCH] file: Check if ELF files have an executable stack Signed-off-by: Michael Tremer --- src/libpakfire/file.c | 56 +++++++++++++++++++++++++++ src/libpakfire/include/pakfire/file.h | 1 + src/scripts/check-hardening | 16 -------- 3 files changed, 57 insertions(+), 16 deletions(-) diff --git a/src/libpakfire/file.c b/src/libpakfire/file.c index e1922dcb..0d3ddb6b 100644 --- a/src/libpakfire/file.c +++ b/src/libpakfire/file.c @@ -1579,6 +1579,57 @@ static int pakfire_file_hardening_check_pie(struct pakfire_file* file) { return pakfire_file_open_elf(file, __pakfire_file_hardening_check_pie, NULL); } +static int __pakfire_file_hardening_check_execstack( + struct pakfire_file* file, Elf* elf, void* data) { + GElf_Phdr phdr; + int r; + + size_t phnum = 0; + + // Fetch the total numbers of program headers + r = elf_getphdrnum(elf, &phnum); + if (r) { + ERROR(file->pakfire, "Could not fetch number of program headers: %s\n", + elf_errmsg(-1)); + return 1; + } + + // Walk through all program headers + for (unsigned int i = 0; i < phnum; i++) { + if (!gelf_getphdr(elf, i, &phdr)) { + ERROR(file->pakfire, "Could not parse program header: %s\n", elf_errmsg(-1)); + return 1; + } + + switch (phdr.p_type) { + case PT_GNU_STACK: + DEBUG(file->pakfire, + "%s: GNU_STACK flags: %c%c%c\n", + file->path, + (phdr.p_flags & PF_R) ? 'R' : '-', + (phdr.p_flags & PF_W) ? 'W' : '-', + (phdr.p_flags & PF_X) ? 'X' : '-' + ); + + // The stack cannot be writable and executable + if ((phdr.p_flags & PF_W) && (phdr.p_flags & PF_X)) + file->hardening_issues |= PAKFIRE_FILE_EXECSTACK; + + // Done + return 0; + + default: + break; + } + } + + return 0; +} + +static int pakfire_file_hardening_check_execstack(struct pakfire_file* file) { + return pakfire_file_open_elf(file, __pakfire_file_hardening_check_execstack, NULL); +} + int pakfire_file_check_hardening(struct pakfire_file* file, int* issues) { int r; @@ -1594,6 +1645,11 @@ int pakfire_file_check_hardening(struct pakfire_file* file, int* issues) { if (r) return r; + // Check for executable stacks + r = pakfire_file_hardening_check_execstack(file); + if (r) + return r; + // All checks done file->hardening_check_done = 1; } diff --git a/src/libpakfire/include/pakfire/file.h b/src/libpakfire/include/pakfire/file.h index 206d3d46..9b8a2940 100644 --- a/src/libpakfire/include/pakfire/file.h +++ b/src/libpakfire/include/pakfire/file.h @@ -157,6 +157,7 @@ int pakfire_file_verify(struct pakfire_file* file, int* status); enum pakfire_file_hardening_flags { PAKFIRE_FILE_NO_SSP = (1 << 0), PAKFIRE_FILE_NO_PIE = (1 << 1), + PAKFIRE_FILE_EXECSTACK = (1 << 2), }; int pakfire_file_check_hardening(struct pakfire_file* file, int* issues); diff --git a/src/scripts/check-hardening b/src/scripts/check-hardening index 2db5aa7e..b37d62c2 100644 --- a/src/scripts/check-hardening +++ b/src/scripts/check-hardening @@ -33,7 +33,6 @@ main() { return 1 fi - local exec_stack=() local not_relro=() local partly_relro=() @@ -56,11 +55,6 @@ main() { continue fi - # Does this file have an executable stack? - if readelf -l "${file}" 2>/dev/null | grep -A1 "GNU_STACK" | grep -q "RWE"; then - exec_stack+=( "${file}" ) - fi - # Perform more checks for shared objects (i.e. libraries) if file "${file}" | grep -q "shared object"; then # Is this file partly RELRO? @@ -78,16 +72,6 @@ main() { local r=0 - # Log files with an executable stack - if [ "${#exec_stack[@]}" -gt 0 ]; then - error "The following files have an executable stack:" - for file in ${exec_stack[@]}; do - error " ${file/${buildroot}/}" - done - - r=1 - fi - # Log files which are not RELRO if [ "${#not_relro[@]}" -gt 0 ]; then error "The following files are not fully RELRO:" -- 2.47.3