Skip to content

Commit 5008995

Browse files
committed
misc/AMDSEV: strengthen reproducible build guarantees
1 parent bb8f719 commit 5008995

File tree

8 files changed

+591
-240
lines changed

8 files changed

+591
-240
lines changed

misc/AMDSEV/README.md

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,12 +233,46 @@ Use `ovmf-metadata` to inspect the OVMF firmware's SEV metadata sections:
233233

234234
## Reproducible Builds
235235

236-
Set `SOURCE_DATE_EPOCH` for deterministic output:
236+
`SOURCE_DATE_EPOCH` is required for deterministic builds:
237237

238238
```sh
239-
SOURCE_DATE_EPOCH=$(git log -1 --format=%ct) ./misc/AMDSEV/build.sh
239+
export SOURCE_DATE_EPOCH=$(git log -1 --format=%ct)
240+
./misc/AMDSEV/build.sh
241+
```
242+
243+
For stronger package source determinism, pin apt to a snapshot:
244+
245+
```sh
246+
export APT_SNAPSHOT_URL="http://snapshot.ubuntu.com/ubuntu/20250115T000000Z/"
247+
export APT_SNAPSHOT_SUITE="noble"
248+
export APT_SNAPSHOT_COMPONENTS="main"
240249
```
241250

251+
If building in a containerized pipeline, set the image digest for provenance tracking:
252+
253+
```sh
254+
export BUILD_CONTAINER_IMAGE_DIGEST="sha256:<digest>"
255+
```
256+
257+
Run a built-in reproducibility check (double build + hash compare):
258+
259+
```sh
260+
export KATANA_STRICT_REPRO=1 # optional: requires vendored cargo deps for strict katana reproducibility
261+
./misc/AMDSEV/build.sh --katana /path/to/katana --repro-check
262+
```
263+
264+
You can also compare two build output directories directly:
265+
266+
```sh
267+
./misc/AMDSEV/verify-build.sh --compare /path/to/build-a /path/to/build-b
268+
```
269+
270+
Each build writes deterministic provenance metadata to:
271+
- `build-info.txt`
272+
- `materials.lock`
273+
274+
See [`REPRODUCIBILITY.md`](./REPRODUCIBILITY.md) for the full policy.
275+
242276
## Troubleshooting
243277

244278
### `SEV: guest firmware hashes table area is invalid (base=0x0 size=0x0)`

misc/AMDSEV/REPRODUCIBILITY.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# AMD SEV-SNP Build Reproducibility Policy
2+
3+
## Scope
4+
5+
This policy targets byte-identical outputs for the following artifacts when built with the same:
6+
- source tree revision
7+
- `build-config` pins
8+
- `SOURCE_DATE_EPOCH`
9+
- toolchain/runtime environment
10+
11+
Artifacts:
12+
- `OVMF.fd`
13+
- `vmlinuz`
14+
- `initrd.img`
15+
- `katana`
16+
17+
## Required Inputs
18+
19+
- `SOURCE_DATE_EPOCH` must be explicitly set and fixed.
20+
- `OVMF_COMMIT` must be pinned.
21+
- Package versions and SHA256 values in `build-config` must remain pinned.
22+
- `BUILD_CONTAINER_IMAGE_DIGEST` should be set when using a containerized CI pipeline.
23+
- For katana, prefer passing a prebuilt pinned binary via `--katana`. If auto-building, set `KATANA_STRICT_REPRO=1` with vendored dependencies.
24+
25+
## Stronger Package Source Determinism
26+
27+
To avoid host apt source drift, set:
28+
- `APT_SNAPSHOT_URL`
29+
- `APT_SNAPSHOT_SUITE`
30+
- `APT_SNAPSHOT_COMPONENTS`
31+
32+
If unset, build scripts use host apt sources and reproducibility guarantees are weaker.
33+
34+
## Validation
35+
36+
- Use `./misc/AMDSEV/build.sh --repro-check` to run a double-build and hash comparison.
37+
- Use `./misc/AMDSEV/verify-build.sh --compare DIR_A DIR_B` for explicit directory comparisons.
38+
39+
## Provenance Files
40+
41+
Each build emits:
42+
- `build-info.txt` with pinned inputs and output checksums
43+
- `materials.lock` with immutable input and artifact hashes

