From 7cbd782490aa92cd4e1ee91944fe63beadd97c1e Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Thu, 1 Oct 2026 22:14:25 -0700 Subject: [PATCH 1/2] go: let sandlock.pc.in take its libdir from the caller The template hardcoded ${exec_prefix}/lib, which is wrong for RPM-based distros, where 64-bit libraries live in /usr/lib64. libdir is now an @LIBDIR@ placeholder; the Makefile fills in the same ${exec_prefix}/lib as before, so the Go library tree it stages is unchanged. Signed-off-by: Cong Wang --- Makefile | 3 ++- go/sandlock.pc.in | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 05ba146bd..c7a2059c3 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,8 @@ install-go-lib: ffi install -Dm755 target/release/libsandlock_ffi.so $(LIBDIR)/libsandlock_ffi.so install -Dm644 crates/sandlock-ffi/include/sandlock.h $(INCLUDEDIR)/sandlock.h install -d $(PCDIR) - sed -e 's|@PREFIX@|$(PREFIX)|g' -e 's|@VERSION@|$(VERSION)|g' \ + sed -e 's|@PREFIX@|$(PREFIX)|g' -e 's|@LIBDIR@|$${exec_prefix}/lib|g' \ + -e 's|@VERSION@|$(VERSION)|g' \ go/sandlock.pc.in > $(PCDIR)/sandlock.pc uninstall-go-lib: diff --git a/go/sandlock.pc.in b/go/sandlock.pc.in index a7b8b754a..746152eee 100644 --- a/go/sandlock.pc.in +++ b/go/sandlock.pc.in @@ -1,6 +1,6 @@ prefix=@PREFIX@ exec_prefix=${prefix} -libdir=${exec_prefix}/lib +libdir=@LIBDIR@ includedir=${prefix}/include Name: sandlock From 4010ebf112213f4c6707270c28f7f8542ae82deb Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Thu, 1 Oct 2026 22:14:25 -0700 Subject: [PATCH 2/2] release: build .deb and .rpm packages Attach .deb and .rpm packages per arch to each GitHub Release, so users on Debian/Ubuntu and Fedora/RHEL can install sandlock with their package manager instead of unpacking a tarball. They are built from the existing release binaries with nfpm (pinned by version and checksum) and are not submitted to any distro. The CLI does not link libsandlock_ffi, so the library ships separately: sandlock carries the CLI, sandlock-oci and the license, and sandlock-dev (sandlock-devel for .rpm) carries libsandlock_ffi.so with sandlock.h and sandlock.pc for C and Go SDK builds. The library has no SONAME, so there is no versioned runtime library to split off from the header. The library and .pc file go to /usr/lib for .deb and /usr/lib64 for .rpm, since Fedora and RHEL only search the latter. The binaries need glibc 2.34, which covers Ubuntu 22.04, Debian 12 and RHEL 9 onwards. On x86_64 the job installs both packages, the .rpm in a Rocky 9 container, and runs a sandboxed command before the release picks them up. riscv64 packages are experimental, like the riscv64 build. Signed-off-by: Cong Wang --- .github/workflows/release.yml | 68 +++++++++++++++++++++++++++++++++-- packaging/build.sh | 27 ++++++++++++++ packaging/nfpm-dev.yaml | 65 +++++++++++++++++++++++++++++++++ packaging/nfpm.yaml | 44 +++++++++++++++++++++++ 4 files changed, 202 insertions(+), 2 deletions(-) create mode 100755 packaging/build.sh create mode 100644 packaging/nfpm-dev.yaml create mode 100644 packaging/nfpm.yaml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ebec8e681..c27e77262 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -79,6 +79,67 @@ jobs: name: sandlock-${{ matrix.target }} path: sandlock-${{ matrix.target }}.tar.gz + # Wrap each arch's release build in a .deb and an .rpm for the GitHub + # Release. They are not submitted to any distro. + packages: + name: Packages (${{ matrix.target }}) + needs: build + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.experimental || false }} + strategy: + fail-fast: false + matrix: + include: + - target: x86_64-unknown-linux-gnu + goarch: amd64 + - target: aarch64-unknown-linux-gnu + goarch: arm64 + - target: riscv64gc-unknown-linux-gnu + goarch: riscv64 + experimental: true + env: + NFPM_VERSION: 2.47.0 + NFPM_SHA256: 0660ca602b2d2d2ae4781a06c692b3eeb9d437ffea05b831d76e41f4a3188783 + steps: + - uses: actions/checkout@v4 + + - name: Download build + uses: actions/download-artifact@v4 + with: + name: sandlock-${{ matrix.target }} + + - name: Install nfpm + run: | + tarball=nfpm_${NFPM_VERSION}_Linux_x86_64.tar.gz + curl -fsSLO "https://github.com/goreleaser/nfpm/releases/download/v${NFPM_VERSION}/${tarball}" + echo "${NFPM_SHA256} ${tarball}" | sha256sum -c + sudo tar -xzf "${tarball}" -C /usr/local/bin nfpm + + - name: Build packages + run: | + mkdir bin && tar -xzf sandlock-${{ matrix.target }}.tar.gz -C bin + version=$(sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml | head -1) + packaging/build.sh bin "$version" ${{ matrix.goarch }} dist + + # Only the runner's own arch can be installed and run here. + - name: Smoke-test the .deb and .rpm + if: matrix.goarch == 'amd64' + run: | + smoke='set -e; sandlock --version + sandlock run -r /usr -r /lib -r /lib64 -r /bin -r /etc -- /bin/echo ok + pkg-config --exists sandlock; ldconfig -p | grep -q libsandlock_ffi' + sudo apt-get update + sudo apt-get install -y ./dist/*.deb pkg-config + sh -c "$smoke" + docker run --rm --security-opt seccomp=unconfined -v "$PWD/dist:/dist:ro" rockylinux:9 \ + sh -c "dnf install -y -q /dist/*.rpm pkgconf-pkg-config && $smoke" + + - name: Upload + uses: actions/upload-artifact@v4 + with: + name: packages-${{ matrix.target }} + path: dist/* + # Build Python sdist (includes setup.py that builds Rust on install) sdist: name: Build Python sdist @@ -335,7 +396,7 @@ jobs: # Create GitHub Release with Rust binaries github-release: name: GitHub Release - needs: [build, test, go-libs] + needs: [build, test, go-libs, packages] # Only cut a GitHub Release on a real tag push, not on a manual # workflow_dispatch (which has no tag to attach assets to). if: github.event_name == 'push' @@ -351,5 +412,8 @@ jobs: - name: Create Release uses: softprops/action-gh-release@v2 with: - files: artifacts/**/*.tar.gz + files: | + artifacts/**/*.tar.gz + artifacts/**/*.deb + artifacts/**/*.rpm generate_release_notes: true diff --git a/packaging/build.sh b/packaging/build.sh new file mode 100755 index 000000000..3feeea220 --- /dev/null +++ b/packaging/build.sh @@ -0,0 +1,27 @@ +#!/bin/sh +# Usage: packaging/build.sh +# holds a release build's sandlock, sandlock-oci and libsandlock_ffi.so. +set -eu + +bindir=$1 version=$2 arch=$3 outdir=$4 +root=$(cd "$(dirname "$0")/.." && pwd) +stage=$(mktemp -d) +trap 'rm -rf "$stage"' EXIT + +cp "$bindir/sandlock" "$bindir/sandlock-oci" "$bindir/libsandlock_ffi.so" "$stage/" +cp "$root/crates/sandlock-ffi/include/sandlock.h" "$root/LICENSE" "$stage/" +for lib in lib lib64; do + sed -e 's|@PREFIX@|/usr|g' -e "s|@LIBDIR@|\${exec_prefix}/$lib|g" -e "s|@VERSION@|$version|g" \ + "$root/go/sandlock.pc.in" > "$stage/sandlock-$lib.pc" +done + +mkdir -p "$outdir" +outdir=$(cd "$outdir" && pwd) +cd "$stage" +for fmt in deb rpm; do + case $fmt in deb) dev=sandlock-dev ;; rpm) dev=sandlock-devel ;; esac + VERSION=$version ARCH=$arch \ + nfpm package -f "$root/packaging/nfpm.yaml" -p "$fmt" -t "$outdir/" + NAME=$dev VERSION=$version ARCH=$arch \ + nfpm package -f "$root/packaging/nfpm-dev.yaml" -p "$fmt" -t "$outdir/" +done diff --git a/packaging/nfpm-dev.yaml b/packaging/nfpm-dev.yaml new file mode 100644 index 000000000..2f3ee3747 --- /dev/null +++ b/packaging/nfpm-dev.yaml @@ -0,0 +1,65 @@ +# Driven by packaging/build.sh, which runs nfpm from the staging directory. +# NAME is sandlock-dev for .deb and sandlock-devel for .rpm. +name: ${NAME} +version: ${VERSION} +arch: ${ARCH} +platform: linux +section: libdevel +priority: optional +maintainer: Cong Wang +description: | + Development files for the sandlock C library + libsandlock_ffi, its header and its pkg-config file, for building programs + (including ones using the Go SDK) that embed the sandlock sandbox. +homepage: https://github.com/multikernel/sandlock +license: Apache-2.0 + +contents: + - src: ./sandlock.h + dst: /usr/include/sandlock.h + file_info: {mode: 0644} + - src: ./LICENSE + dst: /usr/share/doc/sandlock-dev/copyright + file_info: {mode: 0644} + packager: deb + - src: ./LICENSE + dst: /usr/share/licenses/sandlock-devel/LICENSE + type: license + file_info: {mode: 0644} + packager: rpm + + # Fedora and RHEL only search /usr/lib64 for 64-bit libraries. + - src: ./libsandlock_ffi.so + dst: /usr/lib/libsandlock_ffi.so + file_info: {mode: 0755} + packager: deb + - src: ./sandlock-lib.pc + dst: /usr/lib/pkgconfig/sandlock.pc + file_info: {mode: 0644} + packager: deb + - src: ./libsandlock_ffi.so + dst: /usr/lib64/libsandlock_ffi.so + file_info: {mode: 0755} + packager: rpm + - src: ./sandlock-lib64.pc + dst: /usr/lib64/pkgconfig/sandlock.pc + file_info: {mode: 0644} + packager: rpm + +overrides: + deb: + depends: + - libc6 (>= 2.34) + - libgcc-s1 + rpm: + depends: + - glibc >= 2.34 + - libgcc + +deb: + triggers: + activate_noawait: + - ldconfig + +rpm: + group: Development/Libraries diff --git a/packaging/nfpm.yaml b/packaging/nfpm.yaml new file mode 100644 index 000000000..c55b70b78 --- /dev/null +++ b/packaging/nfpm.yaml @@ -0,0 +1,44 @@ +# Driven by packaging/build.sh, which runs nfpm from the staging directory. +name: sandlock +version: ${VERSION} +arch: ${ARCH} +platform: linux +section: admin +priority: optional +maintainer: Cong Wang +description: | + Lightweight process sandbox for Linux + Confines a process with Landlock, seccomp and seccomp user notification, + without root, containers or VMs. +homepage: https://github.com/multikernel/sandlock +license: Apache-2.0 + +contents: + - src: ./sandlock + dst: /usr/bin/sandlock + file_info: {mode: 0755} + - src: ./sandlock-oci + dst: /usr/bin/sandlock-oci + file_info: {mode: 0755} + - src: ./LICENSE + dst: /usr/share/doc/sandlock/copyright + file_info: {mode: 0644} + packager: deb + - src: ./LICENSE + dst: /usr/share/licenses/sandlock/LICENSE + type: license + file_info: {mode: 0644} + packager: rpm + +overrides: + deb: + depends: + - libc6 (>= 2.34) + - libgcc-s1 + rpm: + depends: + - glibc >= 2.34 + - libgcc + +rpm: + group: System Environment/Base