debugging recursion

This commit is contained in:
Samuel Aubertin
2026-03-10 00:42:19 +01:00
parent 1e97baa534
commit 3731094f60
5 changed files with 664 additions and 19 deletions

39
AGENTS.md Normal file
View File

@@ -0,0 +1,39 @@
# skz-sloptrap
This workspace is the source code of `sloptrap`, eg. your own runtime.
Your author, 'sk4nz', has ran the command `sloptrap path/to/skz-sloptrap` and you are living in your own reflection.
# Recursive `slopsloptrap`
sloptrap can recurse.
If you need to prove it, spawn a child from this repo with sloptrap:
`./sloptrap /workspace ...`
This starts a child `slopsloptrap`. Use the child normally, as the end-user would.
# Keep Memory
Future sloptrap instances should add short, useful, durable notes they learn during their session to this file.
Only add high-signal information that is likely to help later runs.
Keep additions brief.
Do not remove existing instructions unless they are outdated or wrong.
---
# Session Memory
- When you make changes that affect how the runtime behaves and cannot test it with recursion, you can ask sk4nz to restart you.
- If recursion is blocked by the current session state and a restart is required, give sk4nz an exact prompt to paste into the next restarted session so it can continue from the current checkpoint.
- Useful checks in the skz-sloptrap repo:
`shellcheck sloptrap`
`bash tests/run_tests.sh` (you can also run them separately)
- Recursive nested-podman inside an already user-namespaced sloptrap needs subuid/subgid ranges derived from `/proc/self/uid_map` and `/proc/self/gid_map`; hardcoding `100000:65536` breaks `newuidmap`.
- When running tests from inside sloptrap, inherited `CODEX_HOME=/codex` plus `SLOPTRAP_PREFER_CODEX_HOME=1` can leak into host-style child launches; ignore that preference when `HOME` has been redirected elsewhere and the runtime hints still point into the inherited `/codex` tree.
- For real recursive `./sloptrap` launches, correct `/proc/self/uid_map` alone is not enough: if the current session still has stale read-only `/etc/subuid` and `/etc/subgid` mounts (for example `sk4nz:100000:65536`), the first nested podman launch still fails before child startup.
- Forcing `SLOPTRAP_CONTAINER_ENGINE=sloppodman` inside sloptrap also needs `TMPDIR` under `/workspace`; otherwise its build-context path guard rejects the staged Dockerfile under `/tmp` before you reach the real subuid/subgid problem.
- If a restarted session still inherits stale read-only `/etc/subuid` and `/etc/subgid` tmpfs mounts, an unprivileged agent cannot repair them in-place (`umount` says `must be superuser to unmount`); both podman and sloppodman stay blocked until the session starts without those mounts.
- Outer sloptrap launches no longer need `/etc/subuid` or `/etc/subgid` bind mounts: `nested-podman` now disables read-only rootfs and the container entrypoint synthesizes container-local subid files from `/proc/self/{uid,gid}_map` before dropping privileges.
- With stale subid mounts gone, recursive `./sloptrap /workspace` can still fail earlier during the inner image build: `crun` tries to open `/proc/sys/net/ipv4/ping_group_range` and gets `Read-only file system` while creating the build container.
- In a fragile nested-podman session, `podman system migrate` can make things worse: a state that still answered `podman info` fell back to repeated `newuidmap ... write to uid_map failed: Operation not permitted` failures afterward.

View File

@@ -68,7 +68,7 @@ Supported keys when the manifest is present:
Values containing `$`, `` ` ``, or newlines are rejected to prevent command injection. Setting illegal keys or malformed values aborts the run before containers start. Values containing `$`, `` ` ``, or newlines are rejected to prevent command injection. Setting illegal keys or malformed values aborts the run before containers start.
sloptrap always runs Codex with `--sandbox danger-full-access --ask-for-approval never`. `codex_args` is deprecated and rejected if present. sloptrap always runs Codex with `--sandbox danger-full-access --ask-for-approval never`. `codex_args` is deprecated and rejected if present.
Capability trust is local state, not part of the repository. Builds for manifests that request capabilities require either an interactive trust confirmation or `--trust-capabilities`. Trusted capabilities can then be activated per run with `--enable-capability <name>`. Capability trust is local state, not part of the repository. Builds for manifests that request capabilities require either an interactive trust confirmation or `--trust-capabilities`. Once the current manifest is trusted, its requested capabilities are enabled automatically for that project configuration.
### `.sloptrapignore` ### `.sloptrapignore`
@@ -80,7 +80,7 @@ Capability trust is local state, not part of the repository. Builds for manifest
## CLI Reference ## CLI Reference
``` ```
./sloptrap [--dry-run] [--print-config] [--trust-capabilities] [--enable-capability <name> ...] <code-directory> [target ...] ./sloptrap [--dry-run] [--print-config] [--trust-capabilities] <code-directory> [target ...]
``` ```
Options: Options:
@@ -88,7 +88,6 @@ Options:
- `--dry-run` &mdash; print the container/engine commands that would run without executing them. - `--dry-run` &mdash; print the container/engine commands that would run without executing them.
- `--print-config` &mdash; output the resolved manifest values, defaults, and ignore list. - `--print-config` &mdash; output the resolved manifest values, defaults, and ignore list.
- `--trust-capabilities` &mdash; trust the manifest's requested capabilities for the current build flow. - `--trust-capabilities` &mdash; trust the manifest's requested capabilities for the current build flow.
- `--enable-capability <name>` &mdash; enable a trusted runtime capability for this invocation. Repeat for multiple capabilities.
- `-h, --help` &mdash; display usage. - `-h, --help` &mdash; display usage.
- `--` &mdash; stop option parsing; remaining arguments are treated as targets. - `--` &mdash; stop option parsing; remaining arguments are treated as targets.
@@ -128,11 +127,12 @@ The launcher executes targets sequentially, so `./sloptrap repo build run` perfo
### Capability Helpers ### Capability Helpers
When a trusted capability is enabled for a run, the container includes helper commands: When the current manifest's capabilities are trusted and enabled, the container includes helper commands:
- `slop-apt install <package...>` for session-scoped package installation. - `slop-apt install <package...>` for session-scoped package installation.
- `slopcap capture --interface <iface> [--filter <expr>] [--output <path>] [--stdout]` for packet capture. - `slopcap capture --interface <iface> [--filter <expr>] [--output <path>] [--stdout]` for packet capture.
- `sloppodman <pull|build|tag|run|ps|logs|stop|rm|inspect> ...` for nested Podman workflows. `build` contexts and Dockerfiles must remain inside `/workspace`, and pushes are not supported. - `sloppodman <pull|build|tag|run|ps|logs|stop|rm|inspect> ...` for nested Podman workflows. `build` contexts and Dockerfiles must remain inside `/workspace`, and pushes are not supported.
- When `nested-podman` is enabled, sloptrap makes the container root filesystem writable long enough to synthesize container-local `/etc/subuid` and `/etc/subgid` files from the live namespace maps, so rootless nested Podman does not depend on host subid files.
## Execution Environment ## Execution Environment

