Skip to content
Open
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
38 changes: 36 additions & 2 deletions misc/AMDSEV/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,12 +233,46 @@ Use `ovmf-metadata` to inspect the OVMF firmware's SEV metadata sections:

## Reproducible Builds

Set `SOURCE_DATE_EPOCH` for deterministic output:
`SOURCE_DATE_EPOCH` is required for deterministic builds:

```sh
SOURCE_DATE_EPOCH=$(git log -1 --format=%ct) ./misc/AMDSEV/build.sh
export SOURCE_DATE_EPOCH=$(git log -1 --format=%ct)
./misc/AMDSEV/build.sh
```

For stronger package source determinism, pin apt to a snapshot:

```sh
export APT_SNAPSHOT_URL="http://snapshot.ubuntu.com/ubuntu/20250115T000000Z/"
export APT_SNAPSHOT_SUITE="noble"
export APT_SNAPSHOT_COMPONENTS="main"
```

If building in a containerized pipeline, set the image digest for provenance tracking:

```sh
export BUILD_CONTAINER_IMAGE_DIGEST="sha256:<digest>"
```

Run a built-in reproducibility check (double build + hash compare):

```sh
export KATANA_STRICT_REPRO=1 # optional: requires vendored cargo deps for strict katana reproducibility
./misc/AMDSEV/build.sh --katana /path/to/katana --repro-check
```

You can also compare two build output directories directly:

```sh
./misc/AMDSEV/verify-build.sh --compare /path/to/build-a /path/to/build-b
```

Each build writes deterministic provenance metadata to:
- `build-info.txt`
- `materials.lock`

See [`REPRODUCIBILITY.md`](./REPRODUCIBILITY.md) for the full policy.

## Troubleshooting

### `SEV: guest firmware hashes table area is invalid (base=0x0 size=0x0)`
Expand Down
43 changes: 43 additions & 0 deletions misc/AMDSEV/REPRODUCIBILITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# AMD SEV-SNP Build Reproducibility Policy

## Scope

This policy targets byte-identical outputs for the following artifacts when built with the same:
- source tree revision
- `build-config` pins
- `SOURCE_DATE_EPOCH`
- toolchain/runtime environment

Artifacts:
- `OVMF.fd`
- `vmlinuz`
- `initrd.img`
- `katana`

## Required Inputs

- `SOURCE_DATE_EPOCH` must be explicitly set and fixed.
- `OVMF_COMMIT` must be pinned.
- Package versions and SHA256 values in `build-config` must remain pinned.
- `BUILD_CONTAINER_IMAGE_DIGEST` should be set when using a containerized CI pipeline.
- For katana, prefer passing a prebuilt pinned binary via `--katana`. If auto-building, set `KATANA_STRICT_REPRO=1` with vendored dependencies.

## Stronger Package Source Determinism

To avoid host apt source drift, set:
- `APT_SNAPSHOT_URL`
- `APT_SNAPSHOT_SUITE`
- `APT_SNAPSHOT_COMPONENTS`

If unset, build scripts use host apt sources and reproducibility guarantees are weaker.

## Validation

- Use `./misc/AMDSEV/build.sh --repro-check` to run a double-build and hash comparison.
- Use `./misc/AMDSEV/verify-build.sh --compare DIR_A DIR_B` for explicit directory comparisons.

## Provenance Files

Each build emits:
- `build-info.txt` with pinned inputs and output checksums
- `materials.lock` with immutable input and artifact hashes
10 changes: 10 additions & 0 deletions misc/AMDSEV/build-config
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,13 @@ BUSYBOX_PKG_SHA256="944b2728f53ceb3916cec2c962873c9951e612408099601751db2a0a5d81
# Kernel modules extra (Ubuntu package, for initrd SEV-SNP support)
KERNEL_MODULES_EXTRA_PKG_VERSION="6.8.0-90.91"
KERNEL_MODULES_EXTRA_PKG_SHA256="c17bd76779ce68a076dc1ef9b1669947f35f1868f6736dbd0a8a7ccacf7571f3"

# Optional apt snapshot source for stronger reproducibility guarantees.
# When set, build scripts use this source instead of host /etc/apt/sources.list.
# Example:
# APT_SNAPSHOT_URL="http://snapshot.ubuntu.com/ubuntu/20250115T000000Z/"
# APT_SNAPSHOT_SUITE="noble"
# APT_SNAPSHOT_COMPONENTS="main"
APT_SNAPSHOT_URL=""
APT_SNAPSHOT_SUITE="noble"
APT_SNAPSHOT_COMPONENTS="main"
115 changes: 93 additions & 22 deletions misc/AMDSEV/build-initrd.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,26 @@
# KERNEL_MODULES_EXTRA_PKG_VERSION REQUIRED. Exact apt package version.
# KERNEL_MODULES_EXTRA_PKG_SHA256 REQUIRED. SHA256 checksum of the modules .deb package.
#
# Optional environment (stronger package source determinism):
# APT_SNAPSHOT_URL
# APT_SNAPSHOT_SUITE
# APT_SNAPSHOT_COMPONENTS
#
# ==============================================================================

