]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
pull-job: port .payload field to struct iovec 39620/head
authorLennart Poettering <lennart@poettering.net>
Fri, 7 Nov 2025 12:52:38 +0000 (13:52 +0100)
committerLennart Poettering <lennart@poettering.net>
Sat, 8 Nov 2025 08:28:50 +0000 (09:28 +0100)
struct iovec is really how we should encode any form of arbitrary blob
data

src/import/pull-common.c
src/import/pull-job.c
src/import/pull-job.h

index a58b8b8185fb754be78509822334e012608f35be..12d9736725c9caa4b943b3b520be9a4756dd0620 100644 (file)
@@ -380,8 +380,8 @@ static int verify_one(PullJob *checksum_job, PullJob *job) {
                 if (!line)
                         return log_oom();
 
-                p = memmem_safe(checksum_job->payload,
-                                checksum_job->payload_size,
+                p = memmem_safe(checksum_job->payload.iov_base,
+                                checksum_job->payload.iov_len,
                                 line,
                                 strlen(line));
                 if (p)
@@ -389,7 +389,7 @@ static int verify_one(PullJob *checksum_job, PullJob *job) {
         }
 
         /* Only counts if found at beginning of a line */
-        if (!p || (p != (char*) checksum_job->payload && p[-1] != '\n'))
+        if (!p || (p != (char*) checksum_job->payload.iov_base && p[-1] != '\n'))
                 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG),
                                        "DOWNLOAD INVALID: Checksum of %s file did not check out, file has been tampered with.", fn);
 
