From 134aecf8203b387c5d904a269c53f5cef8c73093 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Fri, 25 Oct 2024 17:33:34 +0000 Subject: [PATCH] linter: Move the ELF stuff to the file stuff Signed-off-by: Michael Tremer --- src/libpakfire/include/pakfire/linter-file.h | 2 + src/libpakfire/linter-file.c | 158 +++++++++++++++++++ src/libpakfire/linter.c | 157 +----------------- 3 files changed, 164 insertions(+), 153 deletions(-) diff --git a/src/libpakfire/include/pakfire/linter-file.h b/src/libpakfire/include/pakfire/linter-file.h index 4a57fec99..976f2356a 100644 --- a/src/libpakfire/include/pakfire/linter-file.h +++ b/src/libpakfire/include/pakfire/linter-file.h @@ -35,5 +35,7 @@ int pakfire_linter_file_create(struct pakfire_linter_file** lfile, struct pakfire_linter_file* pakfire_linter_file_ref(struct pakfire_linter_file* lfile); struct pakfire_linter_file* pakfire_linter_file_unref(struct pakfire_linter_file* lfile); +int pakfire_linter_file_lint(struct pakfire_linter_file* lfile); + #endif /* PAKFIRE_PRIVATE */ #endif /* PAKFIRE_LINTER_FILE_H */ diff --git a/src/libpakfire/linter-file.c b/src/libpakfire/linter-file.c index 4d1d2c73a..879d93708 100644 --- a/src/libpakfire/linter-file.c +++ b/src/libpakfire/linter-file.c @@ -21,6 +21,9 @@ #include #include +// libelf +#include + #include #include #include @@ -38,6 +41,9 @@ struct pakfire_linter_file { // File Descriptor int fd; + + // Path + const char* path; }; int pakfire_linter_file_create(struct pakfire_linter_file** lfile, @@ -66,6 +72,13 @@ int pakfire_linter_file_create(struct pakfire_linter_file** lfile, // Store a reference to the file l->file = pakfire_file_ref(file); + // Cache path + l->path = pakfire_file_get_path(l->file); + if (!l->path) { + r = -EINVAL; + goto ERROR; + } + // Store the file descriptor l->fd = dup(fd); if (l->fd < 0) { @@ -108,3 +121,148 @@ struct pakfire_linter_file* pakfire_linter_file_unref(struct pakfire_linter_file pakfire_linter_file_free(lfile); return NULL; } + +static int pakfire_linter_file_init_libelf(struct pakfire_linter_file* lfile) { + // Initialize libelf + if (elf_version(EV_CURRENT) == EV_NONE) { + ERROR(lfile->ctx, "Could not initialize libelf: %s\n", elf_errmsg(-1)); + return -EINVAL; + } + + return 0; +} + +static int pakfire_linter_file_is_elf(struct pakfire_linter_file* lfile) { + Elf* elf = NULL; + int r; + + // Initialize libelf + r = pakfire_linter_file_init_libelf(lfile); + if (r < 0) + return r; + + // Parse the ELF header + elf = elf_begin(lfile->fd, ELF_C_READ, NULL); + if (!elf) { + ERROR(lfile->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_file_elf(struct pakfire_linter_file* lfile, + int (*callback)(struct pakfire_linter_file* lfile, Elf* elf, void* data), void* data) { + Elf* elf = NULL; + int r; + + // Initialize libelf + r = pakfire_linter_file_init_libelf(lfile); + if (r < 0) + return r; + + // Parse the ELF header + elf = elf_begin(lfile->fd, ELF_C_READ, NULL); + if (!elf) { + ERROR(lfile->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: + ERROR(lfile->ctx, "%s is not an ELF object\n", lfile->path); + r = -EINVAL; + goto ERROR; + } + + // Call the callback + r = callback(lfile, elf, data); + +ERROR: + if (elf) + elf_end(elf); + + return r; +} + +static int __pakfire_linter_file_get_elf_type( + struct pakfire_linter_file* lfile, Elf* elf, void* data) { + GElf_Ehdr ehdr = {}; + + int* type = data; + + // Fetch the ELF header + if (!gelf_getehdr(elf, &ehdr)) { + ERROR(lfile->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_file_get_elf_type(struct pakfire_linter_file* lfile) { + int type = ET_NONE; + int r; + + // Fetch the type + r = pakfire_linter_file_elf(lfile, __pakfire_linter_file_get_elf_type, &type); + if (r < 0) + return r; + + return type; +} + +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 + case ET_DYN: + return 0; + + // Everything else is bad + default: + break; + } + + return pakfire_linter_error(lfile->linter, "%s is not PIE", lfile->path); +} + +int pakfire_linter_file_lint(struct pakfire_linter_file* lfile) { + int r = 0; + + // ELF Checks + if (pakfire_linter_file_is_elf(lfile)) { + // Check PIE + r = pakfire_linter_file_check_pie(lfile); + if (r < 0) + return r; + } + + return 0; +} diff --git a/src/libpakfire/linter.c b/src/libpakfire/linter.c index baf2872d4..3be333f36 100644 --- a/src/libpakfire/linter.c +++ b/src/libpakfire/linter.c @@ -28,9 +28,6 @@ #include #include -// libelf -#include - #include #include #include @@ -214,145 +211,6 @@ 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) { - 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, int fd) { - Elf* elf = NULL; - int r; - - // 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) { - 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 fd, - int (*callback)(struct pakfire_linter* linter, struct pakfire_file* file, Elf* elf, void* data), - void* data) { - Elf* elf = NULL; - int r; - - // 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) { - 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: - 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)) { - 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 fd) { - int type = ET_NONE; - int r; - - // Fetch the type - r = pakfire_linter_elf(linter, file, fd, __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, int fd) { - switch (pakfire_linter_get_elf_type(linter, file, fd)) { - // 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; @@ -460,17 +318,10 @@ static int pakfire_linter_payload( goto ERROR; } - // XXX TODO - - // Check ELF files - if (pakfire_linter_file_is_elf(linter, file, fd)) { - // Check PIE - r = pakfire_linter_check_pie(linter, file, fd); - if (r < 0) - goto ERROR; - - // TODO - } + // Lint the file + r = pakfire_linter_file_lint(lfile); + if (r < 0) + goto ERROR; ERROR: if (lfile) -- 2.39.5