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
36 changes: 28 additions & 8 deletions .github/workflows/run-nvx-microvm-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -341,12 +341,14 @@ jobs:
)
scratch="build/ubuntu-smoke-${{ inputs.backend }}.ext4"
cp --reflink=auto build/ubuntu-smoke-scratch.ext4 "${scratch}"
# The probe checks the security profile.
# A run executes the probe once, as nvx-init runs each execution,
# and the probe checks the security profile of that execution.
nvx-rs/target/release/nvx-rs sandbox \
--hypervisor "${{ inputs.backend }}" \
--layer "distro,build/ubuntu-distro.erofs,${uuid}" \
--scratch "${scratch}" \
--entrypoint /sbin/nvx-sandbox-smoke \
--arg init \
--workload-user 65534:65534 \
--memory-mib 256

Expand Down Expand Up @@ -377,6 +379,7 @@ jobs:
--mount "/workspace,${share},rw" \
--mount-deny nvx-denied \
--entrypoint /sbin/nvx-sandbox-smoke \
--arg init \
--arg /workspace \
--arg rw \
--workload-user 65534:65534 \
Expand All @@ -403,6 +406,7 @@ jobs:
--mount "/opt/hostedtoolcache,${share},ro" \
--mount-deny nvx-denied \
--entrypoint /sbin/nvx-sandbox-smoke \
--arg init \
--arg /opt/hostedtoolcache \
--arg ro \
--workload-user 65534:65534 \
Expand Down Expand Up @@ -511,18 +515,30 @@ jobs:
# group. With --mount-owner caller, every share operation must fail
# with EPERM instead of running as the runner. The OpenVMM unit tests
# cover the identity of each request, including guest root squash.
# A run maps its shares as a start does: its guest agent reaches the
# share as guest root, which the mode squashes to the share's owner,
# before any workload runs, so that request fails with EPERM, and the
# run fails without running its workload.
cp --reflink=auto build/ubuntu-smoke-scratch.ext4 "${scratch}"
nvx-rs/target/release/nvx-rs sandbox \
errors=$(mktemp)
if nvx-rs/target/release/nvx-rs sandbox \
--hypervisor "${{ inputs.backend }}" \
--layer "distro,build/ubuntu-distro.erofs,${uuid}" \
--scratch "${scratch}" \
--mount "/workspace,${share},rw" \
--mount-owner caller \
--entrypoint /sbin/nvx-sandbox-smoke \
--arg init \
--arg /workspace \
--arg eperm \
--workload-user 65534:65534 \
--memory-mib 256
--memory-mib 256 2>"${errors}"; then
echo "the caller-owned run reached its share as the runner" >&2
exit 1
fi
cat "${errors}" >&2
grep -q 'could not mount a mapped host path (error 1)' "${errors}"
rm -f "${errors}"
test "$(ls -A "${share}")" = nvx-host-marker
# A managed sandbox persists the ownership mode and applies it on
# start. Its guest agent reaches the share as guest root, which the
Expand Down Expand Up @@ -645,7 +661,7 @@ jobs:
--layer "distro,build/ubuntu-distro.erofs,${uuid}" \
--scratch "${scratch}" \
"${share_options[@]}" \
"${smoke_arguments[@]}" \
--arg init "${smoke_arguments[@]}" \
--workload-user 65534:65534 \
--memory-mib 256
check_shares
Expand Down Expand Up @@ -770,7 +786,7 @@ jobs:
--layer "distro,build/ubuntu-distro.erofs,${uuid}" \
--scratch "${scratch}" \
"${share_options[@]}" \
"${smoke_arguments[@]}" \
--arg init "${smoke_arguments[@]}" \
--workload-user 65534:65534 \
--memory-mib 256
check_share
Expand Down Expand Up @@ -844,12 +860,14 @@ jobs:
ConvertFrom-Json
$scratch = "build\ubuntu-smoke-${{ inputs.backend }}.ext4"
Copy-Item build\ubuntu-smoke-scratch.ext4 $scratch
# The probe checks the security profile.
# A run executes the probe once, as nvx-init runs each execution,
# and the probe checks the security profile of that execution.
nvx-rs\target\release\nvx-rs.exe sandbox `
--hypervisor "${{ inputs.backend }}" `
--layer "distro,build\ubuntu-distro.erofs,$($manifest.uuid)" `
--scratch $scratch `
--entrypoint /sbin/nvx-sandbox-smoke `
--arg init `
--workload-user 65534:65534 `
--memory-mib 256

Expand Down Expand Up @@ -878,6 +896,7 @@ jobs:
--mount "/workspace,$share,rw" `
--mount-deny nvx-denied `
--entrypoint /sbin/nvx-sandbox-smoke `
--arg init `
--arg /workspace `
--arg rw `
--workload-user 65534:65534 `
Expand Down Expand Up @@ -921,6 +940,7 @@ jobs:
--mount "/opt/hostedtoolcache,$share,ro" `
--mount-deny nvx-denied `
--entrypoint /sbin/nvx-sandbox-smoke `
--arg init `
--arg /opt/hostedtoolcache `
--arg ro `
--workload-user 65534:65534 `
Expand Down Expand Up @@ -1101,7 +1121,7 @@ jobs:
if ([IO.File]::ReadAllText((Join-Path $files "results\other.txt")) -ne "other`n") { throw "guest changed a file beside a shared file" }
}
Initialize-Shares
Invoke-Nvx sandbox --hypervisor "${{ inputs.backend }}" --layer $layer --scratch $scratch @shareOptions @smokeArguments --workload-user 65534:65534 --memory-mib 256
Invoke-Nvx sandbox --hypervisor "${{ inputs.backend }}" --layer $layer --scratch $scratch @shareOptions --arg init @smokeArguments --workload-user 65534:65534 --memory-mib 256
Test-Shares
# A managed sandbox persists every share and reattaches them on start.
Initialize-Shares
Expand Down Expand Up @@ -1202,7 +1222,7 @@ jobs:
}
}
Initialize-Share
Invoke-Nvx sandbox --hypervisor "${{ inputs.backend }}" --layer $layer --scratch $scratch @shareOptions @smokeArguments --workload-user 65534:65534 --memory-mib 256
Invoke-Nvx sandbox --hypervisor "${{ inputs.backend }}" --layer $layer --scratch $scratch @shareOptions --arg init @smokeArguments --workload-user 65534:65534 --memory-mib 256
Test-Share
# A managed sandbox persists the access policy and reapplies it on
# start.
Expand Down
35 changes: 18 additions & 17 deletions doc/ci.md
Original file line number Diff line number Diff line change
Expand Up @@ -537,13 +537,13 @@ that read it as a workflow artifact of its own, under its build filenames (see
[Guest artifact handoff](#guest-artifact-handoff)). Each
backend also boots the Ubuntu initramfs and runs
`/sbin/nvx-sandbox-smoke` from the Ubuntu EROFS layer as UID/GID 65534 over a
fresh ext4 scratch copy. The probe verifies the
[sandbox security profile](run.md#experimental-single-workload-sandbox): the
fixed identity, empty capability sets and `no_new_privs`, private mount, PID,
and UTS namespaces, the private device view and read-only sysfs, the
container cgroup, and the overlay root over read-only image layers with its
upper directory on scratch. The live-share runs below repeat the profile
checks. Each
fresh ext4 scratch copy, as the one workload of an `nvx-rs sandbox run`, which
nvx-init executes. The probe verifies the
[sandbox security profile](run.md#experimental-single-workload-sandbox) of
such an execution: the fixed identity, empty capability sets and
`no_new_privs`, the host name, the device view and read-only sysfs, and the
overlay root over read-only image layers with its upper directory on scratch.
The live-share runs below repeat the profile checks. Each
backend also runs the public `managed-exec-config`, `sandbox-lifecycle`,
`sandbox-proxy-only`, and `sandbox-ram-upper` scenarios of `test-microvm`,
which drive `nvx-rs sandbox run`, `provision`, `start`,
Expand Down Expand Up @@ -587,7 +587,7 @@ read-write file but neither remove nor rename either one. The host requires
the guest's writes in the workspace and the read-write file, an unchanged tool
cache, read-only file, and denied files, and unchanged files beside the shared
files, both for a
one-shot run and for a managed sandbox whose format-6 configuration must
run and for a managed sandbox whose format-6 configuration must
persist every share and its kind and whose `stop` must leave a cleanly
unmounted scratch
filesystem. Each backend then attaches a read-write `/workspace` share whose
Expand All @@ -599,8 +599,8 @@ writes to succeed only in `nvx-writable` and to fail with `EROFS` everywhere
else, a hard link of a read-only file into `nvx-writable` to fail, and
`nvx-denied` to list only `nvx-allowed`, whose file stays readable while
`nvx-denied/secret` stays hidden. The host requires the guest's writes in
`nvx-writable` and no other change to the share, both for a one-shot run and
for a managed sandbox whose format-5 configuration must persist the denied,
`nvx-writable` and no other change to the share, both for a run and for a
managed sandbox whose format-5 configuration must persist the denied,
allowed, and writable paths and whose `stop` must leave a cleanly unmounted
scratch filesystem. The default `filesystem-policy` scenario of `test-microvm`
covers the same policy as guest root, whose permission checks mode bits never
Expand All @@ -612,13 +612,14 @@ writable handle open across the capture. On Linux, a
world-writable share then runs with `--mount-owner caller`. The runners grant
OpenVMM neither `CAP_SETUID` nor `CAP_SETGID`, so it can neither assume the
65534 workload identity nor drop the backend group through which it opens
`/dev/kvm` or `/dev/mshv`. The smoke script's `eperm` mode therefore
requires reading and listing the share to fail with `EPERM` and writes to
fail, and the host requires the share to be unchanged, both for a one-shot
run and for a managed sandbox whose configuration must persist the mode. The `filesystem-owner` scenario of
`test-microvm` likewise requires guest root and a foreign guest identity to
fail with `EPERM` on the runners, and a root-owned export to be rejected
before boot; on Windows, `--mount-owner caller` must be rejected before boot.
`/dev/kvm` or `/dev/mshv`. The guest agent of a run, and of a managed
sandbox whose configuration must persist the mode, therefore fails to map the
share with `EPERM` before any workload runs, which fails the run and the
start, and the host requires the share to be unchanged. The `filesystem-owner`
scenario of `test-microvm` likewise requires guest root and a foreign guest
identity to fail with `EPERM` on the runners, and a root-owned export to be
rejected before boot; on Windows, `--mount-owner caller` must be rejected
before boot.
OpenVMM's unit tests, which its own CI runs (see [OpenVMM CI](#openvmm-ci)),
check the host identity that each request runs as,
including guest root squashed to an export owner other than OpenVMM. Where
Expand Down
Loading
Loading