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) {
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);
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);
+}
return 1
fi
- local missing_ssp=()
local no_pie=()
local exec_stack=()
local not_relro=()
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}" )
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:"