misc/AMDSEV/build-config

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,13 @@ BUSYBOX_PKG_SHA256="944b2728f53ceb3916cec2c962873c9951e612408099601751db2a0a5d81
2020
# Kernel modules extra (Ubuntu package, for initrd SEV-SNP support)
2121
KERNEL_MODULES_EXTRA_PKG_VERSION="6.8.0-90.91"
2222
KERNEL_MODULES_EXTRA_PKG_SHA256="c17bd76779ce68a076dc1ef9b1669947f35f1868f6736dbd0a8a7ccacf7571f3"
23+
24+
# Optional apt snapshot source for stronger reproducibility guarantees.
25+
# When set, build scripts use this source instead of host /etc/apt/sources.list.
26+
# Example:
27+
# APT_SNAPSHOT_URL="http://snapshot.ubuntu.com/ubuntu/20250115T000000Z/"
28+
# APT_SNAPSHOT_SUITE="noble"
29+
# APT_SNAPSHOT_COMPONENTS="main"
30+
APT_SNAPSHOT_URL=""
31+
APT_SNAPSHOT_SUITE="noble"
32+
APT_SNAPSHOT_COMPONENTS="main"

misc/AMDSEV/build-initrd.sh

Lines changed: 93 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,26 @@
2020
# KERNEL_MODULES_EXTRA_PKG_VERSION REQUIRED. Exact apt package version.
2121
# KERNEL_MODULES_EXTRA_PKG_SHA256 REQUIRED. SHA256 checksum of the modules .deb package.
2222
#
23+
# Optional environment (stronger package source determinism):
24+
# APT_SNAPSHOT_URL
25+
# APT_SNAPSHOT_SUITE
26+
# APT_SNAPSHOT_COMPONENTS
27+
#
2328
# ==============================================================================
2429

2530
set -euo pipefail
2631

32+
# Environment normalization for reproducibility.
33+
export TZ=UTC
34+
export LANG=C.UTF-8
35+
export LC_ALL=C.UTF-8
36+
umask 022
37+
2738
REQUIRED_APPLETS=(sh mount umount sleep kill cat mkdir ln mknod ip insmod poweroff sync)
2839
SYMLINK_APPLETS=(sh mount umount mkdir mknod switch_root ip insmod sleep kill cat ln poweroff sync)
40+
APT_SNAPSHOT_DIR=""
41+
APT_SOURCE_MODE="host"
42+
declare -a APT_OPTS=()
2943

