From: Michael Tremer Date: Thu, 24 Oct 2024 16:52:02 +0000 (+0000) Subject: linter: Read the payload into memory X-Git-Tag: 0.9.30~909 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bae3d503f387239f6358d3d0c8f14b098546b688;p=pakfire.git linter: Read the payload into memory Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/file.c b/src/libpakfire/file.c index c162fa3b9..05c84181f 100644 --- a/src/libpakfire/file.c +++ b/src/libpakfire/file.c @@ -993,6 +993,20 @@ PAKFIRE_EXPORT void pakfire_file_set_mtime(struct pakfire_file* file, time_t tim archive_entry_set_mtime(file->entry, time, 0); } +int pakfire_file_has_payload(struct pakfire_file* file) { + // File must be a regular file + switch (pakfire_file_get_type(file)) { + case S_IFREG: + break; + + default: + return 0; + } + + // File must be larger than zero + return pakfire_file_get_size(file) > 0; +} + PAKFIRE_EXPORT const unsigned char* pakfire_file_get_digest( struct pakfire_file* file, const enum pakfire_digest_types type, size_t* length) { diff --git a/src/libpakfire/include/pakfire/file.h b/src/libpakfire/include/pakfire/file.h index a175c91ff..468fb8657 100644 --- a/src/libpakfire/include/pakfire/file.h +++ b/src/libpakfire/include/pakfire/file.h @@ -132,6 +132,7 @@ enum pakfire_file_classes { PAKFIRE_FILE_RUNTIME_LINKER = (1 << 14), }; +int pakfire_file_has_payload(struct pakfire_file* file); int pakfire_file_read(struct pakfire_file* file, struct archive* reader, const char* path); diff --git a/src/libpakfire/linter.c b/src/libpakfire/linter.c index 99119b4ef..3f033ae15 100644 --- a/src/libpakfire/linter.c +++ b/src/libpakfire/linter.c @@ -20,6 +20,7 @@ #include #include +#include #include // libarchive @@ -218,6 +219,107 @@ void pakfire_linter_set_result_callback(struct pakfire_linter* linter, linter->result_data = data; } +static int pakfire_linter_read_file( + struct pakfire_linter* linter, struct pakfire_file* file, struct archive* a) { + int fd = -EBADF; + int r; + + // Fetch path + const char* path = pakfire_file_get_path(file); + + // Allocate a new buffer + fd = memfd_create(path, MFD_CLOEXEC); + if (fd < 0) { + CTX_ERROR(linter->ctx, "memfd_create() failed: %m\n"); + r = -errno; + goto ERROR; + } + + // Fetch file size + size_t size = pakfire_file_get_size(file); + + // Tell the kernel how large the file would be + r = ftruncate(fd, size); + if (r < 0) { + CTX_ERROR(linter->ctx, "fallocate() failed: %m\n"); + r = -errno; + goto ERROR; + } + + // Read the payload into the file descriptor + r = archive_read_data_into_fd(a, fd); + if (r) { + CTX_ERROR(linter->ctx, "Could not read %s: %s\n", path, archive_error_string(a)); + r = -errno; + goto ERROR; + } + + // Check how much data we have read + off_t offset = lseek(fd, 0, SEEK_CUR); + if (offset < 0) { + CTX_ERROR(linter->ctx, "lseek() failed: %m\n"); + r = -errno; + goto ERROR; + } + + CTX_DEBUG(linter->ctx, "Read %jd byte(s)\n", offset); + + // Check if we didn't read too little data + if ((size_t)offset < size) { + r = pakfire_linter_error(linter, "%s is actually smaller than %zu byte(s)", path, size); + if (r < 0) + goto ERROR; + + // Check if we have not read more data + } else if ((size_t)offset > size) { + r = pakfire_linter_error(linter, "/%s is actually larger than %zu byte(s)", path, size); + if (r < 0) + goto ERROR; + } + + // Rewind + offset = lseek(fd, 0, SEEK_SET); + if (offset) { + CTX_ERROR(linter->ctx, "Could not rewind: %m\n"); + r = -errno; + goto ERROR; + } + + return fd; + +ERROR: + if (fd >= 0) + close(fd); + + return r; +} + +static int pakfire_linter_payload( + struct pakfire_linter* linter, struct pakfire_file* file, struct archive* a) { + int fd = -EBADF; + int r; + + // Fetch path + const char* path = pakfire_file_get_path(file); + + 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; + goto ERROR; + } + + r = 0; + +ERROR: + if (fd >= 0) + close(fd); + + return r; +} + static int pakfire_linter_name(struct pakfire_linter* linter) { int r; @@ -289,7 +391,7 @@ static int pakfire_linter_lint_fhs( return 0; } -static int pakfire_linter_payload(struct pakfire_archive* archive, +static int pakfire_linter_file(struct pakfire_archive* archive, struct archive* a, struct archive_entry* e, void* data) { struct pakfire_linter* linter = data; struct pakfire_file* file = NULL; @@ -309,6 +411,13 @@ static int pakfire_linter_payload(struct pakfire_archive* archive, goto ERROR; } + // Lint the payload for regular files + if (pakfire_file_has_payload(file)) { + r = pakfire_linter_payload(linter, file, a); + if (r < 0) + goto ERROR; + } + ERROR: if (file) pakfire_file_unref(file); @@ -325,7 +434,7 @@ int pakfire_linter_lint(struct pakfire_linter* linter) { return r; // Lint the payload - r = pakfire_archive_walk_payload(linter->archive, pakfire_linter_payload, linter); + r = pakfire_archive_walk_payload(linter->archive, pakfire_linter_file, linter); if (r < 0) return r;