#include <archive.h>
#include <archive_entry.h>
+// libelf
+#include <gelf.h>
+
#include <pakfire/archive.h>
#include <pakfire/fhs.h>
#include <pakfire/file.h>
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;
goto ERROR;
}
- return fd;
+ // Store the file descriptor
+ r = pakfire_file_set_fd(file, fd);
+ if (r < 0)
+ goto ERROR;
ERROR:
if (fd >= 0)
static int pakfire_linter_payload(
struct pakfire_linter* linter, struct pakfire_file* file, struct archive* a) {
- int fd = -EBADF;
int r;
// Fetch path
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;
}
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;
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)