scripts/container-tests.sh
#!/bin/sh
# SPDX-License-Identifier: AGPL-3.0-only
# heimdall-container kernel tests (the #[ignore]d tests in
# crates/heimdall-container/tests/container.rs). Heimdall is a defensive
# sandbox; these tests run real protected containers that attack only
# themselves.
#
# They need user namespaces, Landlock, seccomp and cgroup v2 with the memory,
# pids and cpu controllers delegated (io too when the host delegates it). The
# script runs them in a privileged toolchain container (rootless podman is
# enough), moves itself out of the container's root cgroup so controllers can
# be enabled for the job cgroups, then runs
# cargo test -p nordisk-heimdall-broker --test kernel -- --ignored
# cargo test -p nordisk-heimdall-container --features youki --test container -- --ignored
# and the `heimdall profile probe-container` kernel tests (a real program
# learned inside the container, driven through its channel from outside):
# cargo test -p nordisk-heimdall-cli --test probe_container -- --ignored
# (they build a static musl test program with rustc: the image needs the
# <arch>-unknown-linux-musl target). HEIMDALL_CONTAINER_SUITES=container or
# =probe runs one suite only.
#
# Usage, from the repo root on a Linux host with podman:
# scripts/container-tests.sh
# Environment:
# HEIMDALL_TEST_IMAGE toolchain image with libseccomp-dev and busybox-static
# (default localhost/nordisk-cargo-toolchain:heim-m0)
# CARGO_TARGET_DIR host target dir to mount (default ./target)
# CARGO_HOME host cargo home to mount (optional)
# HEIMDALL_CONTAINER_TEST_ARGS extra arguments after `--` (e.g. a test name)
set -eu
cd "$(dirname "$0")/.."
if [ "${HEIMDALL_CONTAINER_INNER:-}" != 1 ]; then
img=${HEIMDALL_TEST_IMAGE:-localhost/nordisk-cargo-toolchain:heim-m0}
tgt=${CARGO_TARGET_DIR:-$PWD/target}
mkdir -p "$tgt"
extra=""
if [ -n "${CARGO_HOME:-}" ]; then extra="-v $CARGO_HOME:/ch -e CARGO_HOME=/ch"; fi
if [ -n "${CARGO_REGISTRY:-}" ]; then extra="$extra -v $CARGO_REGISTRY:/usr/local/cargo/registry"; fi
# shellcheck disable=SC2086
exec podman run --rm --privileged --cgroupns=private \
-v "$PWD":/src -v "$tgt":/tgt -e CARGO_TARGET_DIR=/tgt $extra \
-e HEIMDALL_CONTAINER_INNER=1 -e HEIMDALL_CONTAINER_DEBUG=${HEIMDALL_CONTAINER_DEBUG:-} -e HEIMDALL_CONTAINER_TEST_ARGS="${HEIMDALL_CONTAINER_TEST_ARGS:-}" \
-e HEIMDALL_CONTAINER_SUITES="${HEIMDALL_CONTAINER_SUITES:-}" \
-e CARGO_BUILD_JOBS="${CARGO_BUILD_JOBS:-8}" \
-w /src "$img" scripts/container-tests.sh
fi
# Inside the container: leave the root cgroup, enable the controllers.
cg=/sys/fs/cgroup
if [ ! -w "$cg/cgroup.subtree_control" ]; then
echo "cgroup v2 is not writable here (need --privileged and cgroup v2)" >&2
exit 2
fi
mkdir -p "$cg/init"
for p in $(cat "$cg/cgroup.procs"); do echo "$p" > "$cg/init/cgroup.procs" 2>/dev/null || true; done
for c in cpu memory pids; do
if grep -qw "$c" "$cg/cgroup.controllers"; then
echo "+$c" > "$cg/cgroup.subtree_control"
else
echo "controller $c is not delegated to this container" >&2
exit 2
fi
done
if grep -qw io "$cg/cgroup.controllers"; then
echo "+io" > "$cg/cgroup.subtree_control"
else
echo "controller io is not delegated here: jobs run without io.weight (reported)" >&2
fi
echo "controllers enabled: $(cat "$cg/cgroup.subtree_control")"
# The broker's own kernel tests (heimdall-broker, spec §4): no container needed,
# USER_NOTIF + ADDFD only.
if [ "${HEIMDALL_SKIP_BROKER_TESTS:-}" != 1 ]; then
cargo test -p nordisk-heimdall-broker --test kernel -- --ignored --test-threads=4
fi
cargo build -p nordisk-heimdall-container --features youki --bins
# The broker's selftest worker, static (musl), for the in-container broker tests.
if rustup target list --installed 2>/dev/null | grep -q '^x86_64-unknown-linux-musl$'; then
cargo build -p nordisk-heimdall-broker --bin heimdall-broker-selftest --target x86_64-unknown-linux-musl
export HEIMDALL_BROKER_SELFTEST="$CARGO_TARGET_DIR/x86_64-unknown-linux-musl/debug/heimdall-broker-selftest"
else
echo "no musl target: the in-container broker selftest jobs are skipped" >&2
fi
export HEIMDALL_CONTAINER_SHIM="$CARGO_TARGET_DIR/debug/heimdall-container-shim"
suites=${HEIMDALL_CONTAINER_SUITES:-container probe}
for s in $suites; do
case $s in
container)
# shellcheck disable=SC2086
cargo test -p nordisk-heimdall-container --features youki --test container --test workspace_kernel -- --ignored --test-threads=4 ${HEIMDALL_CONTAINER_TEST_ARGS:-} ;;
probe)
# shellcheck disable=SC2086
cargo test -p nordisk-heimdall-cli --test probe_container -- --ignored --test-threads=3 ${HEIMDALL_CONTAINER_TEST_ARGS:-} ;;
*) echo "unknown suite $s (container, probe)" >&2; exit 2 ;;
esac
done