Skip to content
Draft
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
6 changes: 5 additions & 1 deletion .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ task:
CIRRUS_WORKING_DIR: /home/runc
GO_VER_PREFIX: "1.25."
BATS_VERSION: "v1.12.0"
RPMS: gcc git-core iptables jq glibc-static libseccomp-devel make criu fuse-sshfs container-selinux
LIBPATHRS_VERSION: "0.2.3"
RPMS: gcc git-core iptables jq glibc-static libseccomp-devel make criu fuse-sshfs container-selinux cargo lld
# yamllint disable rule:key-duplicates
matrix:
- DISTRO: almalinux-8
Expand Down Expand Up @@ -63,6 +64,9 @@ task:
dnf -y install criu
esac

# Install libpathrs.
/home/runc/script/build-libpathrs.sh "$LIBPATHRS_VERSION" /usr

# Install Go.
URL_PREFIX="https://go.dev/dl/"
# Find out the latest minor release URL.
Expand Down
30 changes: 28 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ jobs:
matrix:
os: [ubuntu-24.04, ubuntu-24.04-arm]
go-version: [1.24.x, 1.25.x, 1.26.x]
libpathrs-version: [&LIBPATHRS_VERSION "0.2.3"]
rootless: ["rootless", ""]
race: ["-race", ""]
criu: ["", "criu-dev"]
Expand Down Expand Up @@ -75,7 +76,13 @@ jobs:
- name: install deps
run: |
sudo apt update
sudo apt -y install libseccomp-dev sshfs uidmap
sudo apt -y install libseccomp-dev sshfs uidmap lld

- name: install libpathrs v${{ matrix.libpathrs-version }}
env:
LIBPATHRS_VERSION: (${{ matrix.libpathrs-version }})
run: |
sudo -E PATH="$PATH" ./script/build-libpathrs.sh "$LIBPATHRS_VERSION" /usr

- name: install CRIU
if: ${{ matrix.criu == '' }}
Expand Down Expand Up @@ -170,7 +177,24 @@ jobs:
sudo add-apt-repository -y ppa:criu/ppa || sudo add-apt-repository -y ppa:criu/ppa
# apt-add-repository runs apt update so we don't have to.

sudo apt -qy install libseccomp-dev libseccomp-dev:i386 gcc-multilib libgcc-s1:i386 criu
GCC_VERSION="$(gcc -dumpversion)"
sudo apt -qy install \
lld criu \
libseccomp-dev libseccomp-dev:i386 \
libc-dev:i386 libgcc-s1:i386 libgcc-${GCC_VERSION}-dev:i386 gcc-i686-linux-gnu

# When cross-compiling, GCC will look for a linker that is marked for
# cross-compilation, which the Ubuntu lld package doesn't provide. The
# solution is to create a symlink ourselves.
# See <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111605>.
ln -sv "$(which ld.lld)" /usr/local/bin/i686-linux-gnu-ld.lld
- run: rustup target add i686-unknown-linux-gnu

- name: install libpathrs
env:
LIBPATHRS_VERSION: *LIBPATHRS_VERSION
run: |
sudo -E PATH="$PATH" ./script/build-libpathrs.sh "$LIBPATHRS_VERSION" /usr 386

- name: install go
uses: actions/setup-go@v6
Expand All @@ -179,6 +203,8 @@ jobs:
check-latest: true

- name: unit test
env:
PKG_CONFIG_PATH: /usr/386/lib/pkgconfig
run: sudo -E PATH="$PATH" -- make GOARCH=386 localunittest

fedora:
Expand Down
7 changes: 6 additions & 1 deletion .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,12 @@ jobs:
- name: install deps
run: |
sudo apt update
sudo apt -y install libseccomp-dev
sudo apt -y install libseccomp-dev lld
- name: install libpathrs
env:
LIBPATHRS_VERSION: "0.2.3"
run: |
sudo -E PATH="$PATH" ./script/build-libpathrs.sh "$LIBPATHRS_VERSION" /usr
- name: compile with no build tags
run: make BUILDTAGS=""
- name: compile with runc_nocriu build tag
Expand Down
46 changes: 31 additions & 15 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
ARG GO_VERSION=1.25
ARG BATS_VERSION=v1.12.0
ARG LIBSECCOMP_VERSION=2.6.0
ARG LIBPATHRS_VERSION=0.2.3

FROM golang:${GO_VERSION}-bookworm
FROM golang:${GO_VERSION}-trixie
ARG DEBIAN_FRONTEND=noninteractive
ARG CRIU_REPO=https://download.opensuse.org/repositories/devel:/tools:/criu/Debian_12
ARG CRIU_REPO=https://download.opensuse.org/repositories/devel:/tools:/criu/Debian_13

