chore: import upstream snapshot with attribution
Build containerization / Verify commit signatures (push) Has been skipped
Build containerization / containerization (push) Successful in 0s
Linux build / Linux compile check (push) Has been cancelled
Linux build / Determine Swift version (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 12:25:30 +08:00
commit 680845cb1c
445 changed files with 103779 additions and 0 deletions
+243
View File
@@ -0,0 +1,243 @@
#!/bin/bash
# Copyright © 2026 Apple Inc. and the Containerization project authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Builds the x86_64 deployment tarball.
#
# Runs INSIDE the aarch64 Linux dev container (invoked by
# `make dist-x86_64` via the linux_run macro). Cross-compiles all four
# host-side binaries — cctl, vminitd, cloud-hypervisor, virtiofsd —
# to x86_64-linux-musl, packs an initfs.ext4 with the x86_64 guest
# binaries inside, and emits bin/containerization-x86_64-<sha>.tar.gz.
#
# See docs/x86_64-build.md for full documentation: prerequisites,
# pipeline stages, toolchain rationale, and troubleshooting.
#
# Force-rebuild env vars (default = skip stages whose outputs are
# up-to-date):
# REBUILD_VMINITD=1 vminitd + vmexec
# REBUILD_INITFS=1 initfs.ext4 (and the native aarch64 cctl packer)
# REBUILD_CH=1 cloud-hypervisor
# REBUILD_VIRTIOFSD=1 virtiofsd
# cctl x86 cross always rebuilds (Swift incremental handles no-ops).
set -euo pipefail
cd /workspace
GIT_SHA=$(git rev-parse --short HEAD 2>/dev/null || echo unknown)
DIST_NAME="containerization-x86_64-${GIT_SHA}"
DIST_DIR="bin/dist-x86_64"
STAGE="${DIST_DIR}/${DIST_NAME}"
TGZ="bin/${DIST_NAME}.tar.gz"
CROSS_PREFIX=/opt/cross-x86_64-musl
GNU_PREFIX=/opt/cross-x86_64-gnu
PATCH=/workspace/scripts/patches/virtiofsd-skip-cap-drop-with-sandbox-none.patch
# Cargo cross env for the musl stages (cctl, vminitd, cloud-hypervisor).
# CC/CXX/AR are used by cc-rs (Rust build scripts that compile C, e.g.
# zstd-sys, libseccomp-sys, capng) — points them at the Zig-backed
# wrappers. Linker is intentionally NOT set here: cargo-zigbuild
# installs its own linker wrapper that strips Rust's self-contained
# musl crt files (which would otherwise collide with Zig's musl crt).
# Setting CARGO_TARGET_*_LINKER ourselves would override that and
# cause duplicate-symbol link errors.
# pkg-config (used by libseccomp-sys and libcap-ng's capng-sys) points
# at the static-musl prefix, not the aarch64 host.
# PKG_CONFIG_ALL_STATIC=1 makes pkg-config-rs emit
# `rustc-link-lib=static=...` for resolved libs — required because
# the C libs at $CROSS_PREFIX are static-only (.a, no .so), so the
# default dynamic link would fail to find the .so.
#
# virtiofsd has its own glibc-dynamic env block below; it overrides
# PKG_CONFIG_LIBDIR / SYSROOT_DIR in a subshell so the musl values
# stay correct for cloud-hypervisor.
. /root/.cargo/env
export CC_x86_64_unknown_linux_musl=x86_64-linux-musl-gcc
export CXX_x86_64_unknown_linux_musl=x86_64-linux-musl-g++
export AR_x86_64_unknown_linux_musl=x86_64-linux-musl-ar
export PKG_CONFIG_LIBDIR="${CROSS_PREFIX}/lib/pkgconfig"
export PKG_CONFIG_SYSROOT_DIR="${CROSS_PREFIX}"
export PKG_CONFIG_ALLOW_CROSS=1
# Add the static-musl cross prefix to rustc's native library search
# path so the linker finds the libseccomp.so / libcap-ng.so linker
# scripts that build-musl-x86_64-deps.sh installs alongside the .a
# files. The scripts redirect resolution to the static archives.
export CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_RUSTFLAGS="-L native=${CROSS_PREFIX}/lib"
# Pre-flight checks
[ -f .local/cloud-hypervisor/Cargo.toml ] || {
echo "ERROR: missing .local/cloud-hypervisor source checkout." >&2
echo " git clone -b v52.0 https://github.com/cloud-hypervisor/cloud-hypervisor .local/cloud-hypervisor" >&2
exit 1
}
[ -f .local/virtiofsd/Cargo.toml ] || {
echo "ERROR: missing .local/virtiofsd source checkout." >&2
echo " git clone https://gitlab.com/virtio-fs/virtiofsd .local/virtiofsd" >&2
exit 1
}
# Kernel candidates (prefer the compressed bzImage produced by
# `make -C kernel TARGET_ARCH=x86_64`, fall back to an uncompressed
# vmlinux). The kernel is required — a tarball without one isn't
# usable, so fail hard rather than silently producing one.
KERNEL_SRC=
for candidate in kernel/vmlinuz-x86_64 kernel/vmlinux-x86_64; do
if [ -f "$candidate" ]; then
if file "$candidate" | grep -qE 'x86 boot|x86-64'; then
KERNEL_SRC=$candidate
break
else
echo "ERROR: $candidate exists but is not x86_64." >&2
file "$candidate" >&2
exit 1
fi
fi
done
if [ -z "${KERNEL_SRC}" ]; then
echo "ERROR: no x86_64 kernel found at kernel/vmlinuz-x86_64 or kernel/vmlinux-x86_64." >&2
echo " build one with 'make -C kernel TARGET_ARCH=x86_64'." >&2
exit 1
fi
mkdir -p "${DIST_DIR}"
# Decide which steps need to run before doing any work, so log messages
# match what's actually happening.
NEED_VMINITD=1
if [ "${REBUILD_VMINITD:-0}" != "1" ] \
&& [ -x "${DIST_DIR}/vminitd" ] && [ -x "${DIST_DIR}/vmexec" ] \
&& [ -z "$(find vminitd/Sources vminitd/Package.swift Sources/Containerization/SandboxContext \
-newer "${DIST_DIR}/vminitd" -print -quit 2>/dev/null)" ] \
&& [ -z "$(find vminitd/Sources vminitd/Package.swift Sources/Containerization/SandboxContext \
-newer "${DIST_DIR}/vmexec" -print -quit 2>/dev/null)" ]; then
NEED_VMINITD=0
fi
NEED_INITFS=1
if [ "${REBUILD_INITFS:-0}" != "1" ] \
&& [ "${NEED_VMINITD}" = "0" ] \
&& [ -f "${DIST_DIR}/initfs.ext4" ] \
&& [ "${DIST_DIR}/initfs.ext4" -nt "${DIST_DIR}/vminitd" ] \
&& [ "${DIST_DIR}/initfs.ext4" -nt "${DIST_DIR}/vmexec" ]; then
NEED_INITFS=0
fi
NEED_CH=1
if [ "${REBUILD_CH:-0}" != "1" ] && [ -x "${DIST_DIR}/cloud-hypervisor" ]; then
NEED_CH=0
fi
NEED_VIRTIOFSD=1
if [ "${REBUILD_VIRTIOFSD:-0}" != "1" ] && [ -x "${DIST_DIR}/virtiofsd" ]; then
NEED_VIRTIOFSD=0
fi
echo "==> Cross-compiling cctl to x86_64-linux-musl"
swift build -c release \
--swift-sdk x86_64-swift-linux-musl \
--product cctl \
-Xswiftc -warnings-as-errors \
-Xlinker -L"${CROSS_PREFIX}/lib" \
--disable-automatic-resolution
CCTL_X86_64_BIN="$(swift build -c release --swift-sdk x86_64-swift-linux-musl --show-bin-path)/cctl"
install -m 755 "${CCTL_X86_64_BIN}" "${DIST_DIR}/cctl"
if [ "${NEED_VMINITD}" = "1" ]; then
echo "==> Cross-compiling vminitd + vmexec to x86_64-linux-musl"
make -C vminitd \
LIBC=musl \
MUSL_ARCH=x86_64 \
BUILD_CONFIGURATION=release \
INSTALL_DIR="$(pwd)/${DIST_DIR}"
else
echo "==> Reusing staged vminitd + vmexec (sources unchanged; set REBUILD_VMINITD=1 to force)"
fi
if [ "${NEED_CH}" = "1" ]; then
echo "==> Cross-compiling cloud-hypervisor to x86_64-unknown-linux-musl"
(
cd .local/cloud-hypervisor
cargo zigbuild --release --target x86_64-unknown-linux-musl --bin cloud-hypervisor
)
install -m 755 \
".local/cloud-hypervisor/target/x86_64-unknown-linux-musl/release/cloud-hypervisor" \
"${DIST_DIR}/cloud-hypervisor"
else
echo "==> Reusing staged cloud-hypervisor (set REBUILD_CH=1 to force)"
fi
if [ "${NEED_VIRTIOFSD}" = "1" ]; then
echo "==> Cross-compiling virtiofsd to x86_64-unknown-linux-gnu.2.35 (glibc-dynamic, with cap-drop patch)"
# virtiofsd ships glibc-dynamic: the deployment host provides
# libseccomp.so.2 and libcap-ng.so.0 at runtime. Subshell scopes
# the gnu env so it doesn't bleed into other stages.
(
export CC_x86_64_unknown_linux_gnu=x86_64-linux-gnu-gcc
export CXX_x86_64_unknown_linux_gnu=x86_64-linux-gnu-g++
export AR_x86_64_unknown_linux_gnu=x86_64-linux-gnu-ar
export PKG_CONFIG_LIBDIR="${GNU_PREFIX}/lib/pkgconfig"
export PKG_CONFIG_SYSROOT_DIR="${GNU_PREFIX}"
export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUSTFLAGS="-L native=${GNU_PREFIX}/lib"
cd .local/virtiofsd
if git apply --check "${PATCH}" 2>/dev/null; then
git apply "${PATCH}"
echo "applied virtiofsd cap-drop patch"
elif git apply --reverse --check "${PATCH}" 2>/dev/null; then
echo "virtiofsd cap-drop patch already applied"
else
echo "ERROR: virtiofsd cap-drop patch does not apply cleanly" >&2
exit 1
fi
cargo zigbuild --release --target x86_64-unknown-linux-gnu.2.35
)
install -m 755 \
".local/virtiofsd/target/x86_64-unknown-linux-gnu/release/virtiofsd" \
"${DIST_DIR}/virtiofsd"
else
echo "==> Reusing staged virtiofsd (set REBUILD_VIRTIOFSD=1 to force)"
fi
if [ "${NEED_INITFS}" = "1" ]; then
echo "==> Building aarch64 cctl natively (used to pack initfs.ext4)"
swift build -c release --product cctl -Xswiftc -warnings-as-errors --disable-automatic-resolution
NATIVE_CCTL="$(swift build -c release --show-bin-path)/cctl"
echo "==> Building initfs.ext4 with x86_64 guest binaries"
rm -f "${DIST_DIR}/init.rootfs.tar.gz" "${DIST_DIR}/initfs.ext4"
"${NATIVE_CCTL}" rootfs create \
--vminitd "${DIST_DIR}/vminitd" \
--vmexec "${DIST_DIR}/vmexec" \
--ext4 "${DIST_DIR}/initfs.ext4" \
--label org.opencontainers.image.source=https://github.com/apple/containerization \
--image vminit-x86_64:latest \
"${DIST_DIR}/init.rootfs.tar.gz"
else
echo "==> Reusing staged initfs.ext4 (vminitd/vmexec unchanged; set REBUILD_INITFS=1 to force)"
fi
echo "==> Staging tree at ${STAGE} and packaging"
rm -rf "${STAGE}"
mkdir -p "${STAGE}/bin"
install -m 755 "${DIST_DIR}/cctl" "${STAGE}/bin/cctl"
install -m 755 "${DIST_DIR}/cloud-hypervisor" "${STAGE}/bin/cloud-hypervisor"
install -m 755 "${DIST_DIR}/virtiofsd" "${STAGE}/bin/virtiofsd"
mkdir -p "${STAGE}/kernel"
cp "${KERNEL_SRC}" "${STAGE}/kernel/$(basename "${KERNEL_SRC}")"
cp "${DIST_DIR}/initfs.ext4" "${STAGE}/initfs.ext4"
rm -f "${TGZ}"
tar -czf "${TGZ}" -C "${DIST_DIR}" "${DIST_NAME}"
echo "wrote ${TGZ}"
+138
View File
@@ -0,0 +1,138 @@
#!/bin/bash
# Copyright © 2026 Apple Inc. and the Containerization project authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Builds x86_64-linux-gnu shared-library versions of libseccomp and
# libcap-ng (the two C libs virtiofsd links against) and installs them
# at /opt/cross-x86_64-gnu. Sibling of build-musl-x86_64-deps.sh; the
# Dockerfile invokes both at image build time.
#
# Why a separate prefix: virtiofsd ships glibc-dynamic in the x86_64
# tarball (see docs/x86_64-build.md) so deployment hosts can use their
# system libseccomp.so.2 + libcap-ng.so.0; everything else in the tarball
# stays musl-static. Mixing static-musl .a archives and dynamic-gnu .so
# files at one prefix confuses pkg-config and the linker, so they live
# apart.
#
# The glibc baseline is pinned at 2.35 (Ubuntu 22.04 / Debian 12 / RHEL 9
# era) via the Zig wrapper scripts at /usr/local/bin/x86_64-linux-gnu-*,
# which dispatch to `zig cc -target x86_64-linux-gnu.2.35`. Bump the
# wrapper triple if the baseline moves.
#
# Only two libraries here, both shared: virtiofsd's other build-script
# deps (zstd, etc.) come from cargo crates that vendor C sources, and
# cctl's libarchive lives on the musl side.
set -euo pipefail
HOST=x86_64-linux-gnu
PREFIX=/opt/cross-x86_64-gnu
mkdir -p "${PREFIX}/lib" "${PREFIX}/include"
export CC="${HOST}-gcc"
export CXX="${HOST}-g++"
export AR="${HOST}-ar"
export RANLIB="${HOST}-ranlib"
export STRIP="${HOST}-strip"
export PKG_CONFIG_PATH="${PREFIX}/lib/pkgconfig"
WORK=$(mktemp -d)
trap 'rm -rf "${WORK}"' EXIT
cd "${WORK}"
JOBS="$(nproc)"
# fetch_extract URL ARCHIVE
#
# Downloads URL to ARCHIVE then extracts. Relies on HTTPS for transport
# integrity; no SHA pinning. The other build-time deps (apt packages,
# Zig, Rust toolchain) trust the same.
fetch_extract() {
local url=$1 archive=$2
curl -fsSL -o "${archive}" "${url}"
tar -xf "${archive}"
}
# Sanity check: cross compiler produces clean output for a trivial
# program. autotools / libtool turn unexpected compiler chatter into
# baffling configure errors; surfacing it here gives a real message.
echo "==> cross compiler sanity check"
"${CC}" --version
cat > "${WORK}/sanity.c" <<'EOF'
void foo(void) {}
EOF
out=$("${CC}" -c "${WORK}/sanity.c" -o "${WORK}/sanity.o" 2>&1) || {
echo "ERROR: cross compiler failed on trivial test.c:" >&2
echo "${out}" >&2
exit 1
}
if [ -n "${out}" ]; then
echo "WARNING: cross compiler emitted output on a clean compile:" >&2
echo "${out}" >&2
fi
# libcap-ng — github auto-archive (release artifacts for older tags
# aren't always uploaded).
LIBCAP_NG_VERSION=0.8.5
fetch_extract "https://github.com/stevegrubb/libcap-ng/archive/refs/tags/v${LIBCAP_NG_VERSION}.tar.gz" libcap-ng.tar.gz
(
cd "libcap-ng-${LIBCAP_NG_VERSION}"
# GNU automake's strict mode requires these standard files to exist;
# the auto-archive tarball doesn't ship NEWS. Cheaper than
# configure.ac surgery.
touch NEWS README AUTHORS ChangeLog
autoreconf -i
./configure --host="${HOST}" --prefix="${PREFIX}" \
--disable-static --enable-shared \
--without-python --without-python3
make -j"${JOBS}"
make install
)
# libseccomp — needs gperf at build time (installed via the Dockerfile
# alongside the musl deps). Built shared here.
LIBSECCOMP_VERSION=2.5.5
fetch_extract "https://github.com/seccomp/libseccomp/releases/download/v${LIBSECCOMP_VERSION}/libseccomp-${LIBSECCOMP_VERSION}.tar.gz" libseccomp.tar.gz
(
cd "libseccomp-${LIBSECCOMP_VERSION}"
./configure --host="${HOST}" --prefix="${PREFIX}" \
--disable-static --enable-shared \
--disable-python
make -j"${JOBS}"
make install
)
# Drop libtool .la files — they encode build-host paths and confuse
# downstream consumers; the .so + pkg-config .pc files are sufficient.
rm -f "${PREFIX}/lib"/*.la
# Force the unversioned dev symlinks (libseccomp.so, libcap-ng.so).
# libtool conservatively omits these when cross-compiling, but rustc's
# link step looks for them by unversioned name; without them the
# link fails with "unable to find dynamic system library 'seccomp'".
# Idempotent — `ln -sf` overwrites any existing symlink, and the loop
# picks up whatever versioned files libtool actually installed.
for stem in libseccomp libcap-ng; do
versioned=$(ls "${PREFIX}/lib/${stem}.so."* 2>/dev/null | sort -V | head -n1)
if [ -n "${versioned}" ]; then
ln -sf "$(basename "${versioned}")" "${PREFIX}/lib/${stem}.so"
else
echo "ERROR: no ${stem}.so.* found in ${PREFIX}/lib after install" >&2
ls -la "${PREFIX}/lib" >&2
exit 1
fi
done
echo "glibc-dynamic x86_64 C deps installed under ${PREFIX}"
+188
View File
@@ -0,0 +1,188 @@
#!/bin/bash
# Copyright © 2026 Apple Inc. and the Containerization project authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Builds static-musl x86_64 versions of the C libraries that cctl and
# virtiofsd link against, and installs them at /opt/cross-x86_64-musl
# (a standalone prefix — the Zig-based cross compiler has no
# traditional sysroot, so the build-dist-x86_64.sh script and the
# cargo cross flow add explicit -L / -I flags pointing here).
#
# Invoked once at dev-image build time; the resulting layer is cached
# until this script changes. Adding/removing a library here is the only
# reason to invalidate it.
set -euo pipefail
HOST=x86_64-linux-musl
PREFIX=/opt/cross-x86_64-musl
mkdir -p "${PREFIX}/lib" "${PREFIX}/include"
export CC="${HOST}-gcc"
export CXX="${HOST}-g++"
export AR="${HOST}-ar"
export RANLIB="${HOST}-ranlib"
export STRIP="${HOST}-strip"
export PKG_CONFIG_PATH="${PREFIX}/lib/pkgconfig"
WORK=$(mktemp -d)
trap 'rm -rf "${WORK}"' EXIT
cd "${WORK}"
JOBS="$(nproc)"
# fetch_extract URL ARCHIVE
#
# Downloads URL to ARCHIVE then extracts. Relies on HTTPS for transport
# integrity; no SHA pinning. The other build-time deps (apt packages,
# Zig, Rust toolchain) trust the same.
fetch_extract() {
local url=$1 archive=$2
curl -fsSL -o "${archive}" "${url}"
tar -xf "${archive}"
}
# Sanity check: cross compiler is on PATH and produces clean output
# for a trivial program. If it doesn't, zlib's configure script (which
# treats any stderr/stdout from a test compile as evidence of -Werror)
# will fail with a misleading "Compiler error reporting is too harsh"
# error. Surfacing this here gives us a real error message instead.
echo "==> cross compiler sanity check"
"${CC}" --version
cat > "${WORK}/sanity.c" <<'EOF'
void foo(void) {}
EOF
out=$("${CC}" -c "${WORK}/sanity.c" -o "${WORK}/sanity.o" 2>&1) || {
echo "ERROR: cross compiler failed on trivial test.c:" >&2
echo "${out}" >&2
exit 1
}
if [ -n "${out}" ]; then
echo "WARNING: cross compiler emitted output on a clean compile:" >&2
echo "${out}" >&2
echo "(this will trip up zlib's configure script — see fix below)" >&2
fi
# zlib — provides libz.a. Its configure does not take --host, so the
# CC env var is what selects the cross compiler.
ZLIB_VERSION=1.3.1
fetch_extract "https://zlib.net/fossils/zlib-${ZLIB_VERSION}.tar.gz" zlib.tar.gz
(
cd "zlib-${ZLIB_VERSION}"
if ! ./configure --static --prefix="${PREFIX}"; then
echo "==================== zlib configure.log ====================" >&2
[ -f configure.log ] && cat configure.log >&2
echo "============================================================" >&2
exit 1
fi
make -j"${JOBS}"
make install
)
# xz — provides liblzma.a.
XZ_VERSION=5.6.4
fetch_extract "https://github.com/tukaani-project/xz/releases/download/v${XZ_VERSION}/xz-${XZ_VERSION}.tar.gz" xz.tar.gz
(
cd "xz-${XZ_VERSION}"
./configure --host="${HOST}" --prefix="${PREFIX}" \
--enable-static --disable-shared \
--disable-doc --disable-scripts \
--disable-xz --disable-xzdec --disable-lzmadec --disable-lzmainfo \
--disable-lzma-links
make -j"${JOBS}"
make install
)
# bzip2 — no autotools, drives a plain Makefile. Build only the static
# library; the bzip2 CLI tools are not needed.
BZIP2_VERSION=1.0.8
fetch_extract "https://sourceware.org/pub/bzip2/bzip2-${BZIP2_VERSION}.tar.gz" bzip2.tar.gz
(
cd "bzip2-${BZIP2_VERSION}"
make CC="${CC}" AR="${AR}" RANLIB="${RANLIB}" libbz2.a -j"${JOBS}"
install -m 644 libbz2.a "${PREFIX}/lib/"
install -m 644 bzlib.h "${PREFIX}/include/"
)
# libarchive — needs zlib + lzma + bz2 (built above). Disable optional
# deps that pull in extra toolchain weight (xml2, iconv, zstd, lz4,
# openssl, libb2). cctl uses libarchive for tar/ext layouts; the
# disabled formats are not used at runtime.
LIBARCHIVE_VERSION=3.7.7
fetch_extract "https://github.com/libarchive/libarchive/releases/download/v${LIBARCHIVE_VERSION}/libarchive-${LIBARCHIVE_VERSION}.tar.gz" libarchive.tar.gz
(
cd "libarchive-${LIBARCHIVE_VERSION}"
./configure --host="${HOST}" --prefix="${PREFIX}" \
--enable-static --disable-shared \
--disable-bsdtar --disable-bsdcat --disable-bsdcpio --disable-bsdunzip \
--without-xml2 --without-iconv --without-zstd --without-lz4 \
--without-openssl --without-libb2 \
CPPFLAGS="-I${PREFIX}/include" \
LDFLAGS="-L${PREFIX}/lib"
make -j"${JOBS}"
make install
)
# libcap-ng — github auto-archive (release artifacts for older tags
# aren't always uploaded; the auto-archive URL is always available
# for any tag, but doesn't ship a pre-generated configure script, so
# we autoreconf it ourselves).
LIBCAP_NG_VERSION=0.8.5
fetch_extract "https://github.com/stevegrubb/libcap-ng/archive/refs/tags/v${LIBCAP_NG_VERSION}.tar.gz" libcap-ng.tar.gz
(
cd "libcap-ng-${LIBCAP_NG_VERSION}"
# GNU automake's default (strict) mode requires these standard
# files to exist; the auto-archive tarball doesn't ship NEWS.
# Cheaper than configure.ac surgery.
touch NEWS README AUTHORS ChangeLog
autoreconf -i
./configure --host="${HOST}" --prefix="${PREFIX}" \
--enable-static --disable-shared \
--without-python --without-python3
make -j"${JOBS}"
make install
)
# libseccomp — needs gperf at build time (installed via apt above).
LIBSECCOMP_VERSION=2.5.5
fetch_extract "https://github.com/seccomp/libseccomp/releases/download/v${LIBSECCOMP_VERSION}/libseccomp-${LIBSECCOMP_VERSION}.tar.gz" libseccomp.tar.gz
(
cd "libseccomp-${LIBSECCOMP_VERSION}"
./configure --host="${HOST}" --prefix="${PREFIX}" \
--enable-static --disable-shared \
--disable-python
make -j"${JOBS}"
make install
)
# Linker-script `.so` shims for libseccomp + libcap-ng. The Rust
# `-sys` crates emit plain `cargo:rustc-link-lib=seccomp` (no
# static= prefix), and they don't declare `links = "..."` in their
# Cargo.toml, so cargo's build-script override can't match them.
# Instead we hand the linker fake `.so` files that are actually GNU
# ld linker scripts pointing at the static archive — when ld resolves
# `-lseccomp` to libseccomp.so it reads the script and pulls in
# libseccomp.a as if statically linked. Works regardless of -Bstatic
# vs -Bdynamic state and avoids needing to patch the -sys crates.
cat > "${PREFIX}/lib/libseccomp.so" <<EOF
/* Linker script: pull in the static archive when -lseccomp resolves here. */
GROUP ( ${PREFIX}/lib/libseccomp.a )
EOF
cat > "${PREFIX}/lib/libcap-ng.so" <<EOF
/* Linker script: pull in the static archive when -lcap-ng resolves here. */
GROUP ( ${PREFIX}/lib/libcap-ng.a )
EOF
echo "static-musl x86_64 C deps installed under ${PREFIX}"
+58
View File
@@ -0,0 +1,58 @@
#!/bin/bash
# Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Script to scan the VM boot logs from the integration tests for kernel panics.
# Looks for common kernel panic messages like "attempted to kill init" or "Kernel panic".
GIT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
if [ -z "$GIT_ROOT" ]; then
echo "Error: Not in a git repository"
exit 1
fi
BOOT_LOGS_DIR="$GIT_ROOT/bin/integration-bootlogs"
if [ ! -d "$BOOT_LOGS_DIR" ]; then
echo "Error: Boot logs directory not found: $BOOT_LOGS_DIR"
exit 1
fi
echo "Scanning boot logs in: $BOOT_LOGS_DIR"
echo "========================================"
echo ""
PANIC_FOUND=0
for logfile in "$BOOT_LOGS_DIR"/*; do
if [ -f "$logfile" ]; then
if grep -qi "attempted to kill init\|Kernel panic\|end Kernel panic\|Attempted to kill the idle task\|Oops:" "$logfile"; then
echo "🚨 PANIC DETECTED in: $(basename "$logfile")"
echo "---"
grep -i -B 5 -A 10 "attempted to kill init\|Kernel panic\|end Kernel panic\|Attempted to kill the idle task\|Oops:" "$logfile" | head -30
echo ""
echo "========================================"
echo ""
PANIC_FOUND=1
fi
fi
done
if [ $PANIC_FOUND -eq 0 ]; then
echo "✅ No kernel panics detected in boot logs"
else
echo "❌ Found kernel panics - Virtual machine(s) crashed during integration tests"
fi
exit $PANIC_FOUND
+11
View File
@@ -0,0 +1,11 @@
[SWIFT_STYLE]
firstLine = '//===----------------------------------------------------------------------===//'
endLine = "//===----------------------------------------------------------------------===//\n"
beforeEachLine = '// '
afterEachLine = ''
allowBlankLines = false
multipleLines = true
padLines = false
firstLineDetectionPattern = '//\s?==='
lastLineDetectionPattern = '//\s?==='
skipLinePattern = '// swift-tools-version'
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/env bash
# Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
echo "Checking existence of hawkeye..."
if command -v .local/bin/hawkeye >/dev/null 2>&1; then
echo "hawkeye found!"
else
echo "hawkeye not found in PATH"
echo "please install hawkeye. For convenience, you can run scripts/install-hawkeye.sh"
exit 1
fi
+50
View File
@@ -0,0 +1,50 @@
#!/usr/bin/env bash
# Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -euo pipefail
if command -v .local/bin/hawkeye >/dev/null 2>&1; then
echo "hawkeye already installed"
exit 0
fi
# This installer supports Apple silicon (arm64 macOS) only.
if [ "$(uname -s)" != "Darwin" ] || [ "$(uname -m)" != "arm64" ]; then
echo "error: install-hawkeye.sh supports Apple silicon (arm64 macOS) only" >&2
exit 1
fi
VERSION=v6.5.1
ARTIFACT="hawkeye-aarch64-apple-darwin.tar.xz"
ARTIFACT_URL="https://github.com/korandoru/hawkeye/releases/download/${VERSION}/${ARTIFACT}"
# Pinned SHA-256 of ${ARTIFACT} for ${VERSION}; update when bumping VERSION.
EXPECTED_SHA256="99777f21e4e56c9946ed93621885532c6a0476377f497565c583f5911f2cbb1f"
echo "Installing hawkeye ${VERSION}"
workdir="$(mktemp -d)"
trap 'rm -rf "${workdir}"' EXIT
tarball="${workdir}/${ARTIFACT}"
# Download the tarball, verify it against the pinned checksum (aborts on
# mismatch), then extract just the hawkeye binary into .local/bin.
curl --proto '=https' --tlsv1.2 -LsSf "${ARTIFACT_URL}" -o "${tarball}"
echo "${EXPECTED_SHA256} ${tarball}" | shasum -a 256 -c -
tar -xf "${tarball}" --strip-components 1 -C "${workdir}"
mkdir -p .local/bin
mv "${workdir}/hawkeye" .local/bin/hawkeye
chmod +x .local/bin/hawkeye
echo "hawkeye ${VERSION} installed to .local/bin/hawkeye"
+13
View File
@@ -0,0 +1,13 @@
Copyright ©{{ " " }}{%- set created = attrs.git_file_created_year or attrs.disk_file_created_year -%}{%- set modified = attrs.git_file_modified_year or created -%}{%- if created != modified -%} {{created}}-{{modified}}{%- else -%}{{created}}{%- endif -%}{{ " " }}{{ props["copyrightOwner"] }}.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+52
View File
@@ -0,0 +1,52 @@
#! /bin/bash -e
# Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
opts=()
opts+=("--allow-writing-to-directory" "$1")
opts+=("generate-documentation")
opts+=("--target" "Containerization")
opts+=("--target" "ContainerizationArchive")
opts+=("--target" "ContainerizationError")
opts+=("--target" "ContainerizationEXT4")
opts+=("--target" "ContainerizationExtras")
opts+=("--target" "ContainerizationIO")
opts+=("--target" "ContainerizationNetlink")
opts+=("--target" "ContainerizationOCI")
opts+=("--target" "ContainerizationOS")
opts+=("--output-path" "$1")
opts+=("--disable-indexing")
opts+=("--transform-for-static-hosting")
opts+=("--enable-experimental-combined-documentation")
opts+=("--experimental-documentation-coverage")
if [ ! -z "$2" ] ; then
opts+=("--hosting-base-path" "$2")
fi
/usr/bin/swift package ${opts[@]}
echo '{}' > "$1/theme-settings.json"
cat > "$1/index.html" <<'EOF'
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta http-equiv="refresh" content="0; url=./documentation/">
</head>
<body>
<p>If you are not redirected automatically, <a href="./documentation/">click here</a>.</p>
</body>
</html>
EOF
@@ -0,0 +1,41 @@
# virtiofsd patch — skip capability drop when --sandbox=none.
#
# virtiofsd 1.13.3 unconditionally calls capng::apply (capset(2)) at
# startup when running as root. Inside apple/container's --virtualization
# dev container the default seccomp profile blocks capset(2), so virtiofsd
# fails with "failed to sync capabilities with the kernel" and
# process::exit(1)s before binding its socket.
#
# We already pass --sandbox=none to virtiofsd from VirtiofsdProcess (same
# rationale as why cloud-hypervisor runs with --seccomp false in the same
# environment). This patch extends the existing upstream gate ("We don't
# modify the capabilities if the user call us without any sandbox") so
# that --sandbox=none also skips cap drop at uid==0, matching the user's
# explicit opt-out from the sandbox.
#
# Applied automatically by `make build-virtiofsd` before `cargo build`.
# Targets virtiofsd 1.13.3 (.local/virtiofsd).
diff --git a/src/main.rs b/src/main.rs
index 176e178..27dce55 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -858,8 +858,17 @@ fn main() {
// We don't modify the capabilities if the user call us without
// any sandbox (i.e. --sandbox=none) as unprivileged user
+ //
+ // CONTAINERIZATION-PATCH: also skip cap drop with --sandbox=none even
+ // when running as root. Inside apple/container's --virtualization dev
+ // container the seccomp profile blocks capset(2), so capng::apply
+ // fails with "failed to sync capabilities with the kernel" and
+ // virtiofsd process::exit(1)s before binding its socket. The
+ // user explicitly opted out of the sandbox; respect that and don't
+ // touch caps either. Same class of issue as why CH runs with
+ // --seccomp false in the same env.
let uid = unsafe { libc::geteuid() };
- if uid == 0 {
+ if uid == 0 && !matches!(opt.sandbox, SandboxMode::None) {
drop_capabilities(fs_cfg.inode_file_handles, opt.modcaps);
}
+16
View File
@@ -0,0 +1,16 @@
#! /bin/bash -e
setup_error() {
echo failed to run: $1 1>&2
echo run '"make pre-commit"' and try again 1>&2
exit 1
}
if [ ! -z "${PRECOMMIT_NOFMT}" ] ; then
exit 0
fi
echo checking formatting and licenses 1>&2
project_pathname=$(git rev-parse --show-toplevel)
cd "${project_pathname}"
make check