Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
e96c495
feat(execd): custom-policy + drift e2e and ebpf bare smoke (OSEP-0018…
Pangjiping Aug 18, 2026
b701a29
docs(osep-0018): decline R-a trusted stop channel; keep kill 1 SIGTER…
Pangjiping Aug 18, 2026
938defb
test(execd): close R-l(b)/R-m/R-u e2e gaps (OSEP-0018)
Pangjiping Aug 18, 2026
6fe0f51
fix(e2e): runtime-stop marker path must not use $OPENSANDBOX_ID
Pangjiping Aug 18, 2026
c36c1b1
ci(execd): wire eBPF bare-container smoke into the smoke job (OSEP-00…
Pangjiping Aug 18, 2026
2d31232
ci(execd): drop OSEP reference from eBPF smoke step name
Pangjiping Aug 18, 2026
94fe1bb
test(execd): drop inline OSEP-0018 references from comments
Pangjiping Aug 18, 2026
9401811
fix(ebpf): load each audit hook independently — fail-open per layer
Pangjiping Aug 18, 2026
b73f231
fix(e2e): smoke audit file must be readable by the host runner
Pangjiping Aug 18, 2026
f2890dc
fix(e2e): smoke dumps container logs on partial hook degrade
Pangjiping Aug 18, 2026
ec6829e
fix(e2e): capture report probe exit code under set -euo pipefail
Pangjiping Aug 18, 2026
4af1bd1
fix(e2e): smoke dumps full container log on hook degrade
Pangjiping Aug 19, 2026
33092aa
ci(ebpf): add per-arch bytecode regeneration + freshness check
Pangjiping Aug 19, 2026
49f2cae
ci(ebpf): fetch per-arch vmlinux.h via CI artifact for bytecode regen…
Pangjiping Aug 19, 2026
bb65082
ci(ebpf): use the bpftool package instead of linux-tools-generic
Pangjiping Aug 19, 2026
3a67111
ci(ebpf): simplify to one-shot vmlinux.h dump for committing
Pangjiping Aug 19, 2026
5de41f4
feat(ebpf): generate CO-RE bytecode per TARGETARCH in the build flow
Pangjiping Aug 19, 2026
76dbf15
feat(ebpf): commit vmlinux-x86_64.h, drop the temporary CI fetch step
Pangjiping Aug 19, 2026
e5875d0
fix(ebpf): correct vmlinux.h/bpf2go paths in the Dockerfile builder
Pangjiping Aug 19, 2026
d449757
feat(ebpf): vendor libbpf headers into prog/bpf for hermetic bpf2go
Pangjiping Aug 19, 2026
09bdaea
fix(ebpf): remove the generic audit_bpfel/eb generated files
Pangjiping Aug 19, 2026
8fe79a4
ci(ebpf): regenerate per-arch bytecode before running ebpf tests
Pangjiping Aug 19, 2026
0e70121
fix(ebpf): fix generate-ebpf recipe variable scope and paths
Pangjiping Aug 19, 2026
8514b5d
ci: retrigger execd tests (previous run stuck in queued)
Pangjiping Aug 19, 2026
4e8d9db
feat(ebpf): replace per-arch vmlinux.h with a minimal audit_types.h
Pangjiping Aug 19, 2026
19867b8
chore: remove accidentally committed execd launcher debug binary
Pangjiping Aug 19, 2026
92430ee
fix(ebpf): restore ARG TARGETARCH in the ebpf-builder stage
Pangjiping Aug 19, 2026
2b741f5
fix(ebpf): add types referenced by bpf_helper_defs.h prototypes
Pangjiping Aug 19, 2026
6872e0d
fix(ebpf): pt_regs uses rdi (not di) and add uint*_t + ringbuf map type
Pangjiping Aug 19, 2026
884b00c
fix(ebpf): review feedback — degraded state, strict smoke assertions,…
Pangjiping Aug 19, 2026
52d8f90
docs(osep-0018): mark R-c/R-j implemented, update status header + R-h
Pangjiping Aug 19, 2026
1e9907c
docs(osep-0018): slim the implementation status to remaining items
Pangjiping Aug 19, 2026
0f3797f
docs(osep-0018): drop the all-green phase table and resolved-question…
Pangjiping Aug 19, 2026
f0a3cf8
Merge branch 'main' into feat/execd-hardening-custom-policy-drift-e2e
hittyt Aug 19, 2026
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
4 changes: 3 additions & 1 deletion .github/workflows/detect-changes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ jobs:
path === "scripts/python-k8s-execd-init-e2e.sh" ||
path === "tests/python/tests/test_execd_init_e2e.py" ||
path === "tests/python/tests/test_execd_hardening_e2e.py" ||
path === "tests/python/tests/test_execd_k8s_restart_recycle_e2e.py" ||
path === "server/opensandbox_server/examples/e2e.batchsandbox-template.yaml" ||
path.startsWith("components/execd/") ||
path.startsWith("kubernetes/charts/"),
Expand All @@ -89,7 +90,8 @@ jobs:
execd: (path) =>
workflowChanged(path, "execd-test.yml") ||
path.startsWith("components/execd/") ||
path.startsWith("components/internal/"),
path.startsWith("components/internal/") ||
path === "scripts/execd-ebpf-smoke.sh",
Comment thread
Pangjiping marked this conversation as resolved.
nodeagent: (path) =>
workflowChanged(path, "nodeagent-test.yml") ||
path.startsWith("components/nodeagent/") ||
Expand Down
35 changes: 30 additions & 5 deletions .github/workflows/execd-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,20 @@ jobs:
- name: Run execd-ebpf variant tests
working-directory: components/execd
run: |
# Regenerate the per-arch bytecode first: the generated files are
# build artifacts (not committed), so local tests need them too.
sudo apt-get update -qq && sudo apt-get install -y -qq clang >/dev/null
make generate-ebpf ARCH=$(go env GOARCH)
CGO_ENABLED=1 go test -tags ebpf -count=1 ./pkg/ebpf/

- name: Upload per-arch vmlinux.h (for bytecode regeneration)
if: runner.os == 'Linux' && always()
uses: actions/upload-artifact@v7
with:
name: vmlinux-${{ runner.arch }}
path: /tmp/ebpf-dump/vmlinux.h
if-no-files-found: ignore

- name: Calculate coverage and generate summary
working-directory: components/execd
id: coverage
Expand All @@ -84,7 +96,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
os: [ubuntu-latest, windows-latest, self-hosted]
runs-on: ${{ matrix.os }}
defaults:
run:
Expand Down Expand Up @@ -135,14 +147,27 @@ jobs:
chmod +x components/execd/tests/smoke_bwrap.sh
bash components/execd/tests/smoke_bwrap.sh

- name: Init-mode container regression (OSEP-0018)
- name: Init-mode container regression
if: matrix.os == 'ubuntu-latest'
shell: bash
timeout-minutes: 30
run: |
chmod +x components/execd/tests/init_container.sh
bash components/execd/tests/init_container.sh

- name: Execd eBPF bare-container smoke
if: matrix.os != 'windows-latest'
shell: bash
timeout-minutes: 30
run: |
# Runs the execd-ebpf variant in a bare container against THIS
# runner's kernel and asserts exec/connect/privilege events land in
# the JSONL audit file. GitHub-hosted ubuntu validates the stock CI
# kernel; the self-hosted leg is the 5.10 empirical validation
# (inline-filename exec-hook fallback). Host prerequisites (BTF,
# cgroup v2, tracefs) are prechecked by the script.
bash scripts/execd-ebpf-smoke.sh --build

- name: Show logs
if: always()
run: |
Expand Down Expand Up @@ -240,9 +265,9 @@ jobs:
- name: Run isolated session init-mode reaper integration test
working-directory: components/execd
run: |
# bwrap lifecycle under init-mode reaper dispatch (OSEP-0018 R-o):
# the pre-reap barrier must serialize process-group teardown with
# the reaper's observe/consume while execd owns wait4.
# bwrap lifecycle under init-mode reaper dispatch: the pre-reap
# barrier must serialize process-group teardown with the reaper's
# observe/consume while execd owns wait4.
sudo -E env "PATH=$PATH" go test \
-tags="linux,bwrap" -v -count=1 -timeout=3m \
-run '^TestIsolatedSessionWithInitReaper$' \
Expand Down
16 changes: 16 additions & 0 deletions components/execd/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,17 @@ RUN rm /usr/lib/libcap.so /usr/lib/libcap.so.2 && \
# defaulting to /opt/opensandbox/execd). The variant attaches
# exec/connect/privilege audit hooks and needs CAP_BPF + CAP_PERFMON in the
# container ceiling.
#
# The CO-RE audit bytecode is REGENERATED here at image build time with
# bpf2go. prog/audit_types.h declares only the kernel members the programs
# touch (resolved by name against the target kernel BTF at load time), so
# no per-arch vmlinux.h or host kernel BTF is needed — this stage is fully
# hermetic and cross-compiles for every TARGETARCH.
FROM golang:1.25.9 AS ebpf-builder
ARG VERSION=dev
ARG GIT_COMMIT=unknown
ARG BUILD_TIME=unknown
ARG TARGETARCH
RUN apt-get update && apt-get install -y --no-install-recommends clang
WORKDIR /build
COPY components/internal/go.mod components/internal/go.sum ./components/internal/
Expand All @@ -115,6 +122,15 @@ RUN cd components/execd && go mod download
COPY components/internal ./components/internal
COPY components/execd ./components/execd
WORKDIR /build/components/execd
# Generate the CO-RE bytecode for this TARGETARCH (bpf2go embeds it into
# audit_bpf_<arch>.go, picked up by the Go build tags). clang's bpf target
# only — no host kernel BTF.
RUN go run github.com/cilium/ebpf/cmd/bpf2go@v0.16.0 \
-cc clang -no-strip \
-cflags "-Ipkg/ebpf/prog" \
-target "${TARGETARCH}" \
-go-package ebpf -output-dir pkg/ebpf \
audit pkg/ebpf/prog/audit.bpf.c
# cilium/ebpf is pure Go, so the variant builds fully static.
RUN CGO_ENABLED=0 go build -tags ebpf -trimpath -buildvcs=false \
-ldflags "-buildid= -B none \
Expand Down
26 changes: 26 additions & 0 deletions components/execd/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,35 @@ build-ebpf: ## Build the execd-ebpf observation variant (CGO + cilium/ebpf).
exit 1; \
fi
@mkdir -p bin
$(MAKE) generate-ebpf ARCH=$(shell go env GOARCH)
CGO_ENABLED=1 go build -tags ebpf $(GO_BUILD_FLAGS) -ldflags "$(GO_LDFLAGS)" -o bin/execd-ebpf main.go
@echo "built bin/execd-ebpf"

# Regenerate the CO-RE audit bytecode for one architecture from
# prog/audit.bpf.c + prog/audit_types.h. The types header declares only the
# kernel members the programs touch (resolved by name against the target
# kernel BTF at load time), so no vmlinux.h is needed and the bytecode is
# hermetic across architectures (issue #1563).
#
# make generate-ebpf ARCH=amd64 # or arm64; defaults to GOARCH
#
# Requires clang with the bpf target. bpf2go writes audit_bpf_<target>.{go,o};
# the Go build picks the right one via build tags.
.PHONY: generate-ebpf
ARCH ?= $(shell go env GOARCH)
generate-ebpf:
@case "$(ARCH)" in \
amd64|arm64) ;; \
*) echo "generate-ebpf: unsupported ARCH=$(ARCH) (amd64|arm64)" >&2; exit 1 ;; \
esac
go run github.com/cilium/ebpf/cmd/bpf2go@v0.16.0 \
-cc clang -no-strip \
-cflags "-Ipkg/ebpf/prog" \
-target $(ARCH) \
-go-package ebpf -output-dir pkg/ebpf \
audit pkg/ebpf/prog/audit.bpf.c
@echo "regenerated pkg/ebpf/audit_bpf_$(ARCH).{go,o}"

.PHONY: test-integration
test-integration: ## Run integration tests (Linux + bwrap required).
go test -v -tags="linux,bwrap" -run Integration ./pkg/runtime/bwrap_test/
Expand Down
29 changes: 29 additions & 0 deletions components/execd/configs/isolation.custom.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Copyright 2026 Alibaba Group Holding Ltd.
#
# 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.

# Custom-policy hardening configuration for the execd-as-init e2e: a
# [seccomp] deny override (which REPLACES the built-in denylist) plus
# keep_capabilities. Proves both overrides reach the workload:
# - the denied syscall family (chmod/fchmodat/fchmodat2; glibc coreutils
# chmod uses fchmodat, busybox uses chmod) fails with EACCES in /command
# - CAP_NET_RAW (bit 13) is raised in the ambient set and survives execve,
# so the workload reports CapEff=0x2000
# Landlock stays off: this variant is about the seccomp/caps overrides only.

[hardening]
enabled = true
keep_capabilities = ["CAP_NET_RAW"]

[seccomp]
deny = ["chmod", "fchmodat", "fchmodat2"]
Loading
Loading