RUN KEYFILE=/usr/share/keyrings/criu-repo-keyring.gpg; \
wget -nv $CRIU_REPO/Release.key -O- | gpg --dearmor > "$KEYFILE" \
&& echo "deb [signed-by=$KEYFILE] $CRIU_REPO/ /" > /etc/apt/sources.list.d/criu.list \
&& dpkg --add-architecture i386 \
&& printf "%s\n" i386 armel armhf arm64 ppc64el s390x riscv64 | xargs -t -n1 -- dpkg --add-architecture \
&& apt-get update \
&& apt-get install -y --no-install-recommends \
build-essential \
cargo \
cargo-auditable \
clang \
criu \
gcc \
gcc-multilib \
Expand All @@ -22,20 +26,21 @@ RUN KEYFILE=/usr/share/keyrings/criu-repo-keyring.gpg; \
iptables \
jq \
kmod \
lld \
pkg-config \
python3-minimal \
sshfs \
sudo \
uidmap \
iproute2 \
&& apt-get install -y --no-install-recommends \
libc-dev:i386 libgcc-s1:i386 \
gcc-aarch64-linux-gnu libc-dev-arm64-cross \
gcc-arm-linux-gnueabi libc-dev-armel-cross \
gcc-arm-linux-gnueabihf libc-dev-armhf-cross \
gcc-powerpc64le-linux-gnu libc-dev-ppc64el-cross \
gcc-s390x-linux-gnu libc-dev-s390x-cross \
gcc-riscv64-linux-gnu libc-dev-riscv64-cross \
libc-dev:i386 libgcc-s1:i386 gcc-i686-linux-gnu libstd-rust-dev:i386 \
gcc-aarch64-linux-gnu libc-dev-arm64-cross libstd-rust-dev:arm64 \
gcc-arm-linux-gnueabi libc-dev-armel-cross libstd-rust-dev:armel \
gcc-arm-linux-gnueabihf libc-dev-armhf-cross libstd-rust-dev:armhf \
gcc-powerpc64le-linux-gnu libc-dev-ppc64el-cross libstd-rust-dev:ppc64el \
gcc-s390x-linux-gnu libc-dev-s390x-cross libstd-rust-dev:s390x \
gcc-riscv64-linux-gnu libc-dev-riscv64-cross libstd-rust-dev:riscv64 \
&& apt-get clean \
&& rm -rf /var/cache/apt /var/lib/apt/lists/* /etc/apt/sources.list.d/*.list

Expand All @@ -54,14 +59,25 @@ RUN cd /tmp \
&& ./install.sh /usr/local \
&& rm -rf /tmp/bats-core

ARG RELEASE_ARCHES="386 amd64 arm64 armel armhf ppc64le riscv64 s390x"
ENV DYLIB_DIR=/opt/runc-dylibs

# install libseccomp
ARG LIBSECCOMP_VERSION
COPY script/seccomp.sh script/lib.sh /tmp/script/
RUN mkdir -p /opt/libseccomp \
&& /tmp/script/seccomp.sh "$LIBSECCOMP_VERSION" /opt/libseccomp 386 amd64 arm64 armel armhf ppc64le riscv64 s390x
COPY script/build-seccomp.sh script/lib.sh /tmp/script/
RUN mkdir -p $DYLIB_DIR \
&& /tmp/script/build-seccomp.sh "$LIBSECCOMP_VERSION" $DYLIB_DIR $RELEASE_ARCHES
ENV LIBSECCOMP_VERSION=$LIBSECCOMP_VERSION
ENV LD_LIBRARY_PATH=/opt/libseccomp/lib
ENV PKG_CONFIG_PATH=/opt/libseccomp/lib/pkgconfig

# install libpathrs
ARG LIBPATHRS_VERSION
COPY script/build-libpathrs.sh /tmp/script/
RUN mkdir -p $DYLIB_DIR \
&& /tmp/script/build-libpathrs.sh "$LIBPATHRS_VERSION" $DYLIB_DIR $RELEASE_ARCHES
ENV LIBPATHRS_VERSION=$LIBPATHRS_VERSION

ENV LD_LIBRARY_PATH=$DYLIB_DIR/lib
ENV PKG_CONFIG_PATH=$DYLIB_DIR/lib/pkgconfig

# Prevent the "fatal: detected dubious ownership in repository" git complain during build.
RUN git config --global --add safe.directory /go/src/github.com/opencontainers/runc
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ GIT_BRANCH_CLEAN := $(shell echo $(GIT_BRANCH) | sed -e "s/[^[:alnum:]]/-/g")
RUNC_IMAGE := runc_dev$(if $(GIT_BRANCH_CLEAN),:$(GIT_BRANCH_CLEAN))
PROJECT := github.com/opencontainers/runc
EXTRA_BUILDTAGS :=
BUILDTAGS := seccomp urfave_cli_no_docs
BUILDTAGS := seccomp urfave_cli_no_docs libpathrs
BUILDTAGS += $(EXTRA_BUILDTAGS)

COMMIT := $(shell git describe --dirty --long --always)
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ make EXTRA_BUILDTAGS="runc_nocriu"
| Build Tag | Feature | Enabled by Default | Dependencies |
|---------------|---------------------------------------|--------------------|---------------------|
| `seccomp` | Syscall filtering using `libseccomp`. | yes | `libseccomp` |
| `libpathrs` | Use [`libpathrs`][] for path safety. | yes | [`libpathrs`][] |
| `runc_nocriu` | **Disables** runc checkpoint/restore. | no | `criu` |

The following build tags were used earlier, but are now obsoleted:
Expand All @@ -120,6 +121,8 @@ The following build tags were used earlier, but are now obsoleted:
- **apparmor** (since runc v1.0.0-rc93 the feature is always enabled)
- **selinux** (since runc v1.0.0-rc93 the feature is always enabled)

[`libpathrs`]: https://github.com/cyphar/libpathrs

### Running the test suite

`runc` currently supports running its test suite via Docker.
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ require (
)

require (
cyphar.com/go-pathrs v0.2.1 // indirect
cyphar.com/go-pathrs v0.2.4-0.20260212074101-c4e98bea7862 // indirect
github.com/cilium/ebpf v0.17.3 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cyphar.com/go-pathrs v0.2.1 h1:9nx1vOgwVvX1mNBWDu93+vaceedpbsDqo+XuBGL40b8=
cyphar.com/go-pathrs v0.2.1/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc=
cyphar.com/go-pathrs v0.2.4-0.20260212074101-c4e98bea7862 h1:Kcs6zS5vHgOP/0NV7KaTLUJcB+BTlDufueHvBbqwnSg=
cyphar.com/go-pathrs v0.2.4-0.20260212074101-c4e98bea7862/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc=
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/checkpoint-restore/go-criu/v7 v7.2.0 h1:qGiWA4App1gGlEfIJ68WR9jbezV9J7yZdjzglezcqKo=
github.com/checkpoint-restore/go-criu/v7 v7.2.0/go.mod h1:u0LCWLg0w4yqqu14aXhiB4YD3a1qd8EcCEg7vda5dwo=
Expand Down
153 changes: 153 additions & 0 deletions script/build-libpathrs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
#!/bin/bash
# Copyright (C) 2026 Open Containers 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
#
# http://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 -xEeuo pipefail

# shellcheck source=./script/lib.sh
source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"

PLATFORM="$(get_platform)"

declare -A GOARCH_TO_RUST_TARGET=(
["386"]=i686-unknown-linux-gnu
["amd64"]=x86_64-unknown-linux-gnu
["arm64"]=aarch64-unknown-linux-gnu
["armel"]=armv5te-unknown-linux-gnueabi
["armhf"]=armv7-unknown-linux-gnueabihf
["ppc64le"]=powerpc64le-unknown-linux-gnu
["s390x"]=s390x-unknown-linux-gnu
["riscv64"]=riscv64gc-unknown-linux-gnu
)

declare -A RUST_TARGET_TO_CC=(
["i686-unknown-linux-gnu"]="i686-${PLATFORM}-gcc"
["x86_64-unknown-linux-gnu"]="x86_64-${PLATFORM}-gcc"
["aarch64-unknown-linux-gnu"]="aarch64-${PLATFORM}-gcc"
["armv5te-unknown-linux-gnueabi"]="arm-${PLATFORM}eabi-gcc"
["armv7-unknown-linux-gnueabihf"]="arm-${PLATFORM}eabihf-gcc"
["powerpc64le-unknown-linux-gnu"]="powerpc64le-${PLATFORM}-gcc"
["s390x-unknown-linux-gnu"]="s390x-${PLATFORM}-gcc"
["riscv64gc-unknown-linux-gnu"]="riscv64-${PLATFORM}-gcc"
)

# sha256 checksums for libpathrs release tarballs.
declare -A LIBPATHRS_SHA256=(

Check warning on line 46 in script/build-libpathrs.sh

View workflow job for this annotation

GitHub Actions / shellcheck

LIBPATHRS_SHA256 appears unused. Verify use (or export if used externally).
["0.2.2"]=95978036c0f0d2e67f628fc06ccac090656606bee6632e437eac21d68b00504f
["0.2.3"]=1e7826b64e41940e8f62ca92dde7ae1459a35727a3aeb172cc11d48b4727aeed
)

function generate_cargo_config() {
for rust_target in "${GOARCH_TO_RUST_TARGET[@]}"; do
local target_gcc="${RUST_TARGET_TO_CC[$rust_target]}"

# Based on <https://wiki.debian.org/Rust#Crosscompiling>.
cat <<-EOF
[target.$rust_target]
linker = "$target_gcc"
rustflags = ["-L", "$(rustc --print sysroot)/lib/rustlib/$rust_target/lib"]
EOF
done
}

# Due to libpathrs being MPLv2/LGPLv3 we must include its sources, so
# download, install and build against it.
# Parameters:
# $1 -- libpathrs version to download and build.
# $2 -- destination directory.
# $@ -- additional architectures to cross-compile for.
function build_libpathrs() {
local ver="$1"
shift
local dest="$1"
shift
local go_arches=("$@")
local tar="libpathrs-${ver}.tar.gz"

Check warning on line 76 in script/build-libpathrs.sh

View workflow job for this annotation

GitHub Actions / shellcheck

tar appears unused. Verify use (or export if used externally).

# Download, check, and extract.
# TODO: Signatures and releases.
#wget "https://github.com/cyphar/libpathrs/releases/download/v${ver}/${tar}"{,.asc}
#wget "https://github.com/cyphar/libpathrs/archive/refs/tags/v${ver}.tar.gz" -O "$tar"
#sha256sum --strict --check - <<<"${LIBPATHRS_SHA256[${ver}]} *${tar}"

local srcdir
srcdir="$(mktemp -d)"
#tar xf "$tar" -C "$srcdir"
#pushd "$srcdir/libpathrs-$ver" || return
git clone https://github.com/cyphar/libpathrs.git "$srcdir/libpathrs"
pushd "$srcdir/libpathrs" || return

# Use cargo-auditable if available.
if cargo auditable --version &>/dev/null; then
export CARGO="cargo auditable"
fi
extra_cargo_flags+=("--locked")

# If we are being asked to install this in a system library directory
# (i.e., --prefix=/usr or something similar), the correct place to put
# libpathrs.so depends very strongly on the distro we are running on, and
# detecting this in a generic way is quite difficult.
#
# The simplest solution is to use a disto-packaged binary to detect where
# libc.so is installed and use the same import path, so we look at
# /proc/self/maps and parse out the parent directory of the libc.so being
# used.
local native_libdir libdir=
native_libdir="$(awk '$NF ~ /\/libc\>.*\.so/ { print $NF; }' /proc/self/maps | \
sort -u | head -n1 | xargs dirname)"
if [[ "$native_libdir" == "$dest/"* ]]; then
libdir="$native_libdir"
fi

# Install native version for Dockerfile builds.
make \
EXTRA_CARGO_FLAGS="${extra_cargo_flags[*]}" \
release
./install.sh \
--prefix="$dest" \
--libdir="$libdir"
cargo clean

local cargo_config
cargo_config="$(mktemp --tmpdir runc-libpathrs-cargo.toml.XXXXXX)"
# shellcheck disable=SC2064 # We want to resolve the path here.
trap "rm -f '$cargo_config'" EXIT

# Only configure cross-compile config when we need to cross-compile.
# RedHat-based distros insist on calling their targets "$ARCH-redhat-linux"
# which breaks our above logic, but we don't ever need to compile on RedHat
# distros so we can ignore this.
generate_cargo_config >"$cargo_config"
extra_cargo_flags+=("--config=$cargo_config")

for go_arch in "${go_arches[@]}"; do
local rust_target="${GOARCH_TO_RUST_TARGET[$go_arch]}"
make \
EXTRA_CARGO_FLAGS="${extra_cargo_flags[*]} --target=$rust_target" \
release
./install.sh \
--rust-target="$rust_target" \
--prefix="$dest/$go_arch"
cargo clean
done

popd
}

if [ $# -lt 2 ]; then
echo "Usage: $0 <version> <dest-dir> [<extra-arch> ...]" >&2
exit 1
fi

build_libpathrs "$@"
2 changes: 1 addition & 1 deletion script/seccomp.sh → script/build-seccomp.sh
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ function build_libseccomp() {
}

if [ $# -lt 2 ]; then
echo "Usage: seccomp.sh <version> <dest-dir> [<extra-arch> ...]" >&2
echo "Usage: $0 <version> <dest-dir> [<extra-arch> ...]" >&2
exit 1
fi

Expand Down
Loading
Loading