@@ -398,8 +398,8 @@ static int verify_one(PullJob *checksum_job, PullJob *job) {
 }
 
 static int verify_gpg(
-                const void *payload, size_t payload_size,
-                const void *signature, size_t signature_size) {
+                const struct iovec *payload,
+                const struct iovec *signature) {
 
         _cleanup_close_pair_ int gpg_pipe[2] = EBADF_PAIR;
         _cleanup_(rm_rf_physical_and_freep) char *gpg_home = NULL;
@@ -407,21 +407,21 @@ static int verify_gpg(
         _cleanup_(sigkill_waitp) pid_t pid = 0;
         int r;
 
-        assert(payload || payload_size == 0);
-        assert(signature || signature_size == 0);
+        assert(iovec_is_valid(payload));
+        assert(iovec_is_valid(signature));
 
         r = pipe2(gpg_pipe, O_CLOEXEC);
         if (r < 0)
                 return log_error_errno(errno, "Failed to create pipe for gpg: %m");
 
-        if (signature_size > 0) {
+        if (iovec_is_set(signature)) {
                 _cleanup_close_ int sig_file = -EBADF;
 
                 sig_file = mkostemp(sig_file_path, O_RDWR);
                 if (sig_file < 0)
                         return log_error_errno(errno, "Failed to create temporary file: %m");
 
-                r = loop_write(sig_file, signature, signature_size);
+                r = loop_write(sig_file, signature->iov_base, signature->iov_len);
                 if (r < 0) {
                         log_error_errno(r, "Failed to write to temporary file: %m");
                         goto finish;
@@ -487,10 +487,12 @@ static int verify_gpg(
 
         gpg_pipe[0] = safe_close(gpg_pipe[0]);
 
-        r = loop_write(gpg_pipe[1], payload, payload_size);
-        if (r < 0) {
-                log_error_errno(r, "Failed to write to pipe: %m");
-                goto finish;
+        if (iovec_is_set(payload)) {
+                r = loop_write(gpg_pipe[1], payload->iov_base, payload->iov_len);
+                if (r < 0) {
+                        log_error_errno(r, "Failed to write to pipe: %m");
+                        goto finish;
+                }
         }
 
         gpg_pipe[1] = safe_close(gpg_pipe[1]);
@@ -507,7 +509,7 @@ static int verify_gpg(
         }
 
 finish:
-        if (signature_size > 0)
+        if (iovec_is_set(signature))
                 (void) unlink(sig_file_path);
 
         return r;
@@ -553,7 +555,7 @@ int pull_verify(ImportVerify verify,
                 assert(checksum_job);
                 assert(checksum_job->state == PULL_JOB_DONE);
 
-                if (!checksum_job->payload || checksum_job->payload_size <= 0)
+                if (!iovec_is_set(&checksum_job->payload))
                         return log_error_errno(SYNTHETIC_ERRNO(EBADMSG),
                                                "Checksum is empty, cannot verify.");
 
@@ -579,11 +581,11 @@ int pull_verify(ImportVerify verify,
         assert(signature_job);
         assert(signature_job->state == PULL_JOB_DONE);
 
-        if (!signature_job->payload || signature_job->payload_size <= 0)
+        if (!iovec_is_set(&signature_job->payload))
                 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG),
                                        "Signature is empty, cannot verify.");
 
-        return verify_gpg(verify_job->payload, verify_job->payload_size, signature_job->payload, signature_job->payload_size);
+        return verify_gpg(&verify_job->payload, &signature_job->payload);
 }
 
 int verification_style_from_url(const char *url, VerificationStyle *ret) {
index 1945106099d0bb02889fd67fb3ae4e4e2c801d24..621a90a86e308d0a7bb0bcc36e766b4a37272d29 100644 (file)
@@ -57,7 +57,7 @@ PullJob* pull_job_unref(PullJob *j) {
         free(j->url);
         free(j->etag);
         strv_free(j->old_etags);
-        free(j->payload);
+        iovec_done(&j->payload);
         iovec_done(&j->checksum);
         iovec_done(&j->expected_checksum);
 
@@ -95,8 +95,7 @@ static int pull_job_restart(PullJob *j, const char *new_url) {
 
         j->state = PULL_JOB_INIT;
         j->error = 0;
-        j->payload = mfree(j->payload);
-        j->payload_size = 0;
+        iovec_done(&j->payload);
         j->written_compressed = 0;
         j->written_uncompressed = 0;
         j->content_length = UINT64_MAX;
@@ -381,11 +380,14 @@ static int pull_job_write_uncompressed(const void *p, size_t sz, void *userdata)
         }
 
         if (j->disk_fd < 0 || j->force_memory) {
-                if (!GREEDY_REALLOC(j->payload, j->payload_size + sz + 1))
+                uint8_t *a = j->payload.iov_base;
+
+                if (!GREEDY_REALLOC(a, j->payload.iov_len + sz + 1))
                         return log_oom();
 
-                *((char*) mempcpy(j->payload + j->payload_size, p, sz)) = 0;
-                j->payload_size += sz;
+                *((uint8_t*) mempcpy(a + j->payload.iov_len, p, sz)) = 0;
+                j->payload.iov_base = a;
+                j->payload.iov_len += sz;
         }
 
         j->written_uncompressed += sz;
@@ -397,39 +399,39 @@ finish:
         return 0;
 }
 
-static int pull_job_write_compressed(PullJob *j, void *p, size_t sz) {
+static int pull_job_write_compressed(PullJob *j, const struct iovec *data) {
         int r;
 
         assert(j);
-        assert(p);
+        assert(iovec_is_valid(data));
 
-        if (sz <= 0)
+        if (!iovec_is_set(data))
                 return 0;
 
-        if (j->written_compressed + sz < j->written_compressed)
+        if (j->written_compressed + data->iov_len < j->written_compressed)
                 return log_error_errno(SYNTHETIC_ERRNO(EOVERFLOW), "File too large, overflow");
 
-        if (j->written_compressed + sz > j->compressed_max)
+        if (j->written_compressed + data->iov_len > j->compressed_max)
                 return log_error_errno(SYNTHETIC_ERRNO(EFBIG), "File overly large, refusing.");
 
         uint64_t cl = pull_job_content_length_effective(j);
         if (cl != UINT64_MAX &&
-            j->written_compressed + sz > cl)
+            j->written_compressed + data->iov_len > cl)
                 return log_error_errno(SYNTHETIC_ERRNO(EFBIG),
                                        "Content length incorrect.");
 
         if (j->checksum_ctx) {
-                r = EVP_DigestUpdate(j->checksum_ctx, p, sz);
+                r = EVP_DigestUpdate(j->checksum_ctx, data->iov_base, data->iov_len);
                 if (r == 0)
                         return log_error_errno(SYNTHETIC_ERRNO(EIO),
                                                "Could not hash chunk.");
         }
 
-        r = import_uncompress(&j->compress, p, sz, pull_job_write_uncompressed, j);
+        r = import_uncompress(&j->compress, data->iov_base, data->iov_len, pull_job_write_uncompressed, j);
         if (r < 0)
                 return r;
 
-        j->written_compressed += sz;
+        j->written_compressed += data->iov_len;
 
         return 0;
 }
@@ -470,14 +472,11 @@ static int pull_job_open_disk(PullJob *j) {
 }
 
 static int pull_job_detect_compression(PullJob *j) {
-        _cleanup_free_ uint8_t *stub = NULL;
-        size_t stub_size;
-
         int r;
 
         assert(j);
 
-        r = import_uncompress_detect(&j->compress, j->payload, j->payload_size);
+        r = import_uncompress_detect(&j->compress, j->payload.iov_base, j->payload.iov_len);
         if (r < 0)
                 return log_error_errno(r, "Failed to initialize compressor: %m");
         if (r == 0)
@@ -490,15 +489,11 @@ static int pull_job_detect_compression(PullJob *j) {
                 return r;
 
         /* Now, take the payload we read so far, and decompress it */
-        stub = j->payload;
-        stub_size = j->payload_size;
-
-        j->payload = NULL;
-        j->payload_size = 0;
+        _cleanup_(iovec_done) struct iovec stub = TAKE_STRUCT(j->payload);
 
         j->state = PULL_JOB_RUNNING;
 
-        r = pull_job_write_compressed(j, stub, stub_size);
+        r = pull_job_write_compressed(j, &stub);
         if (r < 0)
                 return r;
 
@@ -516,15 +511,11 @@ static size_t pull_job_write_callback(void *contents, size_t size, size_t nmemb,
 
         case PULL_JOB_ANALYZING:
                 /* Let's first check what it actually is */
-
-                if (!GREEDY_REALLOC(j->payload, j->payload_size + sz)) {
+                if (!iovec_append(&j->payload, &IOVEC_MAKE(contents, sz))) {
                         r = log_oom();
                         goto fail;
                 }
 
-                memcpy(j->payload + j->payload_size, contents, sz);
-                j->payload_size += sz;
-
                 r = pull_job_detect_compression(j);
                 if (r < 0)
                         goto fail;
@@ -532,8 +523,7 @@ static size_t pull_job_write_callback(void *contents, size_t size, size_t nmemb,
                 break;
 
         case PULL_JOB_RUNNING:
-
-                r = pull_job_write_compressed(j, contents, sz);
+                r = pull_job_write_compressed(j, &IOVEC_MAKE(contents, sz));
                 if (r < 0)
                         goto fail;
 
index 178cb8a30a1f113e3146df69dc04ff6d8e6e82a0..b07423817407a353bc0953689e5f829bd77f93f6 100644 (file)
@@ -60,8 +60,7 @@ typedef struct PullJob {
 
         uint64_t expected_content_length;
 
-        uint8_t *payload;
-        size_t payload_size;
+        struct iovec payload;
 
         int disk_fd;
         bool close_disk_fd;