Fix capabilities

This commit is contained in:
Samuel Aubertin
2026-03-09 21:34:06 +01:00
parent 87a23e9772
commit 1e97baa534
3 changed files with 781 additions and 71 deletions

View File

@@ -211,6 +211,33 @@ teardown_stub_env() {
rm -f "${STUB_LOG:-}"
}
extract_embedded_helper() {
local helper=$1
local output=$2
if ! awk -v helper="$helper" '
$0 ~ "^[[:space:]]*" helper "\\)$" { state=1; next }
state == 1 && /cat <<'\''EOF'\''$/ { state=2; next }
state == 2 && /^EOF$/ { exit }
state == 2 { print }
' "$SLOPTRAP_BIN" >"$output"; then
return 1
fi
chmod +x "$output"
}
wait_for_path() {
local path=$1
local attempts=${2:-100}
while (( attempts > 0 )); do
if [[ -e $path ]]; then
return 0
fi
sleep 0.1
((attempts-=1))
done
return 1
}
record_failure() {
failures+=("$1")
}
@@ -302,6 +329,22 @@ run_secret_mask() {
teardown_stub_env
}
run_git_ignore_mask() {
local scenario_dir="$ROOT_DIR"
printf '==> git_ignore_mask\n'
setup_stub_env
if ! PATH="$STUB_BIN:$PATH" HOME="$STUB_HOME" FAKE_PODMAN_LOG="$STUB_LOG" FAKE_PODMAN_INSPECT_FAIL=1 \
"$SLOPTRAP_BIN" --trust-capabilities "$scenario_dir" </dev/null >/dev/null 2>&1; then
record_failure "git_ignore_mask: sloptrap exited non-zero"
teardown_stub_env
return
fi
if ! grep -q -- "--mount type=tmpfs,target=/workspace/.git" "$STUB_LOG"; then
record_failure "git_ignore_mask: .git was not masked with tmpfs"
fi
teardown_stub_env
}
run_resume_target() {
local scenario_dir="$TEST_ROOT/resume_target"
printf '==> resume_target\n'
@@ -335,10 +378,9 @@ run_runtime_context_prompt() {
if [[ -z $run_line || $run_line != *"You are running inside sloptrap"* ]]; then
record_failure "runtime_context_prompt: startup prompt missing from fresh run"
fi
if ! grep -q -- "manifest_present=true" "$STUB_LOG" \
|| ! grep -q -- "manifest_capabilities=apt-install nested-podman packet-capture" "$STUB_LOG" \
|| ! grep -q -- "trusted_capabilities=apt-install nested-podman packet-capture" "$STUB_LOG" \
|| ! grep -q -- "enabled_capabilities=apt-install nested-podman packet-capture" "$STUB_LOG"; then
if ! grep -q -- "name=capability-repo" "$STUB_LOG" \
|| ! grep -q -- "enabled_capabilities=apt-install nested-podman packet-capture" "$STUB_LOG" \
|| ! grep -q -- "network_mode=host" "$STUB_LOG"; then
record_failure "runtime_context_prompt: runtime summary missing manifest or capability state"
fi
if [[ -n $login_line && $login_line == *"You are running inside sloptrap"* ]]; then
@@ -690,7 +732,7 @@ run_capability_profiles() {
teardown_stub_env
return
fi
if ! grep -q -- "CAPABILITY_PACKAGES=tcpdump podman fuse-overlayfs slirp4netns" "$STUB_LOG"; then
if ! grep -q -- "CAPABILITY_PACKAGES=tcpdump podman uidmap fuse-overlayfs slirp4netns" "$STUB_LOG"; then
record_failure "capability_profiles: build arg for capability packages missing"
fi
if ! grep -q -- "--cap-add NET_RAW" "$STUB_LOG"; then
@@ -702,21 +744,279 @@ run_capability_profiles() {
if ! grep -q -- "--device /dev/fuse" "$STUB_LOG"; then
record_failure "capability_profiles: /dev/fuse device missing"
fi
if ! grep -q -- "--cap-add SETUID" "$STUB_LOG"; then
record_failure "capability_profiles: SETUID capability missing"
fi
if ! grep -q -- "--cap-add SETGID" "$STUB_LOG"; then
record_failure "capability_profiles: SETGID capability missing"
fi
if ! grep -q -- "--cap-add CHOWN" "$STUB_LOG"; then
record_failure "capability_profiles: CHOWN capability missing"
fi
if ! grep -q -- "--cap-add DAC_OVERRIDE" "$STUB_LOG"; then
record_failure "capability_profiles: DAC_OVERRIDE capability missing"
fi
if ! grep -q -- "--cap-add FOWNER" "$STUB_LOG"; then
record_failure "capability_profiles: FOWNER capability missing"
fi
if grep -q -- "--read-only" "$STUB_LOG"; then
record_failure "capability_profiles: apt profile should disable read-only rootfs"
fi
if grep -q -- "--user " "$STUB_LOG"; then
record_failure "capability_profiles: capability-enabled run should not force --user"
fi
if ! grep -q -- "--userns=keep-id:uid=$(id -u),gid=$(id -g)" "$STUB_LOG"; then
record_failure "capability_profiles: podman keep-id user namespace missing"
fi
if ! grep -q -- "SLOPTRAP_ACTIVE_CAPABILITIES=apt-install nested-podman packet-capture" "$STUB_LOG"; then
record_failure "capability_profiles: active capability environment missing"
fi
if ! grep -q -- "SLOPTRAP_HOST_UID=$(id -u)" "$STUB_LOG"; then
record_failure "capability_profiles: host uid environment missing"
fi
if ! grep -q -- "SLOPTRAP_HOST_GID=$(id -g)" "$STUB_LOG"; then
record_failure "capability_profiles: host gid environment missing"
fi
if ! grep -q -- "SLOPTRAP_INNER_PODMAN_HOST_NETWORK=1" "$STUB_LOG"; then
record_failure "capability_profiles: inner podman host-network mirror flag missing"
fi
local state_root capability_dir
state_root="$STUB_HOME/.codex/sloptrap/state"
capability_dir=$(find "$state_root" -mindepth 2 -maxdepth 2 -type d -name capabilities | head -n 1 || true)
if [[ -z $capability_dir ]]; then
record_failure "capability_profiles: project capability state directory missing"
else
if [[ ! -d $capability_dir/podman-storage ]]; then
record_failure "capability_profiles: nested podman storage state missing"
fi
if [[ ! -d $capability_dir/podman-run ]]; then
record_failure "capability_profiles: nested podman runroot state missing"
fi
if [[ ! -d $capability_dir/podman-runtime ]]; then
record_failure "capability_profiles: nested podman runtime state missing"
fi
fi
teardown_stub_env
}
run_embedded_capability_helpers() {
printf '==> embedded_capability_helpers\n'
local temp_root helper_bin helper_dir workspace_dir capture_dir tool_log helper_pid
local inner_podman_root inner_podman_runroot inner_runtime_dir
temp_root=$(mktemp -d)
helper_bin="$temp_root/bin"
helper_dir="$temp_root/helper"
workspace_dir="$temp_root/workspace"
capture_dir="$temp_root/captures"
tool_log="$temp_root/tool.log"
inner_podman_root="$temp_root/podman-storage"
inner_podman_runroot="$temp_root/podman-run"
inner_runtime_dir="$temp_root/podman-runtime"
helper_pid=""
mkdir -p "$helper_bin" "$helper_dir/queue" "$workspace_dir/data" "$capture_dir" \
"$inner_podman_root" "$inner_podman_runroot" "$inner_runtime_dir"
: >"$tool_log"
if ! extract_embedded_helper "sloptrap-entrypoint" "$helper_bin/sloptrap-entrypoint" \
|| ! extract_embedded_helper "sloptrap-helperd" "$helper_bin/sloptrap-helperd" \
|| ! extract_embedded_helper "slop-apt" "$helper_bin/slop-apt" \
|| ! extract_embedded_helper "slopcap" "$helper_bin/slopcap" \
|| ! extract_embedded_helper "sloppodman" "$helper_bin/sloppodman"; then
record_failure "embedded_capability_helpers: failed to extract embedded helper scripts"
rm -rf "$temp_root"
return
fi
cat >"$helper_bin/podman" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
printf 'podman %s\n' "$*" >>"$TEST_TOOL_LOG"
exit 0
EOF
cat >"$helper_bin/apt-get" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
printf 'apt-get %s\n' "$*" >>"$TEST_TOOL_LOG"
exit 0
EOF
cat >"$helper_bin/tcpdump" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
printf 'tcpdump %s\n' "$*" >>"$TEST_TOOL_LOG"
output=""
prev=""
for arg in "$@"; do
if [[ $prev == "-w" ]]; then
output=$arg
break
fi
prev=$arg
done
if [[ -n $output ]]; then
mkdir -p "$(dirname "$output")"
: >"$output"
fi
exit 0
EOF
cat >"$helper_bin/setpriv" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
while [[ $# -gt 0 ]]; do
case "$1" in
--reuid|--regid)
shift 2
;;
--clear-groups)
shift
;;
--)
shift
break
;;
*)
break
;;
esac
done
exec "$@"
EOF
chmod +x "$helper_bin/podman" "$helper_bin/apt-get" "$helper_bin/tcpdump" "$helper_bin/setpriv"
if ! grep -q "chmod 711 \"\\\$helper_dir\"" "$helper_bin/sloptrap-entrypoint" \
|| ! grep -q "chown \"\\\$target_uid:\\\$target_gid\" \"\\\$queue_dir\"" "$helper_bin/sloptrap-entrypoint"; then
record_failure "embedded_capability_helpers: entrypoint did not expose helper queue to the dropped user"
fi
local autostart_helper_dir
autostart_helper_dir="$temp_root/helper-autostart"
if ! TEST_TOOL_LOG="$tool_log" PATH="$helper_bin:$PATH" SLOPTRAP_HELPER_DIR="$autostart_helper_dir" \
SLOPTRAP_ACTIVE_CAPABILITIES="apt-install packet-capture" \
SLOPTRAP_CAPTURE_DIR="$capture_dir" SLOPTRAP_WORKDIR="$workspace_dir" \
SLOPTRAP_AUDIT_LOG="$temp_root/autostart-audit.log" \
SLOPTRAP_HOST_UID="$(id -u)" SLOPTRAP_HOST_GID="$(id -g)" \
"$helper_bin/slop-apt" install jq >/dev/null 2>&1; then
record_failure "embedded_capability_helpers: slop-apt did not self-bootstrap the helper daemon"
fi
if [[ ! -r $autostart_helper_dir/helperd.pid ]]; then
record_failure "embedded_capability_helpers: helper self-bootstrap did not create a pid file"
else
kill "$(cat "$autostart_helper_dir/helperd.pid")" >/dev/null 2>&1 || true
wait "$(cat "$autostart_helper_dir/helperd.pid")" >/dev/null 2>&1 || true
fi
local missing_cap_status=0
if TEST_TOOL_LOG="$tool_log" PATH="$helper_bin:$PATH" SLOPTRAP_ACTIVE_CAPABILITIES="" \
SLOPTRAP_WORKDIR="$workspace_dir" \
SLOPTRAP_INNER_PODMAN_ROOT="$inner_podman_root" \
SLOPTRAP_INNER_PODMAN_RUNROOT="$inner_podman_runroot" \
XDG_RUNTIME_DIR="$inner_runtime_dir" \
"$helper_bin/sloppodman" ps >/dev/null 2>&1; then
record_failure "embedded_capability_helpers: sloppodman should reject runs without nested-podman"
else
missing_cap_status=$?
fi
if [[ $missing_cap_status -ne 126 ]]; then
record_failure "embedded_capability_helpers: sloppodman returned the wrong status when capability was absent"
fi
if TEST_TOOL_LOG="$tool_log" PATH="$helper_bin:$PATH" SLOPTRAP_ACTIVE_CAPABILITIES="nested-podman" \
SLOPTRAP_WORKDIR="$workspace_dir" \
SLOPTRAP_INNER_PODMAN_ROOT="$inner_podman_root" \
SLOPTRAP_INNER_PODMAN_RUNROOT="$inner_podman_runroot" \
XDG_RUNTIME_DIR="$inner_runtime_dir" \
"$helper_bin/sloppodman" run --privileged example/image >/dev/null 2>&1; then
record_failure "embedded_capability_helpers: sloppodman allowed --privileged"
fi
if TEST_TOOL_LOG="$tool_log" PATH="$helper_bin:$PATH" SLOPTRAP_ACTIVE_CAPABILITIES="nested-podman" \
SLOPTRAP_WORKDIR="$workspace_dir" \
SLOPTRAP_INNER_PODMAN_ROOT="$inner_podman_root" \
SLOPTRAP_INNER_PODMAN_RUNROOT="$inner_podman_runroot" \
XDG_RUNTIME_DIR="$inner_runtime_dir" \
"$helper_bin/sloppodman" run -v /tmp:/host example/image >/dev/null 2>&1; then
record_failure "embedded_capability_helpers: sloppodman allowed an out-of-workspace bind mount"
fi
if ! (
cd "$workspace_dir" && TEST_TOOL_LOG="$tool_log" PATH="$helper_bin:$PATH" \
SLOPTRAP_ACTIVE_CAPABILITIES="nested-podman" SLOPTRAP_WORKDIR="$workspace_dir" \
SLOPTRAP_INNER_PODMAN_ROOT="$inner_podman_root" \
SLOPTRAP_INNER_PODMAN_RUNROOT="$inner_podman_runroot" \
XDG_RUNTIME_DIR="$inner_runtime_dir" \
"$helper_bin/sloppodman" run -v ./data:/data example/image true >/dev/null 2>&1
); then
record_failure "embedded_capability_helpers: sloppodman rejected a workspace-local bind mount"
fi
if ! grep -q -- 'podman --root ' "$tool_log" || ! grep -q -- '-v ./data:/data' "$tool_log"; then
record_failure "embedded_capability_helpers: sloppodman did not invoke podman with the validated run arguments"
fi
TEST_TOOL_LOG="$tool_log" PATH="$helper_bin:$PATH" SLOPTRAP_HELPER_DIR="$helper_dir" \
SLOPTRAP_ACTIVE_CAPABILITIES="apt-install packet-capture" \
SLOPTRAP_CAPTURE_DIR="$capture_dir" SLOPTRAP_WORKDIR="$workspace_dir" \
SLOPTRAP_AUDIT_LOG="$temp_root/audit.log" "$helper_bin/sloptrap-helperd" >/dev/null 2>&1 &
helper_pid=$!
if ! TEST_TOOL_LOG="$tool_log" PATH="$helper_bin:$PATH" SLOPTRAP_HELPER_DIR="$helper_dir" \
"$helper_bin/slop-apt" install jq >/dev/null 2>&1; then
record_failure "embedded_capability_helpers: slop-apt failed against the embedded helper daemon"
fi
if ! grep -q -- 'apt-get install -y --no-install-recommends jq' "$tool_log"; then
record_failure "embedded_capability_helpers: slop-apt did not reach apt-get install"
fi
local bad_apt_request
bad_apt_request=$(mktemp -d "$helper_dir/queue/request.XXXXXX.req")
printf 'apt-install\n' >"$bad_apt_request/op"
printf '%s\n' '--allow-unauthenticated' >"$bad_apt_request/packages"
if ! wait_for_path "$bad_apt_request/status"; then
record_failure "embedded_capability_helpers: helper daemon did not answer the invalid apt request"
elif [[ $(<"$bad_apt_request/status") != "2" ]]; then
record_failure "embedded_capability_helpers: invalid apt request returned the wrong status"
fi
if [[ -s "$bad_apt_request/stderr" ]] && ! grep -q -- 'invalid package name' "$bad_apt_request/stderr"; then
record_failure "embedded_capability_helpers: invalid apt request did not explain the rejection"
fi
if TEST_TOOL_LOG="$tool_log" PATH="$helper_bin:$PATH" SLOPTRAP_HELPER_DIR="$helper_dir" \
SLOPTRAP_CAPTURE_DIR="$capture_dir" SLOPTRAP_WORKDIR="$workspace_dir" \
"$helper_bin/slopcap" capture --interface eth0 --output /tmp/escape.pcap >/dev/null 2>&1; then
record_failure "embedded_capability_helpers: slopcap accepted an out-of-bounds output path"
fi
if ! TEST_TOOL_LOG="$tool_log" PATH="$helper_bin:$PATH" SLOPTRAP_HELPER_DIR="$helper_dir" \
SLOPTRAP_CAPTURE_DIR="$capture_dir" SLOPTRAP_WORKDIR="$workspace_dir" \
"$helper_bin/slopcap" capture --interface eth0 --filter 'tcp port 80' \
--output "$workspace_dir/capture.pcap" >/dev/null 2>&1; then
record_failure "embedded_capability_helpers: slopcap failed for a workspace-local capture file"
fi
if ! grep -q -- "tcpdump -i eth0 -w $workspace_dir/capture.pcap -- tcp port 80" "$tool_log"; then
record_failure "embedded_capability_helpers: slopcap did not invoke tcpdump with the expected guarded arguments"
fi
local bad_capture_request
bad_capture_request=$(mktemp -d "$helper_dir/queue/request.XXXXXX.req")
printf 'packet-capture\n' >"$bad_capture_request/op"
printf 'eth0\n' >"$bad_capture_request/interface"
printf '\n' >"$bad_capture_request/filter"
printf '/tmp/escape.pcap\n' >"$bad_capture_request/output"
printf '0\n' >"$bad_capture_request/stdout_mode"
if ! wait_for_path "$bad_capture_request/status"; then
record_failure "embedded_capability_helpers: helper daemon did not answer the invalid capture request"
elif [[ $(<"$bad_capture_request/status") != "2" ]]; then
record_failure "embedded_capability_helpers: invalid capture request returned the wrong status"
fi
if [[ -s "$bad_capture_request/stderr" ]] && ! grep -q -- 'output path must stay within' "$bad_capture_request/stderr"; then
record_failure "embedded_capability_helpers: invalid capture request did not explain the rejection"
fi
if [[ -n $helper_pid ]]; then
kill "$helper_pid" >/dev/null 2>&1 || true
wait "$helper_pid" >/dev/null 2>&1 || true
fi
rm -rf "$temp_root"
}
run_make_install_single_file() {
local scenario_dir="$TEST_ROOT/resume_target"
printf '==> make_install_single_file\n'
@@ -768,6 +1068,7 @@ run_symlink_escape
run_manifest_injection
run_helper_symlink
run_secret_mask
run_git_ignore_mask
run_resume_target
run_runtime_context_prompt
run_sh_reexec
@@ -791,6 +1092,7 @@ run_wizard_existing_defaults
run_wizard_build_trigger
run_capability_trust_required
run_capability_profiles
run_embedded_capability_helpers
run_make_install_single_file
if [[ ${#failures[@]} -gt 0 ]]; then