engineering: support inline dm-verity in COSI-derived Host Configurations - #754
Draft
Paco Huelsz (frhuelsz) wants to merge 3 commits into
Draft
engineering: support inline dm-verity in COSI-derived Host Configurations#754Paco Huelsz (frhuelsz) wants to merge 3 commits into
Paco Huelsz (frhuelsz) wants to merge 3 commits into
Conversation
…ions
Azure Container Linux images use *inline* dm-verity: the hash tree lives
inside the same partition as the data, at a byte offset, rather than in a
dedicated hash partition. `trident grpc-client stream-disk` could not
install such an image.
Derivation resolved the verity hash partition purely by image path. With
inline verity the verity entry points at the same image as the filesystem,
so it produced a VerityDevice whose data and hash devices were the same
partition, which the storage graph then rejected:
Derived Host Configuration is invalid: Referrer 'verity-1' of kind
'verity-device' references target 'partition-2' more than once
Trident also had nowhere to record where the hash tree began, and never
passed an offset to `veritysetup open`.
Changes:
- Read `hashOffset` from COSI verity metadata. Image Customizer already
emits this field for inline layouts (see its `cosiapi` package), so this
only consumes what the producer declares; the COSI spec and schema are
unchanged.
- Carry the offset on the OS image next to the root hash. Like the root
hash, it is a property of the image rather than of the Host
Configuration, so it is read from image metadata at servicing time and
does not appear in the Host Configuration or Host Status.
- Allow a verity device to name the same partition as both its data and
hash device. `hashDeviceId` remains required, so the Host Configuration
schema is unchanged apart from documentation. The storage graph models
the inline case as the single device it is, rather than as a second
reference to the same node, which leaves the duplicate-target and
referrer-sharing invariants untouched. Verity referrer cardinality
becomes 1..=2, and the hash partition type cross-check is skipped when
there is no distinct hash partition.
- Pass `--hash-offset` to `veritysetup open`, so an inline-verity device is
actually opened and verified during servicing.
Derivation fails with a clear error naming `hashOffset` when an image uses
inline verity but does not say where the hash tree starts, rather than
producing a device that cannot be opened.
Tested against a real ACL image end to end: derivation, graph construction
and full Host Configuration validation pass; `stream-disk` writes all five
partitions; verity activates and reports `verified`; and the installed
system boots with systemd activating dm-verity on /usr from the UKI command
line.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Azure Pipelines: Successfully started running 1 pipeline(s). There may be pipelines that require an authorized user to comment /azp run to run. |
Inline dm-verity is not an officially supported configuration, so the public Host Configuration reference should not describe it. Reverts the `hashDeviceId` doc comment to its original wording. The generated `VerityDevice.md` and `host-config-schema.json` are now byte-identical to main, so this change makes no alteration to Trident's documented public API surface. Support itself is unaffected: inline verity is still derived, opened with `--hash-offset`, and verified. The behaviour is simply not advertised. The only remaining generated-doc difference is the verity-device row of the referrer cardinality table in Storage-Rules.md (2..2 becomes 1..2). That table is generated from the cardinality rule itself and states a reference count without mentioning inline verity; suppressing it would mean reverting the rule and reintroducing the graph invariant exemptions this design deliberately avoids. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Image Customizer has emitted `hashOffset` since azure-linux-image-tools#702
("Add support for inline verity"), where it is declared in its `cosiapi`
package and written only for images whose verity hash tree is stored inside
the data partition. COSI 1.2 documents describe the field nowhere, so the
spec has been behind its producer.
Document it: add `hashOffset` to the `VerityConfig` table, note that the
`image` field refers to the same image as the filesystem's own for inline
verity, add a sample, and record the field in the 1.2 changelog.
The addition is descriptive rather than a format change. `hashOffset` is
optional and absent for the ordinary separate-hash-partition layout, so
every existing COSI remains valid and consumers that ignore the field remain
correct.
Extends the schema gate with an inline-verity sample under
tests/cosi/metadata_samples/v1.2/valid/, plus a negative sample asserting
the offset cannot be negative. Verified with check-jsonschema, as the CI
workflow does; also confirmed the metadata of a real inline-verity image
validates against the updated schema.
Note this documents the COSI format Trident consumes. It does not present
inline verity as a supported Host Configuration: the Host Configuration
reference and its schema are unchanged.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🔍 Description
engineering. Adds support for inline dm-verity to Host Configuration derivation from COSI, so
trident grpc-client stream-diskcan install Azure Container Linux (ACL) images.Inline verity stores the hash tree inside the same partition as the data, at a byte offset, rather than in a dedicated hash partition.
🤔 Rationale
Streaming a real ACL image failed during derivation:
Derivation resolved the verity hash partition purely by image path. With inline verity the verity entry points at the same image as the filesystem, so it emitted a
VerityDevicewhose data and hash devices were the same partition, which the storage graph rejected. Trident also had nowhere to record where the hash tree began, and never passed an offset toveritysetup open.This was not a regression — inline verity was never supported.
git log --all --grep=inlineis empty and nothing referencedhashOffset. #673 made ACL work for A/B update, but that path never derives a Host Configuration; it reads the root hash fromusrhash=on the UKI cmdline and mounts/usrdirectly, so it never had to model the layout.Changes
hashOffsetfrom COSI verity metadata. Image Customizer already emits this field for inline layouts — it is declared in itscosiapipackage and was added upstream by azure-linux-image-tools#702 ("Add support for inline verity"), gated so it appears only when inline, and covered by an IC test. This change consumes what the producer already declares, and brings Trident's COSI reference up to date with it:hashOffsetis now documented inComposable-OS-Image.md, the v1.2 JSON Schema, and the changelog. The addition is descriptive and backward compatible — the field is optional and absent for the ordinary separate-hash-partition layout, so every existing COSI stays valid.hashDeviceIdstays required, so the Host Configuration schema is completely unchanged —host-config-schema.jsonand the generatedVerityDevice.mdare byte-identical tomain. The graph models the inline case as the single device it is rather than as a second reference to the same node, which leaves the duplicate-target and referrer-sharing invariants untouched. Verity referrer cardinality becomes1..=2, and the hash partition-type cross-check is skipped when there is no distinct hash partition.--hash-offsettoveritysetup open, so an inline-verity device is actually opened and verified during servicing rather than skipped.Two documentation sets are treated differently on purpose. The COSI reference describes the format Trident consumes, so it documents
hashOffsetas a factual property of images IC already produces. The Host Configuration reference describes what users may configure, and inline dm-verity is not an officially supported configuration, so it is deliberately not documented there —host-config-schema.jsonand the generatedVerityDevice.mdare byte-identical tomain. The only generated-doc change is the verity-device row of the referrer cardinality table inStorage-Rules.md(2..2→1..2), which states a reference count without mentioning inline verity.Derivation fails with a clear error naming
hashOffsetif an image uses inline verity but does not say where the hash tree starts, instead of producing a device that cannot be opened.📝 Checks
Manually validated end to end on a real ACL image (
acl-base-3.0.20260706), installed viastream-diskfrom an Azure Linux installer ISO built with RPMs from this branch, in QEMU/KVM:HostConfiguration::validate()passesServicing completed successfully; rebootverified6.6.143.1, with systemd activating dm-verity on/usrfrom the UKI cmdline (sysusr-usr.mount,/dev/mapper/usr, zero mount failures), 38 targets reachedFirst boot then stops at
emergency.targetbecause Ignition cannot reach Azure IMDS (169.254.169.254) — expected off-Azure for an image carryingflatcar.oem.id=azure, and downstream of everything this PR touches (verity was already mounted and verified before Ignition ran).Before writing any code, the underlying
veritysetupinvocation was confirmed against the real disk image:Automated: 22 test suites pass workspace-wide,
cargo fmt --checkclean,cargo clippyintroduces no new warnings. Addstest_derive_host_configuration_inner_inline_verity(pinning ACL's realusrpartition type GUID, which exercises partition-type rules a generic Linux GUID would mask) and..._inline_verity_missing_offset.📌 Follow-ups
TODO:
osPackagesto be an array, but real ACL COSI files set it tonulland Trident already tolerates that (acl COSI files do not contain ospackages #707). Validating an ACL image's metadata against the checked-in schema fails onosPackagesalone — a pre-existing divergence, unrelated to this PR and left alone here.🗒️ Notes
Opened as a draft: functionally validated end to end, but wanted review on the graph modelling choice before marking ready.
The main design question is how inline verity is represented. Two alternatives were built and discarded:
/usrread-only straight off the partition and leaving verity to systemd at boot. Smallest change and it validates, but Trident never verifies the image it just wrote. It also has a trap: the non-verity path drops theromount option, andresizeis skipped only whenis_read_only() || !fs_type.is_ext(). ACL survives on thebtrfsclause alone; an ext4 inline-verity image would be resized and have its appended hash tree silently destroyed.hash_device_id: Option<BlockDeviceId>. Cleaner conceptually, but it is a Host Status wire-format change that rippled through ~30 files.The approach here keeps the Host Configuration and Host Status untouched while still verifying at install time.