3
slopsloptrap/.sloptrap Normal file
View File

@@ -0,0 +1,3 @@
name=slopsloptrap
capabilities=nested-podman
allow_host_network=false

435
sloptrap
View File

@@ -356,6 +356,120 @@ set -euo pipefail
helper_pid="" helper_pid=""
has_capability() {
local needle=$1
local token
for token in ${SLOPTRAP_ACTIVE_CAPABILITIES:-}; do
if [[ $token == "$needle" ]]; then
return 0
fi
done
return 1
}
detect_subid_range_from_map() {
local map_path=$1
local account_id=$2
awk -v account_id="$account_id" '
NF < 3 { next }
{
ns_start = $1 + 0
ns_count = $3 + 0
if (ns_count <= 0) {
next
}
if (account_id >= ns_start && account_id < (ns_start + ns_count)) {
next
}
if (ns_count > best_count) {
best_start = ns_start
best_count = ns_count
}
}
END {
if (best_count > 0) {
printf "%s %s", best_start, best_count
exit 0
}
exit 1
}
' "$map_path"
}
ensure_subid_mapping_file() {
local destination=$1
local account_name=$2
local account_id=$3
local range_start=$4
local range_count=$5
local tmp_file="${destination}.tmp"
if [[ -r $destination ]] && awk -F: -v account_name="$account_name" -v account_id="$account_id" -v range_start="$range_start" -v range_count="$range_count" '
($1 == account_name || $1 == account_id) && $2 == range_start && $3 == range_count { found=1; exit }
END { exit(found ? 0 : 1) }
' "$destination"; then
return 0
fi
[[ -e $destination && ! -L $destination ]] || : >"$destination"
awk -F: -v account_name="$account_name" -v account_id="$account_id" '
$1 == account_name || $1 == account_id { next }
{ print }
' "$destination" >"$tmp_file"
if [[ -n $account_name && $account_name != "$account_id" ]]; then
printf '%s:%s:%s\n' "$account_name" "$range_start" "$range_count" >>"$tmp_file"
else
printf '%s:%s:%s\n' "$account_id" "$range_start" "$range_count" >>"$tmp_file"
fi
chmod 0644 "$tmp_file" 2>/dev/null || true
if ! mv "$tmp_file" "$destination" 2>/dev/null; then
cat "$tmp_file" >"$destination"
rm -f "$tmp_file"
fi
}
lookup_account_name() {
local account_id=$1
local passwd_entry=""
if passwd_entry=$(getent passwd "$account_id" 2>/dev/null); then
printf '%s\n' "${passwd_entry%%:*}"
return 0
fi
return 1
}
ensure_subid_mappings() {
local account_id account_gid account_name=""
local range_start="" range_count="" gid_start="" gid_count=""
local detected_range=""
account_id=${SLOPTRAP_HOST_UID:-$(id -u)}
account_gid=${SLOPTRAP_HOST_GID:-$(id -g)}
if ! account_name=$(lookup_account_name "$account_id"); then
account_name=""
fi
if detected_range=$(detect_subid_range_from_map /proc/self/uid_map "$account_id" 2>/dev/null); then
read -r range_start range_count <<<"$detected_range"
elif [[ -n ${SLOPTRAP_PODMAN_SUBID_START:-} && -n ${SLOPTRAP_PODMAN_SUBID_COUNT:-} ]]; then
range_start=${SLOPTRAP_PODMAN_SUBID_START}
range_count=${SLOPTRAP_PODMAN_SUBID_COUNT}
fi
if detected_range=$(detect_subid_range_from_map /proc/self/gid_map "$account_gid" 2>/dev/null); then
read -r gid_start gid_count <<<"$detected_range"
elif [[ -n ${SLOPTRAP_PODMAN_SUBGID_START:-} && -n ${SLOPTRAP_PODMAN_SUBGID_COUNT:-} ]]; then
gid_start=${SLOPTRAP_PODMAN_SUBGID_START}
gid_count=${SLOPTRAP_PODMAN_SUBGID_COUNT}
fi
if [[ -n $range_start && -n $range_count ]]; then
ensure_subid_mapping_file /etc/subuid "$account_name" "$account_id" "$range_start" "$range_count"
fi
if [[ -n $gid_start && -n $gid_count ]]; then
ensure_subid_mapping_file /etc/subgid "$account_name" "$account_id" "$gid_start" "$gid_count"
fi
}
cleanup() { cleanup() {
if [[ -n $helper_pid ]]; then if [[ -n $helper_pid ]]; then
kill "$helper_pid" >/dev/null 2>&1 || true kill "$helper_pid" >/dev/null 2>&1 || true
@@ -374,11 +488,11 @@ if [[ $(id -u) -eq 0 ]]; then
queue_dir="$helper_dir/queue" queue_dir="$helper_dir/queue"
mkdir -p "$queue_dir" mkdir -p "$queue_dir"
chmod 711 "$helper_dir" chmod 711 "$helper_dir"
chmod 700 "$queue_dir" chmod 1733 "$queue_dir"
target_uid=${SLOPTRAP_HOST_UID:-} target_uid=${SLOPTRAP_HOST_UID:-}
target_gid=${SLOPTRAP_HOST_GID:-} target_gid=${SLOPTRAP_HOST_GID:-}
if [[ -n $target_uid && -n $target_gid ]]; then if has_capability "nested-podman"; then
chown "$target_uid:$target_gid" "$queue_dir" ensure_subid_mappings
fi fi
if [[ -n ${SLOPTRAP_ACTIVE_CAPABILITIES:-} ]]; then if [[ -n ${SLOPTRAP_ACTIVE_CAPABILITIES:-} ]]; then
/usr/local/bin/sloptrap-helperd & /usr/local/bin/sloptrap-helperd &
@@ -412,7 +526,13 @@ cleanup_pidfile() {
rm -f "$pidfile" rm -f "$pidfile"
} }
trap cleanup_pidfile EXIT INT TERM HUP shutdown_helper() {
cleanup_pidfile
exit 0
}
trap cleanup_pidfile EXIT
trap shutdown_helper INT TERM HUP
printf '%s\n' "$$" >"$pidfile" printf '%s\n' "$$" >"$pidfile"
chmod 644 "$pidfile" 2>/dev/null || true chmod 644 "$pidfile" 2>/dev/null || true
@@ -460,10 +580,35 @@ path_within_root() {
claim_request_dir() { claim_request_dir() {
local request_dir=$1 local request_dir=$1
local owner_uid owner_gid
[[ -d $request_dir && ! -L $request_dir ]] || return 1 [[ -d $request_dir && ! -L $request_dir ]] || return 1
path_within_root "$queue_dir" "$request_dir" || return 1 path_within_root "$queue_dir" "$request_dir" || return 1
chown root:root "$request_dir" 2>/dev/null || true owner_uid=$(stat -c '%u' "$request_dir" 2>/dev/null || true)
owner_gid=$(stat -c '%g' "$request_dir" 2>/dev/null || true)
[[ $owner_uid =~ ^[0-9]+$ && $owner_gid =~ ^[0-9]+$ ]] || return 1
REQUEST_OWNER_UID=$owner_uid
REQUEST_OWNER_GID=$owner_gid
if [[ $(id -u) -eq 0 ]]; then
chown root:root "$request_dir" 2>/dev/null || return 1
chmod 700 "$request_dir" 2>/dev/null || return 1
fi
}
release_request_dir() {
local request_dir=$1
local owner_uid=$2
local owner_gid=$3
local path
[[ $owner_uid =~ ^[0-9]+$ && $owner_gid =~ ^[0-9]+$ ]] || return 0
for path in "$request_dir" "$request_dir/status" "$request_dir/stdout" "$request_dir/stderr"; do
[[ -e $path && ! -L $path ]] || continue
chown "$owner_uid:$owner_gid" "$path" 2>/dev/null || true
done
chmod 700 "$request_dir" 2>/dev/null || true chmod 700 "$request_dir" 2>/dev/null || true
for path in "$request_dir/status" "$request_dir/stdout" "$request_dir/stderr"; do
[[ -e $path && ! -L $path ]] || continue
chmod 600 "$path" 2>/dev/null || true
done
} }
init_request_outputs() { init_request_outputs() {
@@ -636,6 +781,8 @@ while true; do
[[ -d $request_dir ]] || continue [[ -d $request_dir ]] || continue
[[ ! -f "$request_dir/status" ]] || continue [[ ! -f "$request_dir/status" ]] || continue
pending_requests=1 pending_requests=1
REQUEST_OWNER_UID=""
REQUEST_OWNER_GID=""
if ! claim_request_dir "$request_dir"; then if ! claim_request_dir "$request_dir"; then
log_action "request" "unsafe=1 path=$request_dir" 2 log_action "request" "unsafe=1 path=$request_dir" 2
continue continue
@@ -663,6 +810,7 @@ while true; do
log_action "$op" "unknown=1" 2 log_action "$op" "unknown=1" 2
;; ;;
esac esac
release_request_dir "$request_dir" "$REQUEST_OWNER_UID" "$REQUEST_OWNER_GID"
done done
if [[ $pending_requests -eq 0 ]]; then if [[ $pending_requests -eq 0 ]]; then
sleep 1 sleep 1
@@ -716,8 +864,7 @@ ensure_helper_ready() {
[[ -n $helper_bin ]] || exit 1 [[ -n $helper_bin ]] || exit 1
mkdir -p "$queue_dir" mkdir -p "$queue_dir"
chmod 711 "$helper_dir" chmod 711 "$helper_dir"
chmod 700 "$queue_dir" chmod 1733 "$queue_dir"
chown "$SLOPTRAP_HOST_UID:$SLOPTRAP_HOST_GID" "$queue_dir"
if [[ -r $pidfile ]]; then if [[ -r $pidfile ]]; then
pid=$(<"$pidfile") pid=$(<"$pidfile")
if [[ -n $pid ]] && kill -0 "$pid" 2>/dev/null; then if [[ -n $pid ]] && kill -0 "$pid" 2>/dev/null; then
@@ -827,8 +974,7 @@ ensure_helper_ready() {
[[ -n $helper_bin ]] || exit 1 [[ -n $helper_bin ]] || exit 1
mkdir -p "$queue_dir" mkdir -p "$queue_dir"
chmod 711 "$helper_dir" chmod 711 "$helper_dir"
chmod 700 "$queue_dir" chmod 1733 "$queue_dir"
chown "$SLOPTRAP_HOST_UID:$SLOPTRAP_HOST_GID" "$queue_dir"
if [[ -r $pidfile ]]; then if [[ -r $pidfile ]]; then
pid=$(<"$pidfile") pid=$(<"$pidfile")
if [[ -n $pid ]] && kill -0 "$pid" 2>/dev/null; then if [[ -n $pid ]] && kill -0 "$pid" 2>/dev/null; then
@@ -961,6 +1107,10 @@ exit "$status"
EOF EOF
;; ;;
sloppodman) sloppodman)
# shellcheck disable=SC2034
local workspace_root="" podman_root="" podman_runroot="" runtime_dir="" config_home=""
# shellcheck disable=SC2034
local storage_driver="" storage_conf="" containers_conf="" subcommand=""
cat <<'EOF' cat <<'EOF'
#!/usr/bin/env bash #!/usr/bin/env bash
set -euo pipefail set -euo pipefail
@@ -983,11 +1133,29 @@ if [[ $# -eq 0 ]]; then
exit 2 exit 2
fi fi
original_args=("$@")
subcommand=$1 subcommand=$1
shift shift
subcommand_prefix=("$subcommand")
case "$subcommand" in case "$subcommand" in
pull|build|tag|run|ps|logs|stop|rm|inspect) pull|build|tag|run|ps|logs|stop|rm|inspect|rmi)
;;
image)
[[ $# -gt 0 ]] || {
printf 'sloppodman: image requires a subcommand\n' >&2
exit 2
}
case "$1" in
inspect|prune)
subcommand_prefix=(image "$1")
shift
;;
*)
printf 'sloppodman: unsupported image subcommand %s\n' "$1" >&2
exit 2
;;
esac
;; ;;
*) *)
printf 'sloppodman: unsupported subcommand %s\n' "$subcommand" >&2 printf 'sloppodman: unsupported subcommand %s\n' "$subcommand" >&2
@@ -1004,7 +1172,161 @@ workspace_root=${SLOPTRAP_WORKDIR:-/workspace}
podman_root=${SLOPTRAP_INNER_PODMAN_ROOT:-/codex/capabilities/podman/storage} podman_root=${SLOPTRAP_INNER_PODMAN_ROOT:-/codex/capabilities/podman/storage}
podman_runroot=${SLOPTRAP_INNER_PODMAN_RUNROOT:-/codex/capabilities/podman/run} podman_runroot=${SLOPTRAP_INNER_PODMAN_RUNROOT:-/codex/capabilities/podman/run}
runtime_dir=${XDG_RUNTIME_DIR:-/codex/capabilities/podman/runtime} runtime_dir=${XDG_RUNTIME_DIR:-/codex/capabilities/podman/runtime}
mkdir -p "$podman_root" "$podman_runroot" "$runtime_dir" config_home=${SLOPTRAP_INNER_PODMAN_CONFIG_HOME:-$runtime_dir/config}
containers_conf_dir="$config_home/containers"
storage_driver=${SLOPTRAP_INNER_PODMAN_DRIVER:-vfs}
storage_conf="$containers_conf_dir/storage.conf"
containers_conf="$containers_conf_dir/containers.conf"
subuid_file=${SLOPTRAP_PODMAN_SUBUID_FILE:-/etc/subuid}
subgid_file=${SLOPTRAP_PODMAN_SUBGID_FILE:-/etc/subgid}
mkdir -p "$podman_root" "$podman_runroot" "$runtime_dir" "$containers_conf_dir"
cat >"$storage_conf" <<STORAGE_CONF_EOF
[storage]
driver = "$storage_driver"
runroot = "$podman_runroot"
graphroot = "$podman_root"
[storage.options.vfs]
ignore_chown_errors = "true"
[storage.options.overlay]
ignore_chown_errors = "true"
mount_program = "/usr/bin/fuse-overlayfs"
STORAGE_CONF_EOF
cat >"$containers_conf" <<'CONTAINERS_CONF_EOF'
[engine]
cgroup_manager = "cgroupfs"
events_logger = "file"
CONTAINERS_CONF_EOF
export CONTAINERS_STORAGE_CONF="$storage_conf"
export CONTAINERS_CONF="$containers_conf"
export BUILDAH_ISOLATION="${BUILDAH_ISOLATION:-chroot}"
detect_subid_range_from_map() {
local map_path=$1
local account_id=$2
awk -v account_id="$account_id" '
NF < 3 { next }
{
ns_start = $1 + 0
ns_count = $3 + 0
if (ns_count <= 0) {
next
}
if (account_id >= ns_start && account_id < (ns_start + ns_count)) {
next
}
if (ns_count > best_count) {
best_start = ns_start
best_count = ns_count
}
}
END {
if (best_count > 0) {
printf "%s %s", best_start, best_count
exit 0
}
exit 1
}
' "$map_path"
}
ensure_subid_mapping_file() {
local destination=$1
local account_name=$2
local account_id=$3
local range_start=$4
local range_count=$5
local tmp_file="${destination}.tmp"
if [[ -r $destination ]] && awk -F: -v account_name="$account_name" -v account_id="$account_id" -v range_start="$range_start" -v range_count="$range_count" '
($1 == account_name || $1 == account_id) && $2 == range_start && $3 == range_count { found=1; exit }
END { exit(found ? 0 : 1) }
' "$destination"; then
return 0
fi
[[ -e $destination && ! -L $destination ]] || : >"$destination"
awk -F: -v account_name="$account_name" -v account_id="$account_id" '
$1 == account_name || $1 == account_id { next }
{ print }
' "$destination" >"$tmp_file"
if [[ -n $account_name && $account_name != "$account_id" ]]; then
printf '%s:%s:%s\n' "$account_name" "$range_start" "$range_count" >>"$tmp_file"
else
printf '%s:%s:%s\n' "$account_id" "$range_start" "$range_count" >>"$tmp_file"
fi
chmod 0644 "$tmp_file" 2>/dev/null || true
if ! mv "$tmp_file" "$destination" 2>/dev/null; then
cat "$tmp_file" >"$destination"
rm -f "$tmp_file"
fi
}
ensure_subid_mappings() {
local account_id account_name range_start range_count gid_start gid_count detected_range
account_id=${SLOPTRAP_PODMAN_CALLER_UID:-$(id -u)}
account_name=${SLOPTRAP_PODMAN_CALLER_USER:-}
if [[ -z $account_name ]]; then
account_name=$(id -un 2>/dev/null || true)
fi
range_start=${SLOPTRAP_PODMAN_SUBID_START:-100000}
range_count=${SLOPTRAP_PODMAN_SUBID_COUNT:-65536}
gid_start=${SLOPTRAP_PODMAN_SUBGID_START:-$range_start}
gid_count=${SLOPTRAP_PODMAN_SUBGID_COUNT:-$range_count}
if detected_range=$(detect_subid_range_from_map /proc/self/uid_map "$account_id" 2>/dev/null); then
read -r range_start range_count <<<"$detected_range"
fi
if detected_range=$(detect_subid_range_from_map /proc/self/gid_map "${SLOPTRAP_PODMAN_CALLER_GID:-$(id -g)}" 2>/dev/null); then
read -r gid_start gid_count <<<"$detected_range"
fi
[[ -e $subuid_file && ! -L $subuid_file ]] || : >"$subuid_file"
[[ -e $subgid_file && ! -L $subgid_file ]] || : >"$subgid_file"
ensure_subid_mapping_file "$subuid_file" "$account_name" "$account_id" "$range_start" "$range_count"
ensure_subid_mapping_file "$subgid_file" "$account_name" "$account_id" "$gid_start" "$gid_count"
if [[ $(id -u) -eq 0 ]]; then
ensure_subid_mapping_file "$subuid_file" root 0 "$range_start" "$range_count"
ensure_subid_mapping_file "$subgid_file" root 0 "$gid_start" "$gid_count"
fi
}
exec_podman() {
local -a cmd=(
podman
--root "$podman_root"
--runroot "$podman_runroot"
--storage-driver "$storage_driver"
--cgroup-manager cgroupfs
--events-backend file
"${subcommand_prefix[@]}" "$@"
)
if [[ $(id -u) -eq 0 ]]; then
ensure_subid_mappings
exec "${cmd[@]}"
fi
if [[ ${SLOPTRAP_PODMAN_ESCALATED:-0} == 1 ]]; then
exec "${cmd[@]}"
fi
if ! command -v setpriv >/dev/null 2>&1; then
printf 'sloppodman: setpriv is required to enter the nested podman capability profile\n' >&2
exit 1
fi
chmod 0777 "$podman_root" "$podman_runroot" "$runtime_dir" 2>/dev/null || true
exec setpriv --reuid 0 --regid 0 --clear-groups -- env \
CONTAINERS_STORAGE_CONF="$CONTAINERS_STORAGE_CONF" \
CONTAINERS_CONF="$CONTAINERS_CONF" \
BUILDAH_ISOLATION="$BUILDAH_ISOLATION" \
XDG_RUNTIME_DIR="$runtime_dir" \
SLOPTRAP_PODMAN_ESCALATED=1 \
SLOPTRAP_PODMAN_CALLER_UID="${SLOPTRAP_PODMAN_CALLER_UID:-$(id -u)}" \
SLOPTRAP_PODMAN_CALLER_GID="${SLOPTRAP_PODMAN_CALLER_GID:-$(id -g)}" \
SLOPTRAP_PODMAN_CALLER_USER="${SLOPTRAP_PODMAN_CALLER_USER:-$(id -un 2>/dev/null || true)}" \
"$0" "${original_args[@]}"
}
resolve_inner_path() { resolve_inner_path() {
local raw=$1 local raw=$1
@@ -1180,7 +1502,7 @@ if [[ $subcommand == "run" ]]; then
done done
fi fi
exec podman --root "$podman_root" --runroot "$podman_runroot" "$subcommand" "$@" exec_podman "$@"
EOF EOF
;; ;;
*) *)
@@ -1243,6 +1565,30 @@ prepare_build_context() {
select_codex_home() { select_codex_home() {
local preferred="$HOME/.codex" local preferred="$HOME/.codex"
if [[ -n ${CODEX_HOME:-} ]]; then
if [[ ${HOME:-} == "$CODEX_HOME" ]]; then
preferred="$CODEX_HOME"
elif [[ ${SLOPTRAP_PREFER_CODEX_HOME:-0} == "1" ]]; then
local inherited_runtime_home=false
local runtime_hint
for runtime_hint in \
"${SLOPTRAP_CAPTURE_DIR:-}" \
"${SLOPTRAP_AUDIT_LOG:-}" \
"${SLOPTRAP_INNER_PODMAN_ROOT:-}" \
"${SLOPTRAP_INNER_PODMAN_RUNROOT:-}" \
"${XDG_CONFIG_HOME:-}" \
"${XDG_CACHE_HOME:-}" \
"${XDG_STATE_HOME:-}"; do
if [[ -n $runtime_hint && ( $runtime_hint == "$CODEX_HOME" || $runtime_hint == "$CODEX_HOME/"* ) ]]; then
inherited_runtime_home=true
break
fi
done
if ! $inherited_runtime_home; then
preferred="$CODEX_HOME"
fi
fi
fi
if [[ -L $preferred ]]; then if [[ -L $preferred ]]; then
error "Codex home '$preferred' must not be a symlink" error "Codex home '$preferred' must not be a symlink"
fi fi
@@ -1269,6 +1615,59 @@ select_codex_home() {
fi fi
} }
write_subid_mapping_file() {
local destination=$1
local existing_path=$2
local account_name=$3
local account_id=$4
local range_start=$5
local range_count=$6
if [[ -r $existing_path ]]; then
awk -F: -v account_name="$account_name" -v account_id="$account_id" '
$1 == account_name || $1 == account_id { next }
{ print }
' "$existing_path" >"$destination"
else
: >"$destination"
fi
if [[ -n $account_name && $account_name != "$account_id" ]]; then
printf '%s:%s:%s\n' "$account_name" "$range_start" "$range_count" >>"$destination"
else
printf '%s:%s:%s\n' "$account_id" "$range_start" "$range_count" >>"$destination"
fi
chmod 0644 "$destination"
}
detect_subid_range_from_map() {
local map_path=$1
local account_id=$2
awk -v account_id="$account_id" '
NF < 3 { next }
{
ns_start = $1 + 0
ns_count = $3 + 0
if (ns_count <= 0) {
next
}
if (account_id >= ns_start && account_id < (ns_start + ns_count)) {
next
}
if (ns_count > best_count) {
best_start = ns_start
best_count = ns_count
}
}
END {
if (best_count > 0) {
printf "%s %s", best_start, best_count
exit 0
}
exit 1
}
' "$map_path"
}
compute_manifest_digest() { compute_manifest_digest() {
if [[ -f $MANIFEST_PATH ]]; then if [[ -f $MANIFEST_PATH ]]; then
local digest local digest
@@ -2234,7 +2633,7 @@ prepare_container_runtime() {
SLOPTRAP_CONTAINER_NAME=$(sanitize_engine_name "$SLOPTRAP_CONTAINER_NAME") SLOPTRAP_CONTAINER_NAME=$(sanitize_engine_name "$SLOPTRAP_CONTAINER_NAME")
local -a network_opts=(--network "$SLOPTRAP_NETWORK_NAME" --init) local -a network_opts=(--network "$SLOPTRAP_NETWORK_NAME" --init)
local -a security_opts=(--cap-drop=ALL --security-opt no-new-privileges) local -a security_opts=(--cap-drop=ALL)
local -a capability_opts=() local -a capability_opts=()
if [[ -n $SLOPTRAP_SECURITY_OPTS_EXTRA ]]; then if [[ -n $SLOPTRAP_SECURITY_OPTS_EXTRA ]]; then
local -a extra_opts=() local -a extra_opts=()
@@ -2267,7 +2666,12 @@ prepare_container_runtime() {
SLOPTRAP_RUN_AS_ROOT=true SLOPTRAP_RUN_AS_ROOT=true
fi fi
if capability_list_contains "$ENABLED_CAPABILITIES" "nested-podman"; then if capability_list_contains "$ENABLED_CAPABILITIES" "nested-podman"; then
capability_opts+=(--device /dev/fuse) capability_opts+=(--device /dev/fuse --cap-add SYS_CHROOT --cap-add MKNOD)
security_opts+=(--security-opt seccomp=unconfined)
SLOPTRAP_ROOTFS_READONLY=0
SLOPTRAP_RUN_AS_ROOT=true
else
security_opts+=(--security-opt no-new-privileges)
fi fi
if $SLOPTRAP_RUN_AS_ROOT; then if $SLOPTRAP_RUN_AS_ROOT; then
capability_opts+=( capability_opts+=(
@@ -2318,6 +2722,7 @@ prepare_container_runtime() {
-e "SLOPTRAP_AUDIT_LOG=$SLOPTRAP_CODEX_HOME_CONT/state/capabilities.log" -e "SLOPTRAP_AUDIT_LOG=$SLOPTRAP_CODEX_HOME_CONT/state/capabilities.log"
-e "SLOPTRAP_INNER_PODMAN_ROOT=$SLOPTRAP_CODEX_HOME_CONT/capabilities/podman/storage" -e "SLOPTRAP_INNER_PODMAN_ROOT=$SLOPTRAP_CODEX_HOME_CONT/capabilities/podman/storage"
-e "SLOPTRAP_INNER_PODMAN_RUNROOT=$SLOPTRAP_CODEX_HOME_CONT/capabilities/podman/run" -e "SLOPTRAP_INNER_PODMAN_RUNROOT=$SLOPTRAP_CODEX_HOME_CONT/capabilities/podman/run"
-e "SLOPTRAP_PREFER_CODEX_HOME=1"
-e "XDG_RUNTIME_DIR=$SLOPTRAP_CODEX_HOME_CONT/capabilities/podman/runtime" -e "XDG_RUNTIME_DIR=$SLOPTRAP_CODEX_HOME_CONT/capabilities/podman/runtime"
) )
if capability_list_contains "$ENABLED_CAPABILITIES" "nested-podman" && [[ $SLOPTRAP_NETWORK_NAME == "host" ]]; then if capability_list_contains "$ENABLED_CAPABILITIES" "nested-podman" && [[ $SLOPTRAP_NETWORK_NAME == "host" ]]; then
@@ -2381,6 +2786,7 @@ build_image() {
"$CONTAINER_ENGINE" build --quiet "$CONTAINER_ENGINE" build --quiet
-t "$SLOPTRAP_IMAGE_NAME" -t "$SLOPTRAP_IMAGE_NAME"
-f "$SLOPTRAP_DOCKERFILE_PATH" -f "$SLOPTRAP_DOCKERFILE_PATH"
--network "$SLOPTRAP_NETWORK_NAME"
--label "$SLOPTRAP_IMAGE_LABEL" --label "$SLOPTRAP_IMAGE_LABEL"
--build-arg "BASE_PACKAGES=$SLOPTRAP_PACKAGES_BASE" --build-arg "BASE_PACKAGES=$SLOPTRAP_PACKAGES_BASE"
--build-arg "CAPABILITY_PACKAGES=$capability_packages_arg" --build-arg "CAPABILITY_PACKAGES=$capability_packages_arg"
@@ -2426,6 +2832,7 @@ rebuild_image() {
"$CONTAINER_ENGINE" build --no-cache --quiet "$CONTAINER_ENGINE" build --no-cache --quiet
-t "$SLOPTRAP_IMAGE_NAME" -t "$SLOPTRAP_IMAGE_NAME"
-f "$SLOPTRAP_DOCKERFILE_PATH" -f "$SLOPTRAP_DOCKERFILE_PATH"
--network "$SLOPTRAP_NETWORK_NAME"
--label "$SLOPTRAP_IMAGE_LABEL" --label "$SLOPTRAP_IMAGE_LABEL"
--build-arg "BASE_PACKAGES=$SLOPTRAP_PACKAGES_BASE" --build-arg "BASE_PACKAGES=$SLOPTRAP_PACKAGES_BASE"
--build-arg "CAPABILITY_PACKAGES=$capability_packages_arg" --build-arg "CAPABILITY_PACKAGES=$capability_packages_arg"

View File

@@ -447,6 +447,99 @@ run_auth_file_mount() {
teardown_stub_env teardown_stub_env
} }
run_codex_home_override() {
local scenario_dir codex_root
scenario_dir=$(cd "$TEST_ROOT/resume_target" && pwd -P)
printf '==> codex_home_override\n'
setup_stub_env
codex_root="$STUB_HOME/codex-root"
mkdir -p "$codex_root"
printf '{"access_token":"test"}\n' >"$codex_root/auth.json"
if ! PATH="$STUB_BIN:$PATH" HOME="$STUB_HOME" CODEX_HOME="$codex_root" SLOPTRAP_PREFER_CODEX_HOME=1 \
FAKE_PODMAN_LOG="$STUB_LOG" FAKE_PODMAN_INSPECT_FAIL=1 \
"$SLOPTRAP_BIN" "$scenario_dir" </dev/null >/dev/null 2>&1; then
record_failure "codex_home_override: sloptrap exited non-zero"
teardown_stub_env
return
fi
if ! grep -q -- "-v ${codex_root}/auth.json:/codex/auth.json:Z" "$STUB_LOG"; then
record_failure "codex_home_override: missing CODEX_HOME auth file mount"
fi
if ! grep -q -- "-v ${codex_root}/sloptrap/state/" "$STUB_LOG"; then
record_failure "codex_home_override: missing CODEX_HOME project state bind mount"
fi
if grep -q -- "-v ${STUB_HOME}/.codex/auth.json:/codex/auth.json:Z" "$STUB_LOG"; then
record_failure "codex_home_override: should not fall back to HOME/.codex when CODEX_HOME is set"
fi
local first_run
first_run=$(grep "FAKE PODMAN: run " "$STUB_LOG" | head -n 1 || true)
if [[ -z $first_run || $first_run == *" login" ]]; then
record_failure "codex_home_override: existing CODEX_HOME auth should avoid login target"
fi
teardown_stub_env
}
run_recursive_slopsloptrap() {
local scenario_dir temp_root codex_root
printf '==> recursive_slopsloptrap\n'
setup_stub_env
temp_root=$(mktemp -d)
scenario_dir="$temp_root/slopsloptrap"
codex_root="$temp_root/codex-root"
mkdir -p "$scenario_dir" "$codex_root"
cat >"$scenario_dir/.sloptrap" <<'EOF'
name=slopsloptrap
capabilities=nested-podman
allow_host_network=false
EOF
printf '{"access_token":"test"}\n' >"$codex_root/auth.json"
if ! PATH="$STUB_BIN:$PATH" HOME="$codex_root" CODEX_HOME="$codex_root" \
FAKE_PODMAN_LOG="$STUB_LOG" FAKE_PODMAN_INSPECT_FAIL=1 \
"$SLOPTRAP_BIN" --trust-capabilities "$scenario_dir" shell </dev/null >/dev/null 2>&1; then
record_failure "recursive_slopsloptrap: sloptrap exited non-zero"
teardown_stub_env
rm -rf "$temp_root"
return
fi
if ! grep -q -- "slopsloptrap-sloptrap-image" "$STUB_LOG"; then
record_failure "recursive_slopsloptrap: child image name missing"
fi
if ! grep -q -- "slopsloptrap-sloptrap-container" "$STUB_LOG"; then
record_failure "recursive_slopsloptrap: child container name missing"
fi
if ! grep -q -- "-v ${codex_root}/auth.json:/codex/auth.json:Z" "$STUB_LOG"; then
record_failure "recursive_slopsloptrap: missing recursive auth bind mount"
fi
if ! grep -q -- "-v ${codex_root}/sloptrap/state/" "$STUB_LOG"; then
record_failure "recursive_slopsloptrap: missing recursive state bind mount"
fi
if grep -q -- "-v ${codex_root}/.codex/auth.json:/codex/auth.json:Z" "$STUB_LOG"; then
record_failure "recursive_slopsloptrap: should not fall back to CODEX_HOME/.codex in recursive mode"
fi
if grep -q -- "/etc/subuid" "$STUB_LOG" || grep -q -- "/etc/subgid" "$STUB_LOG"; then
record_failure "recursive_slopsloptrap: launcher should not mount subid helper files"
fi
if grep -q -- "--read-only" "$STUB_LOG"; then
record_failure "recursive_slopsloptrap: nested podman should disable read-only rootfs"
fi
local first_run
first_run=$(grep "FAKE PODMAN: run " "$STUB_LOG" | head -n 1 || true)
if [[ -z $first_run || $first_run == *" login" ]]; then
record_failure "recursive_slopsloptrap: recursive auth should avoid login target"
fi
if [[ $first_run != *"/bin/bash"* ]]; then
record_failure "recursive_slopsloptrap: shell target did not reach child container run"
fi
if [[ $first_run == *"--user "* ]]; then
record_failure "recursive_slopsloptrap: nested podman shell should not force --user"
fi
if [[ $first_run != *"--cap-add SETUID"* || $first_run != *"--cap-add SETGID"* ]]; then
record_failure "recursive_slopsloptrap: nested podman shell missing privilege bootstrap capabilities"
fi
teardown_stub_env
rm -rf "$temp_root"
}
run_project_state_isolation() { run_project_state_isolation() {
local scenario_a scenario_b local scenario_a scenario_b
scenario_a=$(cd "$TEST_ROOT/resume_target" && pwd -P) scenario_a=$(cd "$TEST_ROOT/resume_target" && pwd -P)
@@ -735,6 +828,9 @@ run_capability_profiles() {
if ! grep -q -- "CAPABILITY_PACKAGES=tcpdump podman uidmap 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" record_failure "capability_profiles: build arg for capability packages missing"
fi fi
if ! grep -q -- "FAKE PODMAN: build --quiet -t capability-repo-sloptrap-image -f .* --network host " "$STUB_LOG"; then
record_failure "capability_profiles: build should inherit host networking"
fi
if ! grep -q -- "--cap-add NET_RAW" "$STUB_LOG"; then if ! grep -q -- "--cap-add NET_RAW" "$STUB_LOG"; then
record_failure "capability_profiles: NET_RAW capability missing" record_failure "capability_profiles: NET_RAW capability missing"
fi fi
@@ -744,6 +840,12 @@ run_capability_profiles() {
if ! grep -q -- "--device /dev/fuse" "$STUB_LOG"; then if ! grep -q -- "--device /dev/fuse" "$STUB_LOG"; then
record_failure "capability_profiles: /dev/fuse device missing" record_failure "capability_profiles: /dev/fuse device missing"
fi fi
if ! grep -q -- "--cap-add SYS_CHROOT" "$STUB_LOG"; then
record_failure "capability_profiles: SYS_CHROOT capability missing"
fi
if ! grep -q -- "--cap-add MKNOD" "$STUB_LOG"; then
record_failure "capability_profiles: MKNOD capability missing"
fi
if ! grep -q -- "--cap-add SETUID" "$STUB_LOG"; then if ! grep -q -- "--cap-add SETUID" "$STUB_LOG"; then
record_failure "capability_profiles: SETUID capability missing" record_failure "capability_profiles: SETUID capability missing"
fi fi
@@ -759,6 +861,12 @@ run_capability_profiles() {
if ! grep -q -- "--cap-add FOWNER" "$STUB_LOG"; then if ! grep -q -- "--cap-add FOWNER" "$STUB_LOG"; then
record_failure "capability_profiles: FOWNER capability missing" record_failure "capability_profiles: FOWNER capability missing"
fi fi
if ! grep -q -- "--security-opt seccomp=unconfined" "$STUB_LOG"; then
record_failure "capability_profiles: nested podman seccomp override missing"
fi
if grep -q -- "--security-opt no-new-privileges" "$STUB_LOG"; then
record_failure "capability_profiles: nested podman should not force no-new-privileges"
fi
if grep -q -- "--read-only" "$STUB_LOG"; then if grep -q -- "--read-only" "$STUB_LOG"; then
record_failure "capability_profiles: apt profile should disable read-only rootfs" record_failure "capability_profiles: apt profile should disable read-only rootfs"
fi fi
@@ -780,6 +888,9 @@ run_capability_profiles() {
if ! grep -q -- "SLOPTRAP_INNER_PODMAN_HOST_NETWORK=1" "$STUB_LOG"; then if ! grep -q -- "SLOPTRAP_INNER_PODMAN_HOST_NETWORK=1" "$STUB_LOG"; then
record_failure "capability_profiles: inner podman host-network mirror flag missing" record_failure "capability_profiles: inner podman host-network mirror flag missing"
fi fi
if grep -q -- "/etc/subuid" "$STUB_LOG" || grep -q -- "/etc/subgid" "$STUB_LOG"; then
record_failure "capability_profiles: launcher should not mount subid helper files"
fi
local state_root capability_dir local state_root capability_dir
state_root="$STUB_HOME/.codex/sloptrap/state" state_root="$STUB_HOME/.codex/sloptrap/state"
capability_dir=$(find "$state_root" -mindepth 2 -maxdepth 2 -type d -name capabilities | head -n 1 || true) capability_dir=$(find "$state_root" -mindepth 2 -maxdepth 2 -type d -name capabilities | head -n 1 || true)
@@ -830,6 +941,8 @@ run_embedded_capability_helpers() {
cat >"$helper_bin/podman" <<'EOF' cat >"$helper_bin/podman" <<'EOF'
#!/usr/bin/env bash #!/usr/bin/env bash
set -euo pipefail set -euo pipefail
printf 'podman-env BUILDAH_ISOLATION=%s CONTAINERS_STORAGE_CONF=%s CONTAINERS_CONF=%s\n' \
"${BUILDAH_ISOLATION:-}" "${CONTAINERS_STORAGE_CONF:-}" "${CONTAINERS_CONF:-}" >>"$TEST_TOOL_LOG"
printf 'podman %s\n' "$*" >>"$TEST_TOOL_LOG" printf 'podman %s\n' "$*" >>"$TEST_TOOL_LOG"
exit 0 exit 0
EOF EOF
@@ -861,6 +974,7 @@ EOF
cat >"$helper_bin/setpriv" <<'EOF' cat >"$helper_bin/setpriv" <<'EOF'
#!/usr/bin/env bash #!/usr/bin/env bash
set -euo pipefail set -euo pipefail
printf 'setpriv %s\n' "$*" >>"$TEST_TOOL_LOG"
while [[ $# -gt 0 ]]; do while [[ $# -gt 0 ]]; do
case "$1" in case "$1" in
--reuid|--regid) --reuid|--regid)
@@ -883,7 +997,7 @@ EOF
chmod +x "$helper_bin/podman" "$helper_bin/apt-get" "$helper_bin/tcpdump" "$helper_bin/setpriv" 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" \ 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 || ! grep -q "chmod 1733 \"\\\$queue_dir\"" "$helper_bin/sloptrap-entrypoint"; then
record_failure "embedded_capability_helpers: entrypoint did not expose helper queue to the dropped user" record_failure "embedded_capability_helpers: entrypoint did not expose helper queue to the dropped user"
fi fi
@@ -950,6 +1064,86 @@ EOF
if ! grep -q -- 'podman --root ' "$tool_log" || ! grep -q -- '-v ./data:/data' "$tool_log"; then 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" record_failure "embedded_capability_helpers: sloppodman did not invoke podman with the validated run arguments"
fi fi
if ! grep -q -- 'setpriv --reuid 0 --regid 0 --clear-groups -- env ' "$tool_log"; then
record_failure "embedded_capability_helpers: sloppodman did not re-enter root before invoking podman"
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" image inspect example/image >/dev/null 2>&1; then
record_failure "embedded_capability_helpers: sloppodman rejected image inspect"
fi
if ! grep -q -- 'podman --root .* image inspect example/image' "$tool_log"; then
record_failure "embedded_capability_helpers: sloppodman did not forward image inspect"
fi
if ! grep -q -- '--storage-driver vfs' "$tool_log" \
|| ! grep -q -- '--cgroup-manager cgroupfs' "$tool_log" \
|| ! grep -q -- '--events-backend file' "$tool_log"; then
record_failure "embedded_capability_helpers: sloppodman did not apply the nested podman runtime defaults"
fi
if ! grep -q -- 'podman-env BUILDAH_ISOLATION=chroot ' "$tool_log"; then
record_failure "embedded_capability_helpers: sloppodman did not set BUILDAH_ISOLATION=chroot"
fi
if [[ ! -f $inner_runtime_dir/config/containers/storage.conf ]] \
|| [[ ! -f $inner_runtime_dir/config/containers/containers.conf ]]; then
record_failure "embedded_capability_helpers: sloppodman did not materialize its container config files"
elif ! grep -q -- 'ignore_chown_errors = "true"' "$inner_runtime_dir/config/containers/storage.conf"; then
record_failure "embedded_capability_helpers: storage.conf did not enable ignore_chown_errors"
fi
local caller_uid caller_gid caller_user
caller_uid=$(id -u)
caller_gid=$(id -g)
caller_user=$(id -un)
cat >"$helper_bin/id" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
case "${1-}" in
-u)
printf '0\n'
;;
-g)
printf '0\n'
;;
-un)
printf 'root\n'
;;
*)
printf 'uid=0(root) gid=0(root) groups=0(root)\n'
;;
esac
EOF
chmod +x "$helper_bin/id"
local caller_subuid root_subuid caller_subgid root_subgid
local helper_subuid_file helper_subgid_file
helper_subuid_file="$temp_root/helper-subuid"
helper_subgid_file="$temp_root/helper-subgid"
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" \
SLOPTRAP_PODMAN_ESCALATED=1 \
SLOPTRAP_PODMAN_CALLER_UID="$caller_uid" \
SLOPTRAP_PODMAN_CALLER_GID="$caller_gid" \
SLOPTRAP_PODMAN_CALLER_USER="$caller_user" \
SLOPTRAP_PODMAN_SUBUID_FILE="$helper_subuid_file" \
SLOPTRAP_PODMAN_SUBGID_FILE="$helper_subgid_file" \
"$helper_bin/sloppodman" image inspect example/image >/dev/null 2>&1; then
record_failure "embedded_capability_helpers: sloppodman did not synthesize caller and root subid files"
fi
caller_subuid=$(awk -F: -v account="$caller_user" '$1 == account { print $2 ":" $3 }' "$helper_subuid_file" 2>/dev/null || true)
root_subuid=$(awk -F: '$1 == "root" { print $2 ":" $3 }' "$helper_subuid_file" 2>/dev/null || true)
caller_subgid=$(awk -F: -v account="$caller_user" '$1 == account { print $2 ":" $3 }' "$helper_subgid_file" 2>/dev/null || true)
root_subgid=$(awk -F: '$1 == "root" { print $2 ":" $3 }' "$helper_subgid_file" 2>/dev/null || true)
if [[ -z $caller_subuid || $caller_subuid != "$root_subuid" ]]; then
record_failure "embedded_capability_helpers: sloppodman did not mirror caller subuid data onto root"
fi
if [[ -z $caller_subgid || $caller_subgid != "$root_subgid" ]]; then
record_failure "embedded_capability_helpers: sloppodman did not mirror caller subgid data onto root"
fi
TEST_TOOL_LOG="$tool_log" PATH="$helper_bin:$PATH" SLOPTRAP_HELPER_DIR="$helper_dir" \ TEST_TOOL_LOG="$tool_log" PATH="$helper_bin:$PATH" SLOPTRAP_HELPER_DIR="$helper_dir" \
SLOPTRAP_ACTIVE_CAPABILITIES="apt-install packet-capture" \ SLOPTRAP_ACTIVE_CAPABILITIES="apt-install packet-capture" \
@@ -1074,6 +1268,8 @@ run_runtime_context_prompt
run_sh_reexec run_sh_reexec
run_resume_omits_runtime_context run_resume_omits_runtime_context
run_auth_file_mount run_auth_file_mount
run_codex_home_override
run_recursive_slopsloptrap
run_project_state_isolation run_project_state_isolation
run_auto_login_empty_auth run_auto_login_empty_auth
run_codex_symlink_home run_codex_symlink_home