Docker outer layer and bwrap inner layer are mutually exclusive on this host (fresh proc mounts fail with kernel EPERM inside Docker's nested pidns, but work on the host under a userns profile). So tasks that need an inner sandbox run on the host: - Worker --claim-executor-only: strict executor claim (only executor == own type, never NULL). The host worker MUST use it, or it would steal NULL-executor tasks meant for Docker workers (those tasks would lose the Docker outer layer). Default behavior unchanged (NULL claimable by any worker). - host-config-host.json: sandbox workspace-write, state work/host-state-host.json (distinct from Docker tasks' host-state.json), same relay home and test repo as Docker. - deploy/apparmor/codex-host: docker-codex base + userns, mount, pivot_root for bwrap; still denies raw network, ptrace, dangerous capabilities, /proc/sys writes. - deploy/host-worker/codex-host-worker.service: aa-exec -p codex-host, --executor local --claim-executor-only, capacity 2, proxy env 127.0.0.1:8888 so host tasks' relay/git egress also goes through the Tinyproxy allowlist (host direct egress would bypass it). POST /tasks already accepts executor (local/docker/cloud), so no API change was needed for routing. Tests: 4 host-sandbox-routing tests (strict claim incl. CAS, default still takes NULL, config sandbox/state, profile allows bwrap without deny mount). Full suites pass.
86 lines
2.7 KiB
Plaintext
86 lines
2.7 KiB
Plaintext
# AppArmor profile for the HOST-LEVEL sandbox worker (codex-host-worker).
|
|
#
|
|
# This is docker-codex (outer hardening) PLUS what bwrap needs:
|
|
# - userns: allow creating user namespaces (bwrap's inner sandbox)
|
|
# - mount, umount, pivot_root: allow (bwrap mounts proc/tmpfs/binds
|
|
# and pivot_roots into the new root)
|
|
# It KEEPS docker-codex's denies: raw network, ptrace, dangerous
|
|
# capabilities, writes to /proc/sys, /sys, /proc/keys.
|
|
#
|
|
# Why a separate profile: docker-codex deliberately denies mount
|
|
# (containers must never mount; inner sandbox stays off there by
|
|
# choice). The host worker NEEDS mount+userns because its tasks
|
|
# run codex workspace-write (bwrap) directly on the host. The two
|
|
# profiles must not be confused: a task container under codex-host
|
|
# could bwrap (defeats the Docker-only design), and a host worker
|
|
# under docker-codex cannot bwrap at all (mount denied).
|
|
#
|
|
# Security note (honest): allowing mount+userns for the host worker
|
|
# means the WORKER process (trusted, codexsvc) can mount. The AGENT
|
|
# inside a task cannot mount on the host: its mounts happen inside
|
|
# bwrap's new mount namespace (isolated), and bwrap's pid namespace
|
|
# hides other tasks' processes. The agent's writable surface is its
|
|
# own worktree (+ a private tmpfs /tmp that never reaches host /tmp).
|
|
#
|
|
# Install: cp to /etc/apparmor.d/codex-host, then
|
|
# apparmor_parser -r /etc/apparmor.d/codex-host
|
|
# Use: aa-exec -p codex-host -- python3 -m cloud.worker ...
|
|
# (see deploy/host-worker/codex-host-worker.service)
|
|
# Verify: cat /proc/<worker-pid>/attr/current shows
|
|
# "codex-host (enforce)".
|
|
|
|
#include <tunables/global>
|
|
|
|
profile codex-host flags=(attach_disconnected,mediate_deleted) {
|
|
#include <abstractions/base>
|
|
|
|
network inet stream,
|
|
network inet dgram,
|
|
network inet6 stream,
|
|
network inet6 dgram,
|
|
deny network raw,
|
|
|
|
capability chown,
|
|
capability dac_override,
|
|
capability fsetid,
|
|
capability fowner,
|
|
capability mknod,
|
|
capability net_bind_service,
|
|
capability setfcap,
|
|
capability setgid,
|
|
capability setpcap,
|
|
capability setuid,
|
|
capability sys_chroot,
|
|
deny capability sys_admin,
|
|
deny capability sys_ptrace,
|
|
deny capability net_admin,
|
|
deny capability net_raw,
|
|
deny capability sys_module,
|
|
deny capability sys_rawio,
|
|
deny capability sys_boot,
|
|
deny capability sys_time,
|
|
deny capability mac_admin,
|
|
deny capability mac_override,
|
|
|
|
# bwrap needs these (docker-codex denies them).
|
|
userns,
|
|
mount,
|
|
umount,
|
|
pivot_root,
|
|
deny ptrace,
|
|
|
|
file,
|
|
deny @{PROC}/sys/** w,
|
|
deny @{PROC}/sysrq-trigger rw,
|
|
deny @{PROC}/keys/** rw,
|
|
deny @{PROC}/kcore rw,
|
|
deny /sys/** w,
|
|
deny /etc/shadow rw,
|
|
deny /etc/gshadow rw,
|
|
|
|
signal,
|
|
unix,
|
|
dbus,
|
|
ptrace (readby),
|
|
}
|