diff --git a/src/repart/repart.c b/src/repart/repart.c index 91cd77b448..75fb79c48a 100644 --- a/src/repart/repart.c +++ b/src/repart/repart.c @@ -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; diff --git a/test/units/TEST-58-REPART.sh b/test/units/TEST-58-REPART.sh index fb3dbcfad5..7b536fa092 100755 --- a/test/units/TEST-58-REPART.sh +++ b/test/units/TEST-58-REPART.sh @@ -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" \