From: Michael Tremer Date: Fri, 25 Oct 2024 14:19:47 +0000 (+0000) Subject: linter: Try to lint some ELF stuff X-Git-Tag: 0.9.30~883 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a7e67d9651bfeee28030b04f4a4b2501b8945b02;p=pakfire.git linter: Try to lint some ELF stuff Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/linter.c b/src/libpakfire/linter.c index ae796e027..fd8e193b1 100644 --- a/src/libpakfire/linter.c +++ b/src/libpakfire/linter.c @@ -28,6 +28,9 @@ #include #include +// libelf +#include + #include #include #include @@ -220,6 +223,154 @@ void pakfire_linter_set_result_callback(struct pakfire_linter* linter, linter->result_data = data; } +/* + ELF Stuff +*/ + +static int pakfire_linter_init_libelf(struct pakfire_linter* linter) { + // Initialize libelf + if (elf_version(EV_CURRENT) == EV_NONE) { + CTX_ERROR(linter->ctx, "Could not initialize libelf: %s\n", elf_errmsg(-1)); + return -EINVAL; + } + + return 0; +} + +static int pakfire_linter_file_is_elf( + struct pakfire_linter* linter, struct pakfire_file* file) { + Elf* elf = NULL; + int r; + + // Fetch the file descriptor + int fd = pakfire_file_get_fd(file); + + // Initialize libelf + r = pakfire_linter_init_libelf(linter); + if (r < 0) + return r; + + // Parse the ELF header + elf = elf_begin(fd, ELF_C_READ, NULL); + if (!elf) { + CTX_ERROR(linter->ctx, "Could not open ELF file: %s\n", elf_errmsg(-1)); + r = -EINVAL; + goto ERROR; + } + + switch (elf_kind(elf)) { + case ELF_K_ELF: + r = 1; + break; + + // Ignore everything else + default: + r = 0; + break; + } + +ERROR: + if (elf) + elf_end(elf); + + return r; +} + +/* + A helper function that opens an ELF file and calls a callback. +*/ +static int pakfire_linter_elf(struct pakfire_linter* linter, struct pakfire_file* file, + int (*callback)(struct pakfire_linter* linter, struct pakfire_file* file, Elf* elf, void* data), + void* data) { + Elf* elf = NULL; + int fd = -EBADF; + int r; + + // Initialize libelf + r = pakfire_linter_init_libelf(linter); + if (r < 0) + return r; + + // Fetch file descriptor + fd = pakfire_file_get_fd(file); + if (fd < 0) + return fd; + + // Parse the ELF header + elf = elf_begin(fd, ELF_C_READ, NULL); + if (!elf) { + CTX_ERROR(linter->ctx, "Could not open ELF file: %s\n", elf_errmsg(-1)); + r = -EINVAL; + goto ERROR; + } + + // Check if this is an ELF file + switch (elf_kind(elf)) { + case ELF_K_ELF: + break; + + default: + CTX_ERROR(linter->ctx, "%s is not an ELF object\n", pakfire_file_get_path(file)); + r = -EINVAL; + goto ERROR; + } + + // Call the callback + r = callback(linter, file, elf, data); + +ERROR: + if (elf) + elf_end(elf); + + return r; +} + +static int __pakfire_linter_get_elf_type(struct pakfire_linter* linter, + struct pakfire_file* file, Elf* elf, void* data) { + GElf_Ehdr ehdr = {}; + + int* type = data; + + // Fetch the ELF header + if (!gelf_getehdr(elf, &ehdr)) { + CTX_ERROR(linter->ctx, "Could not parse ELF header: %s\n", elf_errmsg(-1)); + return -EINVAL; + } + + // Store the type + *type = ehdr.e_type; + + return 0; +} + +static int pakfire_linter_get_elf_type( + struct pakfire_linter* linter, struct pakfire_file* file) { + int type = ET_NONE; + int r; + + // Fetch the type + r = pakfire_linter_elf(linter, file, __pakfire_linter_get_elf_type, &type); + if (r < 0) + return r; + + return type; +} + +static int pakfire_linter_check_pie( + struct pakfire_linter* linter, struct pakfire_file* file) { + switch (pakfire_linter_get_elf_type(linter, file)) { + // Shared Object files are good + case ET_DYN: + return 0; + + // Everything else is bad + default: + break; + } + + return pakfire_linter_error(linter, "%s is not PIE", pakfire_file_get_path(file)); +} + static int pakfire_linter_read_file( struct pakfire_linter* linter, struct pakfire_file* file, struct archive* a) { int fd = -EBADF; @@ -295,7 +446,10 @@ static int pakfire_linter_read_file( goto ERROR; } - return fd; + // Store the file descriptor + r = pakfire_file_set_fd(file, fd); + if (r < 0) + goto ERROR; ERROR: if (fd >= 0) @@ -306,7 +460,6 @@ ERROR: static int pakfire_linter_payload( struct pakfire_linter* linter, struct pakfire_file* file, struct archive* a) { - int fd = -EBADF; int r; // Fetch path @@ -315,18 +468,21 @@ static int pakfire_linter_payload( CTX_DEBUG(linter->ctx, "Checking payload of %s\n", path); // Read the file - fd = pakfire_linter_read_file(linter, file, a); - if (fd < 0) { - r = fd; + r = pakfire_linter_read_file(linter, file, a); + if (r < 0) goto ERROR; - } - r = 0; + // Check ELF files + if (pakfire_linter_file_is_elf(linter, file)) { + // Check PIE + r = pakfire_linter_check_pie(linter, file); + if (r < 0) + goto ERROR; -ERROR: - if (fd >= 0) - close(fd); + // TODO + } +ERROR: return r; } @@ -350,6 +506,11 @@ static int pakfire_linter_name(struct pakfire_linter* linter) { return 0; } +static int pakfire_linter_lint_source( + struct pakfire_linter* linter, struct pakfire_file* file) { + return 0; +} + static int pakfire_linter_lint_fhs( struct pakfire_linter* linter, struct pakfire_file* file) { int r; @@ -414,7 +575,14 @@ static int pakfire_linter_file(struct pakfire_archive* archive, CTX_DEBUG(linter->ctx, "Linting %s...\n", pakfire_file_get_path(file)); - if (!pakfire_package_is_source(linter->pkg)) { + // Source Packages + if (pakfire_package_is_source(linter->pkg)) { + r = pakfire_linter_lint_source(linter, file); + if (r < 0) + goto ERROR; + + // Binary Packages + } else { // Checking against FHS r = pakfire_linter_lint_fhs(linter, file); if (r < 0)