Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Fixed
- guest: a fresh CVM with a verity volume could take the volume for its data disk and try to LUKS-format it: volumes labelled their data partition `dstack-data`, the data disk's label. `dstack verity` now labels it `dstack-volume-data`, and the guest skips disks that carry a `dstack-volume` partition, so volumes built by older releases are safe too

### Changed
- vmm: `qmp_socket` now defaults to `true`. Each CVM's QEMU exposes `qmp.sock` in its work dir, so the host can change disk options or compact a bloated `hda.img` (`blockdev-mirror`) without stopping the CVM. Applies to CVMs started after the change; set `qmp_socket = false` to opt out

Expand Down
11 changes: 8 additions & 3 deletions docs/verity-volumes.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,16 @@ hash measured in `app-compose.json`.
A built volume is a raw GPT image:

```text
p1: DSTACK_VOLUME metadata envelope
p2: filesystem data
p3: dm-verity superblock and hash tree
p1 dstack-volume: DSTACK_VOLUME metadata envelope
p2 dstack-volume-data: filesystem data
p3 dstack-verity: dm-verity superblock and hash tree
```

The guest opens the partitions by number; the labels only keep a volume apart
from the app data disk, whose partition is `dstack-data`. Older volumes label
p2 `dstack-data` too; the guest skips any disk with a `dstack-volume`
partition when it looks for the data disk.

The envelope identifies a candidate disk. It is not trusted. The guest passes
the root from the measured app compose to `veritysetup`, so a forged envelope or
partition table cannot substitute different contents.
Expand Down
4 changes: 2 additions & 2 deletions dstack/crates/dstack-volume/src/volume.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ fn write_gpt(mut out: fs::File, layout: &GptLayout, root_hash: &str) -> Result<f
first_lba: layout.data.first_lba,
last_lba: layout.data.last_lba,
flags: 0,
name: "dstack-data".to_string(),
name: "dstack-volume-data".to_string(),
},
);
parts.insert(
Expand Down Expand Up @@ -455,7 +455,7 @@ mod tests {
let data_partition = disk.partitions().get(&2).unwrap();
let hash_partition = disk.partitions().get(&3).unwrap();
assert_eq!(metadata.name, "dstack-volume");
assert_eq!(data_partition.name, "dstack-data");
assert_eq!(data_partition.name, "dstack-volume-data");
assert_eq!(hash_partition.name, "dstack-verity");
assert_eq!(
data_partition.part_guid,
Expand Down
35 changes: 33 additions & 2 deletions os/common/rootfs/dstack-prepare.sh
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,36 @@ find_block_by_property() {
return 1
}

# A verity volume's first partition is labelled dstack-volume. Volumes built
# before dstack-volume-data labelled their data partition dstack-data, the app
# data disk's label: never take a partition on such a disk for the data disk.
is_verity_volume_disk() {
local disk="$1" part
for part in /sys/class/block/"$disk"/"$disk"*; do
[ -e "$part/uevent" ] || continue
[ "$(read_uevent_property "$part/uevent" PARTNAME || true)" = dstack-volume ] && return 0
done
return 1
}

# Print the dstack-data partition. Returns 1 if there is none, 2 if there is
# more than one.
find_data_partition() {
local entry found=""
for entry in /sys/class/block/*; do
[ -e "$entry/partition" ] || continue
[ "$(read_uevent_property "$entry/uevent" PARTNAME || true)" = dstack-data ] || continue
is_verity_volume_disk "$(basename "$(dirname "$(readlink -f "$entry")")")" && continue
if [ -n "$found" ]; then
log "Error: more than one dstack-data partition: $found /dev/$(basename "$entry")"
return 2
fi
found="/dev/$(basename "$entry")"
done
[ -n "$found" ] || return 1
printf "%s" "$found"
}

resolve_block_spec() {
local spec="$1"
local device=""
Expand Down Expand Up @@ -203,8 +233,9 @@ choose_data_device() {
fi

# 2. Try to find partition with PARTLABEL=dstack-data
local data_disk
data_disk=$(resolve_block_spec "PARTLABEL=dstack-data" || true)
local data_disk rc=0
data_disk=$(find_data_partition) || rc=$?
[ "$rc" -ne 2 ] || return 1
if [ -n "$data_disk" ]; then
echo "$data_disk"
return 0
Expand Down
Loading