mirror of
https://github.com/morgan9e/systemd
synced 2026-04-15 00:47:10 +09:00
pull-job: port .payload field to struct iovec
struct iovec is really how we should encode any form of arbitrary blob data
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user