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) {
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;
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) {
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);
// Verification Status
int verify_status;
+ // Hardening Issues
+ int hardening_issues;
+ int hardening_check_done:1;
+
#warning TODO capabilities, config, data
// capabilities
//int is_configfile;
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) {
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;
for (;;) {
section = elf_nextscn(elf, section);
if (!section)
- return 0;
+ return 1;
// Fetch the section header
gelf_getshdr(section, §ion_header);
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;
}
}
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);
}
/*
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);
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);
/*
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
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);
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)