repart: trim NUL bytes from verity sig split artifact

The verity signature partition content is a bare JSON object. Repart
pads it with zeros to fill the GPT partition. But when splitting out
the content as an individual file, the padding remains, so it's not
a valid text file.

jq started rejecting files with NUL bytes to fix a security issue:
https://github.com/jqlang/jq/commit/6374ae0bcdfe33a18eb0ae6db28493b1f34a0a5b

Trim the output when writing these files out.
This commit is contained in:
Luca Boccassi
2026-04-23 12:16:10 +02:00
committed by Zbigniew Jędrzejewski-Szmek
parent 1be5cbd6c1
commit b54ef83414
2 changed files with 32 additions and 3 deletions
+24 -3
View File
@@ -7754,9 +7754,30 @@ static int context_split(Context *context) {
if (lseek(fd, p->offset, SEEK_SET) < 0)
return log_error_errno(errno, "Failed to seek to partition offset: %m");
r = copy_bytes(fd, fdt, p->new_size, COPY_REFLINK|COPY_HOLES|COPY_TRUNCATE);
if (r < 0)
return log_error_errno(r, "Failed to copy to split partition %s: %m", p->split_path);
/* Verity signature partitions contain a JSON object NUL-padded out to the partition
* size. The on-disk partition must keep the padding, but the split-out file is a
* standalone artifact, so trim the trailing NUL bytes there to avoid tripping jq. */
if (partition_designator_is_verity_sig(p->type.designator)) {
_cleanup_free_ char *buf = malloc(p->new_size);
if (!buf)
return log_oom();
r = loop_read_exact(fd, buf, p->new_size, /* do_poll= */ false);
if (r < 0)
return log_error_errno(r, "Failed to read verity signature partition: %m");
size_t len = strnlen(buf, p->new_size);
if (len == 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Verity signature partition is empty");
r = loop_write(fdt, buf, len);
if (r < 0)
return log_error_errno(r, "Failed to write to split partition %s: %m", p->split_path);
} else {
r = copy_bytes(fd, fdt, p->new_size, COPY_REFLINK|COPY_HOLES|COPY_TRUNCATE);
if (r < 0)
return log_error_errno(r, "Failed to copy to split partition %s: %m", p->split_path);
}
}
return 0;
+8
View File
@@ -941,6 +941,7 @@ EOF
--dry-run=no \
--empty=create \
--size=auto \
--split=yes \
--json=pretty \
--private-key="$defs/verity.key" \
--certificate="$defs/verity.crt" \
@@ -953,6 +954,13 @@ EOF
assert_eq "$drh" "$hrh"
assert_eq "$hrh" "$srh"
# The split-out verity signature file should be a valid JSON document (i.e. trailing NUL padding
# from the on-disk partition must be trimmed when writing the split file).
sig_split=$(jq -r ".[] | select(.type == \"root-${architecture}-verity-sig\") | .split_path" <<<"$output")
assert_neq "$sig_split" ""
assert_neq "$sig_split" "null"
jq . "$sig_split" >/dev/null
# Check that offline signing works and the resulting image is valid
output=$(systemd-repart --offline="$OFFLINE" \