set -euo pipefail

# Environment normalization for reproducibility.
export TZ=UTC
export LANG=C.UTF-8
export LC_ALL=C.UTF-8
umask 022

REQUIRED_APPLETS=(sh mount umount sleep kill cat mkdir ln mknod ip insmod poweroff sync)
SYMLINK_APPLETS=(sh mount umount mkdir mknod switch_root ip insmod sleep kill cat ln poweroff sync)
APT_SNAPSHOT_DIR=""
APT_SOURCE_MODE="host"
declare -a APT_OPTS=()

usage() {
echo "Usage: $0 KATANA_BINARY OUTPUT_INITRD [KERNEL_VERSION]"
Expand All @@ -44,6 +58,9 @@ usage() {
echo " BUSYBOX_PKG_SHA256 SHA256 checksum of the busybox .deb package"
echo " KERNEL_MODULES_EXTRA_PKG_VERSION Exact apt package version for linux-modules-extra"
echo " KERNEL_MODULES_EXTRA_PKG_SHA256 SHA256 checksum of the linux-modules-extra .deb"
echo " APT_SNAPSHOT_URL Optional apt snapshot URL for deterministic package resolution"
echo " APT_SNAPSHOT_SUITE Snapshot suite when APT_SNAPSHOT_URL is set"
echo " APT_SNAPSHOT_COMPONENTS Snapshot components when APT_SNAPSHOT_URL is set"
echo ""
echo "EXAMPLES:"
echo " export SOURCE_DATE_EPOCH=\$(date +%s)"
Expand Down Expand Up @@ -79,6 +96,47 @@ die() {
exit 1
}

run_cmd() {
echo "$*"
"$@" || die "$*"
}

setup_apt_snapshot() {
: "${APT_SNAPSHOT_URL:?APT_SNAPSHOT_URL is required when snapshot mode is enabled}"
: "${APT_SNAPSHOT_SUITE:?APT_SNAPSHOT_SUITE is required when snapshot mode is enabled}"

local components="${APT_SNAPSHOT_COMPONENTS:-main}"
local sources_list

APT_SNAPSHOT_DIR="$(mktemp -d)"
mkdir -p "$APT_SNAPSHOT_DIR/lists/partial" "$APT_SNAPSHOT_DIR/cache/partial"

sources_list="$APT_SNAPSHOT_DIR/sources.list"
printf "deb [check-valid-until=no] %s %s %s\n" \
"$APT_SNAPSHOT_URL" "$APT_SNAPSHOT_SUITE" "$components" > "$sources_list"

APT_OPTS=(
-o "Dir::Etc::sourcelist=$sources_list"
-o "Dir::Etc::sourceparts=-"
-o "Dir::State::Lists=$APT_SNAPSHOT_DIR/lists"
-o "Dir::Cache::archives=$APT_SNAPSHOT_DIR/cache"
-o "Dir::State::status=/var/lib/dpkg/status"
-o "APT::Get::List-Cleanup=0"
)

log_info "Using apt snapshot source"
log_info " URL: $APT_SNAPSHOT_URL"
log_info " Suite: $APT_SNAPSHOT_SUITE"
log_info " Components: $components"
run_cmd apt-get "${APT_OPTS[@]}" update
APT_SOURCE_MODE="snapshot"
}

apt_download() {
local package="$1"
run_cmd apt-get "${APT_OPTS[@]}" download "$package"
}

# Show help if requested or insufficient arguments
if [[ $# -lt 2 ]] || [[ "${1:-}" == "-h" ]] || [[ "${1:-}" == "--help" ]]; then
usage
Expand All @@ -89,20 +147,17 @@ OUTPUT_INITRD="$2"
KERNEL_VERSION="${3:-${KERNEL_VERSION:?KERNEL_VERSION must be set or passed as third argument}}"
OUTPUT_DIR="$(dirname "$OUTPUT_INITRD")"

log_section "Building Initrd"
echo "Configuration:"
echo " Katana binary: $KATANA_BINARY"
echo " Output initrd: $OUTPUT_INITRD"
echo " Kernel version: $KERNEL_VERSION"
echo " SOURCE_DATE_EPOCH: ${SOURCE_DATE_EPOCH:-<not set>}"
echo ""
echo "Package versions:"
echo " busybox-static: ${BUSYBOX_PKG_VERSION:-<not set>}"
echo " linux-modules-extra: ${KERNEL_MODULES_EXTRA_PKG_VERSION:-<not set>}"

if [[ -z "${SOURCE_DATE_EPOCH:-}" ]]; then
die "SOURCE_DATE_EPOCH must be set for reproducible builds"
fi
if ! [[ "$SOURCE_DATE_EPOCH" =~ ^[0-9]+$ ]]; then
die "SOURCE_DATE_EPOCH must be an integer unix timestamp"
fi

: "${BUSYBOX_PKG_VERSION:?BUSYBOX_PKG_VERSION not set - required for reproducible builds}"
: "${BUSYBOX_PKG_SHA256:?BUSYBOX_PKG_SHA256 not set - required for reproducible builds}"
: "${KERNEL_MODULES_EXTRA_PKG_VERSION:?KERNEL_MODULES_EXTRA_PKG_VERSION not set - required for reproducible builds}"
: "${KERNEL_MODULES_EXTRA_PKG_SHA256:?KERNEL_MODULES_EXTRA_PKG_SHA256 not set - required for reproducible builds}"

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

if [[ -n "${APT_SNAPSHOT_URL:-}" ]]; then
setup_apt_snapshot
else
log_warn "APT_SNAPSHOT_URL not set, using host apt sources (weaker reproducibility)"
fi

log_section "Building Initrd"
echo "Configuration:"
echo " Katana binary: $KATANA_BINARY"
echo " Output initrd: $OUTPUT_INITRD"
echo " Kernel version: $KERNEL_VERSION"
echo " SOURCE_DATE_EPOCH: ${SOURCE_DATE_EPOCH}"
echo " APT source mode: ${APT_SOURCE_MODE}"
echo ""
echo "Package versions:"
echo " busybox-static: ${BUSYBOX_PKG_VERSION}"
echo " linux-modules-extra: ${KERNEL_MODULES_EXTRA_PKG_VERSION}"

WORK_DIR="$(mktemp -d)"
cleanup() {
local exit_code=$?
if [[ -d "$WORK_DIR" ]]; then
if [[ -n "${WORK_DIR:-}" ]] && [[ -d "$WORK_DIR" ]]; then
rm -rf "$WORK_DIR"
fi
if [[ -n "${APT_SNAPSHOT_DIR:-}" ]] && [[ -d "$APT_SNAPSHOT_DIR" ]]; then
rm -rf "$APT_SNAPSHOT_DIR"
fi
exit "$exit_code"
}
trap cleanup EXIT INT TERM
Expand All @@ -146,22 +222,16 @@ mkdir -p "$PACKAGES_DIR"

pushd "$PACKAGES_DIR" >/dev/null

: "${BUSYBOX_PKG_VERSION:?BUSYBOX_PKG_VERSION not set - required for reproducible builds}"
: "${KERNEL_MODULES_EXTRA_PKG_VERSION:?KERNEL_MODULES_EXTRA_PKG_VERSION not set - required for reproducible builds}"

log_info "Downloading busybox-static=${BUSYBOX_PKG_VERSION}"
apt-get download "busybox-static=${BUSYBOX_PKG_VERSION}"
apt_download "busybox-static=${BUSYBOX_PKG_VERSION}"

log_info "Downloading linux-modules-extra-${KERNEL_VERSION}-generic=${KERNEL_MODULES_EXTRA_PKG_VERSION}"
apt-get download "linux-modules-extra-${KERNEL_VERSION}-generic=${KERNEL_MODULES_EXTRA_PKG_VERSION}"
apt_download "linux-modules-extra-${KERNEL_VERSION}-generic=${KERNEL_MODULES_EXTRA_PKG_VERSION}"

echo ""
echo "Downloaded packages:"
ls -lh *.deb

: "${BUSYBOX_PKG_SHA256:?BUSYBOX_PKG_SHA256 not set - required for reproducible builds}"
: "${KERNEL_MODULES_EXTRA_PKG_SHA256:?KERNEL_MODULES_EXTRA_PKG_SHA256 not set - required for reproducible builds}"

log_info "Verifying busybox-static checksum"
ACTUAL_SHA256="$(sha256sum busybox-static_*.deb | awk '{print $1}')"
if [[ "$ACTUAL_SHA256" != "$BUSYBOX_PKG_SHA256" ]]; then
Expand All @@ -187,10 +257,10 @@ EXTRACTED_DIR="$WORK_DIR/extracted"
mkdir -p "$EXTRACTED_DIR"

log_info "Extracting busybox-static"
dpkg-deb -x "$PACKAGES_DIR"/busybox-static_*.deb "$EXTRACTED_DIR"
run_cmd dpkg-deb -x "$PACKAGES_DIR"/busybox-static_*.deb "$EXTRACTED_DIR"

log_info "Extracting linux-modules-extra"
dpkg-deb -x "$PACKAGES_DIR"/linux-modules-extra-*.deb "$EXTRACTED_DIR"
run_cmd dpkg-deb -x "$PACKAGES_DIR"/linux-modules-extra-*.deb "$EXTRACTED_DIR"
log_ok "Packages extracted"

# ==============================================================================
Expand Down Expand Up @@ -585,6 +655,7 @@ echo "=========================================="
echo "[OK] Initrd created successfully!"
echo "=========================================="
echo "Output file: $OUTPUT_INITRD"
echo "APT mode: $APT_SOURCE_MODE"
echo "Size: $(du -h "$OUTPUT_INITRD" | cut -f1)"
echo "SHA256: $(sha256sum "$OUTPUT_INITRD" | cut -d' ' -f1)"
echo "=========================================="
Loading