3044
usage() {
3145
echo "Usage: $0 KATANA_BINARY OUTPUT_INITRD [KERNEL_VERSION]"
@@ -44,6 +58,9 @@ usage() {
4458
echo " BUSYBOX_PKG_SHA256 SHA256 checksum of the busybox .deb package"
4559
echo " KERNEL_MODULES_EXTRA_PKG_VERSION Exact apt package version for linux-modules-extra"
4660
echo " KERNEL_MODULES_EXTRA_PKG_SHA256 SHA256 checksum of the linux-modules-extra .deb"
61+
echo " APT_SNAPSHOT_URL Optional apt snapshot URL for deterministic package resolution"
62+
echo " APT_SNAPSHOT_SUITE Snapshot suite when APT_SNAPSHOT_URL is set"
63+
echo " APT_SNAPSHOT_COMPONENTS Snapshot components when APT_SNAPSHOT_URL is set"
4764
echo ""
4865
echo "EXAMPLES:"
4966
echo " export SOURCE_DATE_EPOCH=\$(date +%s)"
@@ -79,6 +96,47 @@ die() {
7996
exit 1
8097
}
8198

99+
run_cmd() {
100+
echo "$*"
101+
"$@" || die "$*"
102+
}
103+
104+
setup_apt_snapshot() {
105+
: "${APT_SNAPSHOT_URL:?APT_SNAPSHOT_URL is required when snapshot mode is enabled}"
106+
: "${APT_SNAPSHOT_SUITE:?APT_SNAPSHOT_SUITE is required when snapshot mode is enabled}"
107+
108+
local components="${APT_SNAPSHOT_COMPONENTS:-main}"
109+
local sources_list
110+
111+
APT_SNAPSHOT_DIR="$(mktemp -d)"
112+
mkdir -p "$APT_SNAPSHOT_DIR/lists/partial" "$APT_SNAPSHOT_DIR/cache/partial"
113+
114+
sources_list="$APT_SNAPSHOT_DIR/sources.list"
115+
printf "deb [check-valid-until=no] %s %s %s\n" \
116+
"$APT_SNAPSHOT_URL" "$APT_SNAPSHOT_SUITE" "$components" > "$sources_list"
117+
118+
APT_OPTS=(
119+
-o "Dir::Etc::sourcelist=$sources_list"
120+
-o "Dir::Etc::sourceparts=-"
121+
-o "Dir::State::Lists=$APT_SNAPSHOT_DIR/lists"
122+
-o "Dir::Cache::archives=$APT_SNAPSHOT_DIR/cache"
123+
-o "Dir::State::status=/var/lib/dpkg/status"
124+
-o "APT::Get::List-Cleanup=0"
125+
)
126+
127+
log_info "Using apt snapshot source"
128+
log_info " URL: $APT_SNAPSHOT_URL"
129+
log_info " Suite: $APT_SNAPSHOT_SUITE"
130+
log_info " Components: $components"
131+
run_cmd apt-get "${APT_OPTS[@]}" update
132+
APT_SOURCE_MODE="snapshot"
133+
}
134+
135+
apt_download() {
136+
local package="$1"
137+
run_cmd apt-get "${APT_OPTS[@]}" download "$package"
138+
}
139+
82140
# Show help if requested or insufficient arguments
83141
if [[ $# -lt 2 ]] || [[ "${1:-}" == "-h" ]] || [[ "${1:-}" == "--help" ]]; then
84142
usage
@@ -89,20 +147,17 @@ OUTPUT_INITRD="$2"
89147
KERNEL_VERSION="${3:-${KERNEL_VERSION:?KERNEL_VERSION must be set or passed as third argument}}"
90148
OUTPUT_DIR="$(dirname "$OUTPUT_INITRD")"
91149

92-
log_section "Building Initrd"
93-
echo "Configuration:"
94-
echo " Katana binary: $KATANA_BINARY"
95-
echo " Output initrd: $OUTPUT_INITRD"
96-
echo " Kernel version: $KERNEL_VERSION"
97-
echo " SOURCE_DATE_EPOCH: ${SOURCE_DATE_EPOCH:-<not set>}"
98-
echo ""
99-
echo "Package versions:"
100-
echo " busybox-static: ${BUSYBOX_PKG_VERSION:-<not set>}"
101-
echo " linux-modules-extra: ${KERNEL_MODULES_EXTRA_PKG_VERSION:-<not set>}"
102-
103150
if [[ -z "${SOURCE_DATE_EPOCH:-}" ]]; then
104151
die "SOURCE_DATE_EPOCH must be set for reproducible builds"
105152
fi
153+
if ! [[ "$SOURCE_DATE_EPOCH" =~ ^[0-9]+$ ]]; then
154+
die "SOURCE_DATE_EPOCH must be an integer unix timestamp"
155+
fi
156+
157+
: "${BUSYBOX_PKG_VERSION:?BUSYBOX_PKG_VERSION not set - required for reproducible builds}"
158+
: "${BUSYBOX_PKG_SHA256:?BUSYBOX_PKG_SHA256 not set - required for reproducible builds}"
159+
: "${KERNEL_MODULES_EXTRA_PKG_VERSION:?KERNEL_MODULES_EXTRA_PKG_VERSION not set - required for reproducible builds}"
160+
: "${KERNEL_MODULES_EXTRA_PKG_SHA256:?KERNEL_MODULES_EXTRA_PKG_SHA256 not set - required for reproducible builds}"
106161

107162
if [[ ! -f "$KATANA_BINARY" ]]; then
108163
die "Katana binary not found: $KATANA_BINARY"
@@ -124,12 +179,33 @@ for tool in "${REQUIRED_TOOLS[@]}"; do
124179
done
125180
log_ok "Preflight validation complete"
126181

182+
if [[ -n "${APT_SNAPSHOT_URL:-}" ]]; then
183+
setup_apt_snapshot
184+
else
185+
log_warn "APT_SNAPSHOT_URL not set, using host apt sources (weaker reproducibility)"
186+
fi
187+
188+
log_section "Building Initrd"
189+
echo "Configuration:"
190+
echo " Katana binary: $KATANA_BINARY"
191+
echo " Output initrd: $OUTPUT_INITRD"
192+
echo " Kernel version: $KERNEL_VERSION"
193+
echo " SOURCE_DATE_EPOCH: ${SOURCE_DATE_EPOCH}"
194+
echo " APT source mode: ${APT_SOURCE_MODE}"
195+
echo ""
196+
echo "Package versions:"
197+
echo " busybox-static: ${BUSYBOX_PKG_VERSION}"
198+
echo " linux-modules-extra: ${KERNEL_MODULES_EXTRA_PKG_VERSION}"
199+
127200
WORK_DIR="$(mktemp -d)"
128201
cleanup() {
129202
local exit_code=$?
130-
if [[ -d "$WORK_DIR" ]]; then
203+
if [[ -n "${WORK_DIR:-}" ]] && [[ -d "$WORK_DIR" ]]; then
131204
rm -rf "$WORK_DIR"
132205
fi
206+
if [[ -n "${APT_SNAPSHOT_DIR:-}" ]] && [[ -d "$APT_SNAPSHOT_DIR" ]]; then
207+
rm -rf "$APT_SNAPSHOT_DIR"
208+
fi
133209
exit "$exit_code"
134210
}
135211
trap cleanup EXIT INT TERM
@@ -146,22 +222,16 @@ mkdir -p "$PACKAGES_DIR"
146222

147223
pushd "$PACKAGES_DIR" >/dev/null
148224

149-
: "${BUSYBOX_PKG_VERSION:?BUSYBOX_PKG_VERSION not set - required for reproducible builds}"
150-
: "${KERNEL_MODULES_EXTRA_PKG_VERSION:?KERNEL_MODULES_EXTRA_PKG_VERSION not set - required for reproducible builds}"
151-
152225
log_info "Downloading busybox-static=${BUSYBOX_PKG_VERSION}"
153-
apt-get download "busybox-static=${BUSYBOX_PKG_VERSION}"
226+
apt_download "busybox-static=${BUSYBOX_PKG_VERSION}"
154227

155228
log_info "Downloading linux-modules-extra-${KERNEL_VERSION}-generic=${KERNEL_MODULES_EXTRA_PKG_VERSION}"
156-
apt-get download "linux-modules-extra-${KERNEL_VERSION}-generic=${KERNEL_MODULES_EXTRA_PKG_VERSION}"
229+
apt_download "linux-modules-extra-${KERNEL_VERSION}-generic=${KERNEL_MODULES_EXTRA_PKG_VERSION}"
157230

158231
echo ""
159232
echo "Downloaded packages:"
160233
ls -lh *.deb
161234

162-
: "${BUSYBOX_PKG_SHA256:?BUSYBOX_PKG_SHA256 not set - required for reproducible builds}"
163-
: "${KERNEL_MODULES_EXTRA_PKG_SHA256:?KERNEL_MODULES_EXTRA_PKG_SHA256 not set - required for reproducible builds}"
164-
165235
log_info "Verifying busybox-static checksum"
166236
ACTUAL_SHA256="$(sha256sum busybox-static_*.deb | awk '{print $1}')"
167237
if [[ "$ACTUAL_SHA256" != "$BUSYBOX_PKG_SHA256" ]]; then
@@ -187,10 +257,10 @@ EXTRACTED_DIR="$WORK_DIR/extracted"
187257
mkdir -p "$EXTRACTED_DIR"
188258

189259
log_info "Extracting busybox-static"
190-
dpkg-deb -x "$PACKAGES_DIR"/busybox-static_*.deb "$EXTRACTED_DIR"
260+
run_cmd dpkg-deb -x "$PACKAGES_DIR"/busybox-static_*.deb "$EXTRACTED_DIR"
191261

192262
log_info "Extracting linux-modules-extra"
193-
dpkg-deb -x "$PACKAGES_DIR"/linux-modules-extra-*.deb "$EXTRACTED_DIR"
263+
run_cmd dpkg-deb -x "$PACKAGES_DIR"/linux-modules-extra-*.deb "$EXTRACTED_DIR"
194264
log_ok "Packages extracted"
195265

196266
# ==============================================================================
@@ -585,6 +655,7 @@ echo "=========================================="
585655
echo "[OK] Initrd created successfully!"
586656
echo "=========================================="
587657
echo "Output file: $OUTPUT_INITRD"
658+
echo "APT mode: $APT_SOURCE_MODE"
588659
echo "Size: $(du -h "$OUTPUT_INITRD" | cut -f1)"
589660
echo "SHA256: $(sha256sum "$OUTPUT_INITRD" | cut -d' ' -f1)"
590661
echo "=========================================="

0 commit comments

Comments
 (0)