diff --git a/acl/docs/architecture.md b/acl/docs/architecture.md index 6339e9e7f70..84d6ada0b4a 100644 --- a/acl/docs/architecture.md +++ b/acl/docs/architecture.md @@ -54,6 +54,7 @@ ACL's primary boot path uses **systemd-boot** with **Unified Kernel Images (UKI) The `/usr` partition (USR-A) is a read-only btrfs filesystem with zstd compression. **dm-verity** provides block-level integrity verification: - The verity hash tree is stored in a dedicated hash partition (HASH-A, immediately following USR-A on disk). +- A separate, currently-unused 1 MiB partition (HASH-SIG-A) immediately follows HASH-A, reserved for a future verity root-hash signature. - At boot, `systemd-veritysetup` activates the verity device using slot-specific parameters delivered via a per-slot systemd-stub addon: `systemd.verity_usr_data=PARTUUID=`, `systemd.verity_usr_hash=PARTUUID=`, and `systemd.verity_usr_options=panic-on-corruption`. - The main UKI cmdline stays slot-independent (`mount.usr=/dev/mapper/usr`); Trident switches slots by swapping which addon is active in `.efi.extra.d/`, so the same signed UKI boots either A or B. (The secondary GRUB boot path is out of scope for A/B update and is unchanged: it still uses the inline PARTUUID + hash-offset verity cmdline on the existing non-UKI partition layout.) - Any corruption of `/usr` causes an immediate kernel panic, preventing the system from running a tampered image. diff --git a/acl/docs/containerd-image-preload.md b/acl/docs/containerd-image-preload.md index aac5d3650ba..60f1aceb082 100644 --- a/acl/docs/containerd-image-preload.md +++ b/acl/docs/containerd-image-preload.md @@ -323,10 +323,15 @@ actually recovers the store. ### Inspect the output image without booting ```sh -sudo modprobe nbd max_part=8 +sudo modprobe nbd max_part=9 sudo qemu-nbd --connect=/dev/nbd0 --read-only -f vpc staging/out/acl-preloaded.vhd sudo mkdir -p /mnt/verify -sudo mount -o ro /dev/nbd0p7 /mnt/verify # ROOT is the seventh partition + +# Select ROOT by GPT partition label rather than a hard-coded index -- the +# partition number varies by layout (e.g. ROOT is p7 on the pre-usr-verity-sig +# layout, p9 once hash-sig-a/hash-sig-b are present). +ROOT_PART=$(sudo blkid -t PARTLABEL="ROOT" -o device /dev/nbd0p* | head -n1) +sudo mount -o ro "${ROOT_PART}" /mnt/verify ls -la /mnt/verify/var/lib/containerd strings /mnt/verify/var/lib/containerd/io.containerd.metadata.v1.bolt/meta.db \ diff --git a/build_library/disk_layout_uki.json b/build_library/disk_layout_uki.json index b4fb24edb37..14b1753647b 100644 --- a/build_library/disk_layout_uki.json +++ b/build_library/disk_layout_uki.json @@ -35,26 +35,44 @@ ] }, "3": { + "_comment": "9 MiB verity hash tree for USR-A (1 GiB). Assumes sha256 + 4096-byte data/hash blocks (dm-verity default): tree size is ~8.08 MiB (2048 level-0 hash blocks + 17 upper-level blocks + superblock), so 9 MiB leaves headroom for growth. Recompute if USR-A size or verity hash/block params change.", "label": "HASH-A", "uuid": "b736baf1-cdb4-4535-beba-ddaaa30ad7b7", "type": "dps-usr-verity", - "blocks": "20480" + "blocks": "18432" }, "4": { + "_comment": "1 MiB reserved for a future USR-A verity root-hash signature. blocks/part_alignment are 512-byte sectors (see metadata.block_size); part_alignment is overridden to 2048 sectors (1 MiB, vs. the file-wide 4096-sector/2 MiB default) so this partition packs directly after HASH-A with no gap, while the combined 10 MiB HASH-A+HASH-SIG-A still lands on the 2 MiB boundary required by USR-B.", + "label": "HASH-SIG-A", + "uuid": "3514648f-e3da-44ae-89ba-8d0552418f88", + "type": "dps-usr-verity-sig", + "part_alignment": "2048", + "blocks": "2048" + }, + "5": { "label": "USR-B", "uuid": "e03dd35c-7c2d-4a47-b3fe-27f15780a57c", "type": "flatcar-rootfs", "blocks": "2097152", "fs_blocks": "262144", - "verity_hash": "5" + "verity_hash": "6" }, - "5": { + "6": { + "_comment": "9 MiB verity hash tree for USR-B. See HASH-A comment for sizing rationale.", "label": "HASH-B", "uuid": "35bdf78b-c453-4661-98e6-f834f534ef5b", "type": "dps-usr-verity", - "blocks": "20480" + "blocks": "18432" }, - "6": { + "7": { + "_comment": "1 MiB reserved for a future USR-B verity root-hash signature. See HASH-SIG-A comment for units and part_alignment rationale.", + "label": "HASH-SIG-B", + "uuid": "d8941eb2-f713-4bb6-b4ae-bd8350ca27d4", + "type": "dps-usr-verity-sig", + "part_alignment": "2048", + "blocks": "2048" + }, + "8": { "label": "OEM", "fs_label": "OEM", "type": "data", @@ -63,7 +81,7 @@ "fs_compression": "zlib", "mount": "/oem" }, - "7": { + "9": { "label": "ROOT", "fs_label": "ROOT", "type": "dps-root", @@ -73,21 +91,21 @@ } }, "vm": { - "7": { + "9": { "label": "ROOT", "fs_label": "ROOT", "blocks": "12943360" } }, "azure": { - "7": { + "9": { "label": "ROOT", "fs_label": "ROOT", "blocks": "58875904" } }, "vagrant": { - "7": { + "9": { "label": "ROOT", "fs_label": "ROOT", "blocks": "33845248" @@ -113,6 +131,12 @@ "type": "blank" }, "7": { + "type": "blank" + }, + "8": { + "type": "blank" + }, + "9": { "label": "ROOT", "fs_label": "ROOT", "type": "0fc63daf-8483-4772-8e79-3d69d8477de4", diff --git a/build_library/disk_util b/build_library/disk_util index c8f64ef4ab6..772854ea5e0 100755 --- a/build_library/disk_util +++ b/build_library/disk_util @@ -39,6 +39,11 @@ DPS_USR_VERITY_GUIDS = { 'aarch64': '6E11A4E7-FBCA-4DED-B9E9-E1A512BB664E', } +DPS_USR_VERITY_SIG_GUIDS = { + 'x86_64': 'E7BB33FB-06CF-4E81-8273-E543B413E2E2', + 'aarch64': 'C23CE4FF-44BD-4B00-B2D4-B41B3419E02A', +} + # Map BOARD names used by the build system to machine architecture values. BOARD_TO_ARCH = { 'amd64-usr': 'x86_64', @@ -49,12 +54,14 @@ def _resolve_dps_types(config, arch): """Replace symbolic DPS partition type names with architecture-specific GUIDs. Currently supported placeholders: - dps-root → DPS root partition GUID for the target architecture - dps-usr-verity → DPS /usr verity hash partition GUID + dps-root → DPS root partition GUID for the target architecture + dps-usr-verity → DPS /usr verity hash partition GUID + dps-usr-verity-sig → DPS /usr verity signature partition GUID """ dps_map = { 'dps-root': DPS_ROOT_GUIDS, 'dps-usr-verity': DPS_USR_VERITY_GUIDS, + 'dps-usr-verity-sig': DPS_USR_VERITY_SIG_GUIDS, } for layout in config.get('layouts', {}).values(): for part in layout.values():