From 5d3d8f8962ade5ee773f5edd91bb6fd84ff2d7c2 Mon Sep 17 00:00:00 2001 From: Aleksa Sarai Date: Mon, 9 Feb 2026 10:40:18 +1100 Subject: [PATCH 1/9] integration: output debug information in fd leak test Signed-off-by: Aleksa Sarai --- tests/integration/create.bats | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/integration/create.bats b/tests/integration/create.bats index 48b665dc04f..f96c2e2aad7 100644 --- a/tests/integration/create.bats +++ b/tests/integration/create.bats @@ -69,6 +69,8 @@ is_allowed_fdtarget() { if ! is_allowed_fdtarget "$target"; then echo "Violation: FD $fd_name -> '$target'" violation_found=1 + else + echo "Permitted: FD $fd_name -> '$target'" fi done < <(find "/proc/$pid/fd" -type l -print0) [ "$violation_found" -eq 0 ] From 9c35faf5a0e121026fead254b47134060b93686e Mon Sep 17 00:00:00 2001 From: Aleksa Sarai Date: Tue, 3 Feb 2026 00:15:10 +0100 Subject: [PATCH 2/9] dockerfile: switch to Debian 13 Debian 13 (trixie) was released a few months ago and it's probably prudent to just upgrade. This is also necessary to get access to riscv64 repositories when we build libpathrs for inclusion in our runc binaries. Signed-off-by: Aleksa Sarai --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index e4f3df3545b..f97f3036bf2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,9 +2,9 @@ ARG GO_VERSION=1.25 ARG BATS_VERSION=v1.12.0 ARG LIBSECCOMP_VERSION=2.6.0 -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" \ From c8a53cbc5988ad5653f23b1c197f1e490964c25c Mon Sep 17 00:00:00 2001 From: Aleksa Sarai Date: Fri, 13 Feb 2026 18:32:33 +1100 Subject: [PATCH 3/9] build: treat armhf as ARMv7 The intention of commit 531e29e19211 ("script/lib.sh: set GOARM=5 for armel, GOARM=6 for armhf") was to properly support older ARM platforms with our release builds. However, we have never been able to support ARMv6 for our builds because we use the Debian compiler to build the libseccomp we statically compile into our binaries and (as per the now-deleted comment itself) Debian treats armhf as being ARMv7 so the final binaries we produced were always only ever compatible with ARMv7+. This was a bit of an oddity before but when building libpathrs for releases we will need to use Rust which makes the target more explicit (and while it does support armhf, we are using the Debian-packaged Rust cross-compiler and thus are in the same dilemma with what Debian considers "armhf" to be). All-in-all, it's better to just bite the bullet and just follow Debian here properly. Fixes: 531e29e19211 ("script/lib.sh: set GOARM=5 for armel, GOARM=6 for armhf") Signed-off-by: Aleksa Sarai --- script/lib.sh | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/script/lib.sh b/script/lib.sh index 9e4139756a3..89ce8c6c34e 100644 --- a/script/lib.sh +++ b/script/lib.sh @@ -48,16 +48,7 @@ function set_cross_vars() { armhf) HOST=arm-${PLATFORM}eabihf GOARCH=arm - # "armhf" means ARMv7 for Debian, ARMv6 for Raspbian. - # ARMv6 is chosen here for compatibility. - # - # https://wiki.debian.org/RaspberryPi - # - # > Raspberry Pi OS builds a single image for all of the Raspberry families, - # > so you will get an armhf 32-bit, hard floating-point system, but built - # > for the ARMv6 ISA (with VFP2), unlike Debian's ARMv7 ISA (with VFP3) - # > port. - GOARM=6 + GOARM=7 ;; ppc64le) HOST=powerpc64le-${PLATFORM} From b825e1ec06388453252d16df194b6759cd4e8c4e Mon Sep 17 00:00:00 2001 From: Aleksa Sarai Date: Mon, 2 Feb 2026 13:04:50 +0100 Subject: [PATCH 4/9] build: rename /opt/libseccomp cdylib directory Signed-off-by: Aleksa Sarai --- Dockerfile | 10 ++++++---- script/release_build.sh | 23 +++++++++-------------- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/Dockerfile b/Dockerfile index f97f3036bf2..9f5bbc09642 100644 --- a/Dockerfile +++ b/Dockerfile @@ -54,14 +54,16 @@ RUN cd /tmp \ && ./install.sh /usr/local \ && rm -rf /tmp/bats-core +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 +RUN mkdir -p $DYLIB_DIR \ + && /tmp/script/seccomp.sh "$LIBSECCOMP_VERSION" $DYLIB_DIR 386 amd64 arm64 armel armhf ppc64le riscv64 s390x ENV LIBSECCOMP_VERSION=$LIBSECCOMP_VERSION -ENV LD_LIBRARY_PATH=/opt/libseccomp/lib -ENV PKG_CONFIG_PATH=/opt/libseccomp/lib/pkgconfig +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 diff --git a/script/release_build.sh b/script/release_build.sh index 0e0a221839e..7627a65ca33 100755 --- a/script/release_build.sh +++ b/script/release_build.sh @@ -40,14 +40,14 @@ function build_project() { shift local arches=("$@") - # Assume that if /opt/libseccomp exists, then we are run - # via Dockerfile, and seccomp is already built. - local seccompdir=/opt/libseccomp temp_dir - if [ ! -d "$seccompdir" ]; then - temp_dir="$(mktemp -d)" - seccompdir="$temp_dir" + # Assume that if /opt/runc-dylibs exists, then we are running via + # Dockerfile, and thus seccomp is already built. Otherwise, build it now. + local dylibdir=/opt/runc-dylibs + if ! [ -d "$dylibdir" ]; then + trap 'rm -rf "$dylibdir"' EXIT + dylibdir="$(mktemp -d)" # Download and build libseccomp. - "$root/script/seccomp.sh" "$LIBSECCOMP_VERSION" "$seccompdir" "${arches[@]}" + "$root/script/seccomp.sh" "$LIBSECCOMP_VERSION" "$dylibdir" "${arches[@]}" fi # For reproducible builds, add these to EXTRA_LDFLAGS: @@ -70,7 +70,7 @@ function build_project() { CFLAGS="$original_cflags" set_cross_vars "$arch" make -C "$root" \ - PKG_CONFIG_PATH="$seccompdir/$arch/lib/pkgconfig" \ + PKG_CONFIG_PATH="$dylibdir/$arch/lib/pkgconfig" \ "${make_args[@]}" "$STRIP" "$root/$project" mv "$root/$project" "$builddir/$project.$arch" @@ -85,12 +85,7 @@ function build_project() { fi # Copy libseccomp source tarball. - cp "$seccompdir"/src/* "$builddir" - - # Clean up. - if [ -n "$tempdir" ]; then - rm -rf "$tempdir" - fi + cp "$dylibdir"/src/* "$builddir" } # End of the easy-to-configure portion. From af1e231ede95139ca2656731ed24d5664e68529d Mon Sep 17 00:00:00 2001 From: Aleksa Sarai Date: Tue, 3 Feb 2026 19:52:35 +0100 Subject: [PATCH 5/9] script: seccomp.sh -> build-seccomp.sh This name is far more descriptive. Signed-off-by: Aleksa Sarai --- Dockerfile | 6 ++++-- script/{seccomp.sh => build-seccomp.sh} | 2 +- script/release_build.sh | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) rename script/{seccomp.sh => build-seccomp.sh} (96%) diff --git a/Dockerfile b/Dockerfile index 9f5bbc09642..829acc42c51 100644 --- a/Dockerfile +++ b/Dockerfile @@ -54,14 +54,16 @@ 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/ +COPY script/build-seccomp.sh script/lib.sh /tmp/script/ RUN mkdir -p $DYLIB_DIR \ - && /tmp/script/seccomp.sh "$LIBSECCOMP_VERSION" $DYLIB_DIR 386 amd64 arm64 armel armhf ppc64le riscv64 s390x + && /tmp/script/build-seccomp.sh "$LIBSECCOMP_VERSION" $DYLIB_DIR $RELEASE_ARCHES ENV LIBSECCOMP_VERSION=$LIBSECCOMP_VERSION + ENV LD_LIBRARY_PATH=$DYLIB_DIR/lib ENV PKG_CONFIG_PATH=$DYLIB_DIR/lib/pkgconfig diff --git a/script/seccomp.sh b/script/build-seccomp.sh similarity index 96% rename from script/seccomp.sh rename to script/build-seccomp.sh index c4bbfac1f92..d8a3f9a0e42 100755 --- a/script/seccomp.sh +++ b/script/build-seccomp.sh @@ -65,7 +65,7 @@ function build_libseccomp() { } if [ $# -lt 2 ]; then - echo "Usage: seccomp.sh [ ...]" >&2 + echo "Usage: $0 [ ...]" >&2 exit 1 fi diff --git a/script/release_build.sh b/script/release_build.sh index 7627a65ca33..f84bd5041fd 100755 --- a/script/release_build.sh +++ b/script/release_build.sh @@ -47,7 +47,7 @@ function build_project() { trap 'rm -rf "$dylibdir"' EXIT dylibdir="$(mktemp -d)" # Download and build libseccomp. - "$root/script/seccomp.sh" "$LIBSECCOMP_VERSION" "$dylibdir" "${arches[@]}" + "$root/script/build-seccomp.sh" "$LIBSECCOMP_VERSION" "$dylibdir" "${arches[@]}" fi # For reproducible builds, add these to EXTRA_LDFLAGS: From 1554e285c8af8234315aa24f0f55885ad70840de Mon Sep 17 00:00:00 2001 From: Aleksa Sarai Date: Fri, 13 Feb 2026 17:45:47 +1100 Subject: [PATCH 6/9] [wip] deps: update cyphar.com/go-pathrs to latest version Signed-off-by: Aleksa Sarai --- go.mod | 2 +- go.sum | 4 +-- vendor/cyphar.com/go-pathrs/.golangci.yml | 2 +- vendor/cyphar.com/go-pathrs/doc.go | 2 +- vendor/cyphar.com/go-pathrs/handle_linux.go | 10 ++----- .../go-pathrs/internal/fdutils/fd_linux.go | 2 +- .../internal/libpathrs/error_unix.go | 2 +- .../internal/libpathrs/libpathrs_linux.go | 6 ++-- .../go-pathrs/procfs/procfs_linux.go | 15 +++------- vendor/cyphar.com/go-pathrs/root_linux.go | 30 ++----------------- vendor/cyphar.com/go-pathrs/utils_linux.go | 2 +- vendor/modules.txt | 2 +- 12 files changed, 21 insertions(+), 58 deletions(-) diff --git a/go.mod b/go.mod index b9e866a7c66..814f1bc6d84 100644 --- a/go.mod +++ b/go.mod @@ -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 diff --git a/go.sum b/go.sum index 97d3d7c9562..499c4a13d80 100644 --- a/go.sum +++ b/go.sum @@ -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= diff --git a/vendor/cyphar.com/go-pathrs/.golangci.yml b/vendor/cyphar.com/go-pathrs/.golangci.yml index 2778a3268ef..a28cbd2a4fd 100644 --- a/vendor/cyphar.com/go-pathrs/.golangci.yml +++ b/vendor/cyphar.com/go-pathrs/.golangci.yml @@ -1,8 +1,8 @@ # SPDX-License-Identifier: MPL-2.0 # # libpathrs: safe path resolution on Linux -# Copyright (C) 2019-2025 Aleksa Sarai # Copyright (C) 2019-2025 SUSE LLC +# Copyright (C) 2026 Aleksa Sarai # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/vendor/cyphar.com/go-pathrs/doc.go b/vendor/cyphar.com/go-pathrs/doc.go index a7ee4bc487f..c3b4eedd0f8 100644 --- a/vendor/cyphar.com/go-pathrs/doc.go +++ b/vendor/cyphar.com/go-pathrs/doc.go @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MPL-2.0 /* * libpathrs: safe path resolution on Linux - * Copyright (C) 2019-2025 Aleksa Sarai * Copyright (C) 2019-2025 SUSE LLC + * Copyright (C) 2026 Aleksa Sarai * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/vendor/cyphar.com/go-pathrs/handle_linux.go b/vendor/cyphar.com/go-pathrs/handle_linux.go index 3221ef67389..6ed0b7af7ad 100644 --- a/vendor/cyphar.com/go-pathrs/handle_linux.go +++ b/vendor/cyphar.com/go-pathrs/handle_linux.go @@ -3,8 +3,8 @@ // SPDX-License-Identifier: MPL-2.0 /* * libpathrs: safe path resolution on Linux - * Copyright (C) 2019-2025 Aleksa Sarai * Copyright (C) 2019-2025 SUSE LLC + * Copyright (C) 2026 Aleksa Sarai * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -30,11 +30,9 @@ import ( // you can try to use [Root.Open] or [Root.OpenFile]. // // It is critical that perform all relevant operations through this [Handle] -// (rather than fetching the file descriptor yourself with [Handle.IntoRaw]), +// (rather than fetching the underlying [os.File] yourself with [Handle.IntoFile]), // because the security properties of libpathrs depend on users doing all // relevant filesystem operations through libpathrs. -// -// [os.File]: https://pkg.go.dev/os#File type Handle struct { inner *os.File } @@ -43,7 +41,7 @@ type Handle struct { // handle will be copied by this method, so the original handle should still be // freed by the caller. // -// This is effectively the inverse operation of [Handle.IntoRaw], and is used +// This is effectively the inverse operation of [Handle.IntoFile], and is used // for "deserialising" pathrs root handles. func HandleFromFile(file *os.File) (*Handle, error) { newFile, err := fdutils.DupFile(file) @@ -92,8 +90,6 @@ func (h *Handle) OpenFile(flags int) (*os.File, error) { // calling [Handle.Close] will also close any copies of the returned [os.File]. // If you want to get an independent copy, use [Handle.Clone] followed by // [Handle.IntoFile] on the cloned [Handle]. -// -// [os.File]: https://pkg.go.dev/os#File func (h *Handle) IntoFile() *os.File { // TODO: Figure out if we really don't want to make a copy. // TODO: We almost certainly want to clear r.inner here, but we can't do diff --git a/vendor/cyphar.com/go-pathrs/internal/fdutils/fd_linux.go b/vendor/cyphar.com/go-pathrs/internal/fdutils/fd_linux.go index 41aea3e4b3d..418b298149e 100644 --- a/vendor/cyphar.com/go-pathrs/internal/fdutils/fd_linux.go +++ b/vendor/cyphar.com/go-pathrs/internal/fdutils/fd_linux.go @@ -3,8 +3,8 @@ // SPDX-License-Identifier: MPL-2.0 /* * libpathrs: safe path resolution on Linux - * Copyright (C) 2019-2025 Aleksa Sarai * Copyright (C) 2019-2025 SUSE LLC + * Copyright (C) 2026 Aleksa Sarai * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/vendor/cyphar.com/go-pathrs/internal/libpathrs/error_unix.go b/vendor/cyphar.com/go-pathrs/internal/libpathrs/error_unix.go index c9f416de01f..8f610ca564e 100644 --- a/vendor/cyphar.com/go-pathrs/internal/libpathrs/error_unix.go +++ b/vendor/cyphar.com/go-pathrs/internal/libpathrs/error_unix.go @@ -5,8 +5,8 @@ // SPDX-License-Identifier: MPL-2.0 /* * libpathrs: safe path resolution on Linux - * Copyright (C) 2019-2025 Aleksa Sarai * Copyright (C) 2019-2025 SUSE LLC + * Copyright (C) 2026 Aleksa Sarai * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/vendor/cyphar.com/go-pathrs/internal/libpathrs/libpathrs_linux.go b/vendor/cyphar.com/go-pathrs/internal/libpathrs/libpathrs_linux.go index c07b80e3071..d54497a5b70 100644 --- a/vendor/cyphar.com/go-pathrs/internal/libpathrs/libpathrs_linux.go +++ b/vendor/cyphar.com/go-pathrs/internal/libpathrs/libpathrs_linux.go @@ -3,8 +3,8 @@ // SPDX-License-Identifier: MPL-2.0 /* * libpathrs: safe path resolution on Linux - * Copyright (C) 2019-2025 Aleksa Sarai * Copyright (C) 2019-2025 SUSE LLC + * Copyright (C) 2026 Aleksa Sarai * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -100,7 +100,7 @@ func InRootReadlink(rootFd uintptr, path string) (string, error) { size := 128 for { linkBuf := make([]byte, size) - n := C.pathrs_inroot_readlink(C.int(rootFd), cPath, C.cast_ptr(unsafe.Pointer(&linkBuf[0])), C.ulong(len(linkBuf))) + n := C.pathrs_inroot_readlink(C.int(rootFd), cPath, C.cast_ptr(unsafe.Pointer(&linkBuf[0])), C.size_t(len(linkBuf))) switch { case int(n) < C.__PATHRS_MAX_ERR_VALUE: return "", fetchError(n) @@ -301,7 +301,7 @@ func ProcReadlinkat(procRootFd int, base ProcBase, path string) (string, error) linkBuf := make([]byte, size) n := C.pathrs_proc_readlinkat( C.int(procRootFd), cBase, cPath, - C.cast_ptr(unsafe.Pointer(&linkBuf[0])), C.ulong(len(linkBuf))) + C.cast_ptr(unsafe.Pointer(&linkBuf[0])), C.size_t(len(linkBuf))) switch { case int(n) < C.__PATHRS_MAX_ERR_VALUE: return "", fetchError(n) diff --git a/vendor/cyphar.com/go-pathrs/procfs/procfs_linux.go b/vendor/cyphar.com/go-pathrs/procfs/procfs_linux.go index 5533c427cb7..915e9ccdb58 100644 --- a/vendor/cyphar.com/go-pathrs/procfs/procfs_linux.go +++ b/vendor/cyphar.com/go-pathrs/procfs/procfs_linux.go @@ -3,8 +3,8 @@ // SPDX-License-Identifier: MPL-2.0 /* * libpathrs: safe path resolution on Linux - * Copyright (C) 2019-2025 Aleksa Sarai * Copyright (C) 2019-2025 SUSE LLC + * Copyright (C) 2026 Aleksa Sarai * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -56,16 +56,15 @@ var ( // *before* you call wait(2)or any equivalent method that could reap // zombies). func ProcPid(pid int) ProcBase { - if pid < 0 || pid >= 1<<31 { + if pid < 0 || uint64(pid) >= 1<<31 { panic("invalid ProcBasePid value") // TODO: should this be an error? } - return ProcBase{inner: libpathrs.ProcPid(uint32(pid))} + pid32 := uint32(pid) //nolint:gosec // G115 false positive + return ProcBase{inner: libpathrs.ProcPid(pid32)} } // ThreadCloser is a callback that needs to be called when you are done // operating on an [os.File] fetched using [Handle.OpenThreadSelf]. -// -// [os.File]: https://pkg.go.dev/os#File type ThreadCloser func() // Handle is a wrapper around an *os.File handle to "/proc", which can be @@ -181,8 +180,6 @@ func (proc *Handle) OpenRoot(path string, flags int) (*os.File, error) { // Unlike [Handle.OpenThreadSelf], this method does not involve locking // the goroutine to the current OS thread and so is simpler to use and // theoretically has slightly less overhead. -// -// [runtime.LockOSThread]: https://pkg.go.dev/runtime#LockOSThread func (proc *Handle) OpenSelf(path string, flags int) (*os.File, error) { file, closer, err := proc.open(ProcSelf, path, flags) if closer != nil { @@ -228,10 +225,6 @@ func (proc *Handle) OpenPid(pid int, path string, flags int) (*os.File, error) { // callback MUST be called AFTER you have finished using the returned // [os.File]. This callback is completely separate to [os.File.Close], so it // must be called regardless of how you close the handle. -// -// [runtime.LockOSThread]: https://pkg.go.dev/runtime#LockOSThread -// [os.File]: https://pkg.go.dev/os#File -// [os.File.Close]: https://pkg.go.dev/os#File.Close func (proc *Handle) OpenThreadSelf(path string, flags int) (*os.File, ThreadCloser, error) { return proc.open(ProcThreadSelf, path, flags) } diff --git a/vendor/cyphar.com/go-pathrs/root_linux.go b/vendor/cyphar.com/go-pathrs/root_linux.go index edc9e4c87f9..5bc2e907170 100644 --- a/vendor/cyphar.com/go-pathrs/root_linux.go +++ b/vendor/cyphar.com/go-pathrs/root_linux.go @@ -3,8 +3,8 @@ // SPDX-License-Identifier: MPL-2.0 /* * libpathrs: safe path resolution on Linux - * Copyright (C) 2019-2025 Aleksa Sarai * Copyright (C) 2019-2025 SUSE LLC + * Copyright (C) 2026 Aleksa Sarai * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -54,8 +54,6 @@ func OpenRoot(path string) (*Root, error) { // still be closed by the caller. // // This is effectively the inverse operation of [Root.IntoFile]. -// -// [os.File]: https://pkg.go.dev/os#File func RootFromFile(file *os.File) (*Root, error) { newFile, err := fdutils.DupFile(file) if err != nil { @@ -109,8 +107,6 @@ func (r *Root) ResolveNoFollow(path string) (*Handle, error) { // ergonomic to use. // // This is effectively equivalent to [os.Open]. -// -// [os.Open]: https://pkg.go.dev/os#Open func (r *Root) Open(path string) (*os.File, error) { return r.OpenFile(path, os.O_RDONLY) } @@ -127,8 +123,6 @@ func (r *Root) Open(path string) (*os.File, error) { // // This is effectively equivalent to [os.OpenFile], except that os.O_CREAT is // not supported. -// -// [os.OpenFile]: https://pkg.go.dev/os#OpenFile func (r *Root) OpenFile(path string, flags int) (*os.File, error) { return fdutils.WithFileFd(r.inner, func(rootFd uintptr) (*os.File, error) { fd, err := libpathrs.InRootOpen(rootFd, path, flags) @@ -145,8 +139,6 @@ func (r *Root) OpenFile(path string, flags int) (*os.File, error) { // // Unlike [os.Create], if the file already exists an error is created rather // than the file being opened and truncated. -// -// [os.Create]: https://pkg.go.dev/os#Create func (r *Root) Create(path string, flags int, mode os.FileMode) (*os.File, error) { unixMode, err := toUnixMode(mode, false) if err != nil { @@ -194,8 +186,6 @@ func (r *Root) RemoveFile(path string) error { // directory tree. // // This is effectively equivalent to [os.Remove]. -// -// [os.Remove]: https://pkg.go.dev/os#Remove func (r *Root) Remove(path string) error { // In order to match os.Remove's implementation we need to also do both // syscalls unconditionally and adjust the error based on whether @@ -219,8 +209,6 @@ func (r *Root) Remove(path string) error { // RemoveAll recursively deletes a path and all of its children. // // This is effectively equivalent to [os.RemoveAll]. -// -// [os.RemoveAll]: https://pkg.go.dev/os#RemoveAll func (r *Root) RemoveAll(path string) error { _, err := fdutils.WithFileFd(r.inner, func(rootFd uintptr) (struct{}, error) { err := libpathrs.InRootRemoveAll(rootFd, path) @@ -233,8 +221,6 @@ func (r *Root) RemoveAll(path string) error { // mode is used for the new directory (the process's umask applies). // // This is effectively equivalent to [os.Mkdir]. -// -// [os.Mkdir]: https://pkg.go.dev/os#Mkdir func (r *Root) Mkdir(path string, mode os.FileMode) error { unixMode, err := toUnixMode(mode, false) if err != nil { @@ -253,8 +239,6 @@ func (r *Root) Mkdir(path string, mode os.FileMode) error { // directories created by this function (the process's umask applies). // // This is effectively equivalent to [os.MkdirAll]. -// -// [os.MkdirAll]: https://pkg.go.dev/os#MkdirAll func (r *Root) MkdirAll(path string, mode os.FileMode) (*Handle, error) { unixMode, err := toUnixMode(mode, false) if err != nil { @@ -278,9 +262,7 @@ func (r *Root) MkdirAll(path string, mode os.FileMode) (*Handle, error) { // directory tree. The provided mode is used for the new directory (the // process's umask applies). // -// This is effectively equivalent to [unix.Mknod]. -// -// [unix.Mknod]: https://pkg.go.dev/golang.org/x/sys/unix#Mknod +// This is effectively equivalent to [golang.org/x/sys/unix.Mknod]. func (r *Root) Mknod(path string, mode os.FileMode, dev uint64) error { unixMode, err := toUnixMode(mode, true) if err != nil { @@ -298,8 +280,6 @@ func (r *Root) Mknod(path string, mode os.FileMode, dev uint64) error { // created at path and is a link to target. // // This is effectively equivalent to [os.Symlink]. -// -// [os.Symlink]: https://pkg.go.dev/os#Symlink func (r *Root) Symlink(path, target string) error { _, err := fdutils.WithFileFd(r.inner, func(rootFd uintptr) (struct{}, error) { err := libpathrs.InRootSymlink(rootFd, path, target) @@ -314,8 +294,6 @@ func (r *Root) Symlink(path, target string) error { // host). // // This is effectively equivalent to [os.Link]. -// -// [os.Link]: https://pkg.go.dev/os#Link func (r *Root) Hardlink(path, target string) error { _, err := fdutils.WithFileFd(r.inner, func(rootFd uintptr) (struct{}, error) { err := libpathrs.InRootHardlink(rootFd, path, target) @@ -327,8 +305,6 @@ func (r *Root) Hardlink(path, target string) error { // Readlink returns the target of a symlink with a [Root]'s directory tree. // // This is effectively equivalent to [os.Readlink]. -// -// [os.Readlink]: https://pkg.go.dev/os#Readlink func (r *Root) Readlink(path string) (string, error) { return fdutils.WithFileFd(r.inner, func(rootFd uintptr) (string, error) { return libpathrs.InRootReadlink(rootFd, path) @@ -345,8 +321,6 @@ func (r *Root) Readlink(path string) (string, error) { // calling [Root.Close] will also close any copies of the returned [os.File]. // If you want to get an independent copy, use [Root.Clone] followed by // [Root.IntoFile] on the cloned [Root]. -// -// [os.File]: https://pkg.go.dev/os#File func (r *Root) IntoFile() *os.File { // TODO: Figure out if we really don't want to make a copy. // TODO: We almost certainly want to clear r.inner here, but we can't do diff --git a/vendor/cyphar.com/go-pathrs/utils_linux.go b/vendor/cyphar.com/go-pathrs/utils_linux.go index 2208d608f8d..b4e7e08e7df 100644 --- a/vendor/cyphar.com/go-pathrs/utils_linux.go +++ b/vendor/cyphar.com/go-pathrs/utils_linux.go @@ -3,8 +3,8 @@ // SPDX-License-Identifier: MPL-2.0 /* * libpathrs: safe path resolution on Linux - * Copyright (C) 2019-2025 Aleksa Sarai * Copyright (C) 2019-2025 SUSE LLC + * Copyright (C) 2026 Aleksa Sarai * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/vendor/modules.txt b/vendor/modules.txt index 58dd5a1088c..c77776631ad 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,4 +1,4 @@ -# cyphar.com/go-pathrs v0.2.1 +# cyphar.com/go-pathrs v0.2.4-0.20260212074101-c4e98bea7862 ## explicit; go 1.18 cyphar.com/go-pathrs cyphar.com/go-pathrs/internal/fdutils From aacc9c6c4b8520f894420a4d81bcde17cc35ea74 Mon Sep 17 00:00:00 2001 From: Aleksa Sarai Date: Tue, 3 Feb 2026 21:31:12 +0100 Subject: [PATCH 7/9] [wip] build: enable builds with libpathrs Signed-off-by: Aleksa Sarai --- Dockerfile | 28 +++++-- script/build-libpathrs.sh | 153 ++++++++++++++++++++++++++++++++++++++ script/lib.sh | 44 +++++++---- script/release_build.sh | 3 + 4 files changed, 204 insertions(+), 24 deletions(-) create mode 100755 script/build-libpathrs.sh diff --git a/Dockerfile b/Dockerfile index 829acc42c51..ce6707b3301 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,7 @@ 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}-trixie ARG DEBIAN_FRONTEND=noninteractive @@ -9,10 +10,13 @@ ARG CRIU_REPO=https://download.opensuse.org/repositories/devel:/tools:/criu/Debi 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 \ @@ -22,6 +26,7 @@ RUN KEYFILE=/usr/share/keyrings/criu-repo-keyring.gpg; \ iptables \ jq \ kmod \ + lld \ pkg-config \ python3-minimal \ sshfs \ @@ -29,13 +34,13 @@ RUN KEYFILE=/usr/share/keyrings/criu-repo-keyring.gpg; \ 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 @@ -64,6 +69,13 @@ RUN mkdir -p $DYLIB_DIR \ && /tmp/script/build-seccomp.sh "$LIBSECCOMP_VERSION" $DYLIB_DIR $RELEASE_ARCHES ENV LIBSECCOMP_VERSION=$LIBSECCOMP_VERSION +# 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 diff --git a/script/build-libpathrs.sh b/script/build-libpathrs.sh new file mode 100755 index 00000000000..20ebedb6734 --- /dev/null +++ b/script/build-libpathrs.sh @@ -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=( + ["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 . + 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" + + # 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 [ ...]" >&2 + exit 1 +fi + +build_libpathrs "$@" diff --git a/script/lib.sh b/script/lib.sh index 89ce8c6c34e..d3e68f646f6 100644 --- a/script/lib.sh +++ b/script/lib.sh @@ -1,41 +1,53 @@ #!/bin/bash +# get_platform computes the platform section of target triples on this OS. +function get_platform() { + # Fedora doesn't have ID_LIKE and only has ID=fedora, so we need to + # construct a fake ID_LIKE to treat AlmaLinux and Fedora the same way. + local ID_LIKE + # shellcheck source=/etc/os-release + ID_LIKE="$(source /etc/os-release; echo "${ID:-} ${ID_LIKE:-}")" + + local PLATFORM + case "$ID_LIKE" in + *suse*) + PLATFORM=suse-linux + ;; + *rhel*|*fedora*|*centos*) + PLATFORM=redhat-linux + ;; + *) + PLATFORM=linux-gnu + ;; + esac + echo "$PLATFORM" +} + # set_cross_vars sets a few environment variables used for cross-compiling, # based on the architecture specified in $1. function set_cross_vars() { GOARCH="$1" # default, may be overridden below unset GOARM - PLATFORM=linux-gnu - # openSUSE has a custom PLATFORM - if grep -iq "ID_LIKE=.*suse" /etc/os-release; then - PLATFORM=suse-linux - is_suse=1 - fi + PLATFORM="$(get_platform)" + [[ "$PLATFORM" == *suse* ]] && is_suse=1 - case $1 in + case "$1" in 386) # Always use the 64-bit compiler to build the 386 binary, which works # for the more common cross-build method for x86 (namely, the # equivalent of dpkg --add-architecture). local cpu_type if [ -v is_suse ]; then - # There is no x86_64-suse-linux-gcc, so use the native one. - HOST= cpu_type=i586 else - HOST=x86_64-${PLATFORM} cpu_type=i686 fi + HOST=x86_64-${PLATFORM} CFLAGS="-m32 -march=$cpu_type ${CFLAGS[*]}" ;; amd64) - if [ -n "${is_suse:-}" ]; then - # There is no x86_64-suse-linux-gcc, so use the native one. - HOST= - else - HOST=x86_64-${PLATFORM} - fi + HOST=x86_64-${PLATFORM} ;; arm64) HOST=aarch64-${PLATFORM} diff --git a/script/release_build.sh b/script/release_build.sh index f84bd5041fd..bd4369d02cb 100755 --- a/script/release_build.sh +++ b/script/release_build.sh @@ -20,6 +20,7 @@ set -e # Project-specific options and functions. In *theory* you shouldn't need to # touch anything else in this script in order to use this elsewhere. : "${LIBSECCOMP_VERSION:=2.6.0}" +: "${LIBPATHRS_VERSION:=0.2.3}" project="runc" root="$(readlink -f "$(dirname "${BASH_SOURCE[0]}")/..")" @@ -48,6 +49,8 @@ function build_project() { dylibdir="$(mktemp -d)" # Download and build libseccomp. "$root/script/build-seccomp.sh" "$LIBSECCOMP_VERSION" "$dylibdir" "${arches[@]}" + # Download and build libpathrs. + "$root/script/build-libpathrs.sh" "$LIBPATHRS_VERSION" "$dylibdir" "${arches[@]}" fi # For reproducible builds, add these to EXTRA_LDFLAGS: From 96020b986cdc7c5c26a28d3716f031cccdf85bf7 Mon Sep 17 00:00:00 2001 From: Aleksa Sarai Date: Mon, 9 Feb 2026 10:12:48 +1100 Subject: [PATCH 8/9] ci: build and install libpathrs Signed-off-by: Aleksa Sarai --- .cirrus.yml | 6 +++++- .github/workflows/test.yml | 30 ++++++++++++++++++++++++++++-- .github/workflows/validate.yml | 7 ++++++- script/setup_host_fedora.sh | 9 +++++++-- 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index e182c61063f..2244a72ba34 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -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 @@ -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. diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b6be7321ed8..1f3cc6f3735 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -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"] @@ -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 == '' }} @@ -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 . + 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 @@ -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: diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index ab8c4e2538a..e90a486a189 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -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 diff --git a/script/setup_host_fedora.sh b/script/setup_host_fedora.sh index efe6a001dc1..e36fd0d804e 100755 --- a/script/setup_host_fedora.sh +++ b/script/setup_host_fedora.sh @@ -1,7 +1,7 @@ #!/bin/bash set -eux -o pipefail DNF=(dnf -y --setopt=install_weak_deps=False --setopt=tsflags=nodocs --exclude="kernel,kernel-core") -RPMS=(bats git-core glibc-static golang jq libseccomp-devel make) +RPMS=(bats git-core glibc-static golang jq libseccomp-devel cargo lld make) # Work around dnf mirror failures by retrying a few times. for i in $(seq 0 2); do sleep "$i" @@ -16,11 +16,16 @@ fi dnf clean all +SCRIPTDIR="$(dirname "${BASH_SOURCE[0]}")" + +LIBPATHRS_VERSION=0.2.3 +"$SCRIPTDIR"/build-libpathrs.sh "$LIBPATHRS_VERSION" /usr + # To avoid "avc: denied { nosuid_transition }" from SELinux as we run tests on /tmp. mount -o remount,suid /tmp # Setup rootless user. -"$(dirname "${BASH_SOURCE[0]}")"/setup_rootless.sh +"$SCRIPTDIR"/setup_rootless.sh # Delegate cgroup v2 controllers to rootless user via --systemd-cgroup mkdir -p /etc/systemd/system/user@.service.d From bd15ac11c071642ae02606feaf9ea4a2f27d2375 Mon Sep 17 00:00:00 2001 From: Aleksa Sarai Date: Wed, 4 Feb 2026 18:38:02 +0100 Subject: [PATCH 9/9] build: enable libpathrs by default Signed-off-by: Aleksa Sarai --- Makefile | 2 +- README.md | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index dba7d7a8f81..91b4b84a99b 100644 --- a/Makefile +++ b/Makefile @@ -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) diff --git a/README.md b/README.md index bca08c2d284..84f6b9e9c33 100644 --- a/README.md +++ b/README.md @@ -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: @@ -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.