#include <errno.h>
#include <stdlib.h>
+// libelf
+#include <gelf.h>
+
#include <pakfire/ctx.h>
#include <pakfire/file.h>
#include <pakfire/linter.h>
// File Descriptor
int fd;
+
+ // Path
+ const char* path;
};
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) {
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;
+}
#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) {
- 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;
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)