goto ERROR;
}
- // Stack-smashing Protection
- if (file->issues & PAKFIRE_FILE_MISSING_SSP) {
- r = asprintf(&buffer, "%s [MISSING-SSP]", buffer);
- if (r < 0)
- goto ERROR;
- }
-
// Executable Stack
if (file->issues & PAKFIRE_FILE_EXECSTACK) {
r = asprintf(&buffer, "%s [EXECSTACK]", buffer);
return pakfire_file_open_elf(file, __pakfire_file_check_debuginfo, NULL);
}
-static int __pakfire_file_check_ssp(
- struct pakfire_file* file, Elf* elf, void* data) {
- Elf_Scn* symtab = NULL;
- GElf_Shdr shdr;
- Elf_Data* elf_data = NULL;
- GElf_Sym symbol;
- const char* name = NULL;
- int r;
-
- // Fetch the symbol table
- r = pakfire_file_get_elf_section(file, elf, SHT_SYMTAB, &symtab, &shdr, &elf_data);
- if (r) {
- ERROR(file->ctx, "%s has no symbol table\n", pakfire_file_get_path(file));
- return 1;
- }
-
- // Count any global functions
- size_t counter = 0;
-
- // Walk through all symbols
- for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) {
- gelf_getsym(elf_data, i, &symbol);
-
- // Fetch the symbol name
- name = elf_strptr(elf, shdr.sh_link, symbol.st_name);
-
- // Skip empty section names
- if (!name || !*name)
- continue;
-
- // Exit if there is a symbol called "__stack_chk_fail"
- if (pakfire_string_startswith(name, "__stack_chk_fail"))
- return 0;
-
- // Count any global functions
- if ((ELF64_ST_BIND(symbol.st_info) == STB_GLOBAL) &&
- (ELF64_ST_TYPE(symbol.st_info) == STT_FUNC))
- counter++;
- }
-
- // We do not perform the check for libraries that do not contain any functions.
- // Some packages use shared libraries to provide data.
- if (!counter) {
- DEBUG(file->ctx, "%s: File has no functions. Skipping SSP check.\n",
- pakfire_file_get_path(file));
- return 0;
- }
-
- // The file does not seem to have SSP enabled
- file->issues |= PAKFIRE_FILE_MISSING_SSP;
-
- return 0;
-}
-
-static int pakfire_file_check_ssp(struct pakfire_file* file) {
- // This check will be skipped for these files
- static const char* whitelist[] = {
- "/usr/lib64/libgcc_s.so.*",
- "/usr/lib64/libmvec.so.*",
- NULL,
- };
-
- // Do not perform this check for runtime linkers
- if (pakfire_file_matches_class(file, PAKFIRE_FILE_RUNTIME_LINKER))
- return 0;
-
- // We cannot perform this check if we don't have debuginfo
- if (file->issues & PAKFIRE_FILE_MISSING_DEBUGINFO)
- return 0;
-
- // Check if this file is whitelisted
- for (const char** path = whitelist; *path; path++) {
- if (pakfire_file_matches(file, *path)) {
- DEBUG(file->ctx, "Skipping SSP check for whitelisted file %s\n",
- pakfire_file_get_path(file));
- return 0;
- }
- }
-
- return pakfire_file_open_elf(file, __pakfire_file_check_ssp, NULL);
-}
-
static int __pakfire_file_check_execstack(
struct pakfire_file* file, Elf* elf, void* data) {
GElf_Phdr phdr;
if (r)
return r;
- // Check for SSP
- r = pakfire_file_check_ssp(file);
- if (r)
- return r;
-
// Check for executable stacks
r = pakfire_file_check_execstack(file);
if (r)
#include <pakfire/file.h>
#include <pakfire/linter.h>
#include <pakfire/linter-file.h>
+#include <pakfire/string.h>
struct pakfire_linter_file {
struct pakfire_ctx* ctx;
return type;
}
+static int pakfire_linter_file_get_elf_section(struct pakfire_linter_file* lfile,
+ Elf* elf, const Elf64_Word type, Elf_Scn** section, GElf_Shdr* header, Elf_Data** data) {
+ Elf_Scn* s = NULL;
+
+ GElf_Shdr shdr;
+
+ // Walk through all sections
+ for (;;) {
+ s = elf_nextscn(elf, s);
+ if (!s)
+ break;
+
+ // Fetch the section header
+ gelf_getshdr(s, &shdr);
+
+ // Return any matching sections
+ if (shdr.sh_type == type) {
+ *section = s;
+
+ // Send header if requested
+ if (header)
+ gelf_getshdr(s, header);
+
+ // Send data if requested
+ if (data)
+ *data = elf_getdata(s, NULL);
+
+ return 0;
+ }
+ }
+
+ // No section found
+ return 1;
+}
+
static int pakfire_linter_file_check_pie(struct pakfire_linter_file* lfile) {
switch (pakfire_linter_file_get_elf_type(lfile)) {
// Shared Object files are good
return pakfire_linter_error(lfile->linter, "%s is not PIE", lfile->path);
}
+static int __pakfire_linter_file_check_ssp(
+ struct pakfire_linter_file* lfile, Elf* elf, void* data) {
+ Elf_Scn* symtab = NULL;
+ GElf_Shdr shdr;
+ Elf_Data* elf_data = NULL;
+ GElf_Sym symbol;
+ const char* name = NULL;
+ int r;
+
+ // Fetch the symbol table
+ r = pakfire_linter_file_get_elf_section(lfile, elf, SHT_SYMTAB, &symtab, &shdr, &elf_data);
+ if (r) {
+ ERROR(lfile->ctx, "%s has no symbol table\n", lfile->path);
+ return 1;
+ }
+
+ // Count any global functions
+ size_t counter = 0;
+
+ // Walk through all symbols
+ for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) {
+ gelf_getsym(elf_data, i, &symbol);
+
+ // Fetch the symbol name
+ name = elf_strptr(elf, shdr.sh_link, symbol.st_name);
+
+ // Skip empty section names
+ if (!name || !*name)
+ continue;
+
+ // Exit if there is a symbol called "__stack_chk_fail"
+ if (pakfire_string_startswith(name, "__stack_chk_fail"))
+ return 0;
+
+ // Count any global functions
+ if ((ELF64_ST_BIND(symbol.st_info) == STB_GLOBAL) &&
+ (ELF64_ST_TYPE(symbol.st_info) == STT_FUNC))
+ counter++;
+ }
+
+ // We do not perform the check for libraries that do not contain any functions.
+ // Some packages use shared libraries to provide data.
+ if (!counter) {
+ DEBUG(lfile->ctx, "%s: File has no functions. Skipping SSP check.\n", lfile->path);
+ return 0;
+ }
+
+ // The file does not seem to have SSP enabled
+ return pakfire_linter_error(lfile->linter,
+ "%s does not have Stack Smashing Protection", lfile->path);
+}
+
+static int pakfire_linter_file_check_ssp(struct pakfire_linter_file* lfile) {
+ // This check will be skipped for these files
+ static const char* whitelist[] = {
+ "/usr/lib64/libgcc_s.so.*",
+ "/usr/lib64/libmvec.so.*",
+ NULL,
+ };
+
+ // Do not perform this check for runtime linkers
+ if (pakfire_file_matches(lfile->file, "/usr/lib*/ld-*.so*"))
+ return 0;
+
+ // Check if this file is whitelisted
+ for (const char** path = whitelist; *path; path++) {
+ if (pakfire_file_matches(lfile->file, *path)) {
+ DEBUG(lfile->ctx, "Skipping SSP check for whitelisted file %s\n", lfile->path);
+ return 0;
+ }
+ }
+
+ return pakfire_linter_file_elf(lfile, __pakfire_linter_file_check_ssp, NULL);
+}
+
int pakfire_linter_file_lint(struct pakfire_linter_file* lfile) {
int r = 0;
r = pakfire_linter_file_check_pie(lfile);
if (r < 0)
return r;
+
+ // Check SSP
+ r = pakfire_linter_file_check_ssp(lfile);
+ if (r < 0)
+ return r;
}
return 0;