Skip to content

vmexec: enter the container's IPC namespace on exec - #851

Merged
crosbymichael merged 1 commit into
apple:mainfrom
crosbymichael:exec-ipc-namespace
Aug 27, 2026
Merged

vmexec: enter the container's IPC namespace on exec#851
crosbymichael merged 1 commit into
apple:mainfrom
crosbymichael:exec-ipc-namespace

Conversation

@crosbymichael

Copy link
Copy Markdown
Contributor

ExecCommand.execInNamespaces entered a hardcoded CLONE_NEWCGROUP | CLONE_NEWPID | CLONE_NEWUTS | CLONE_NEWNS, while the init process gets its namespaces from the OCI spec via RunCommand.setupNamespaces — which includes CLONE_NEWIPC whenever the spec lists an ipc namespace. LinuxContainer (and LinuxPod) always declare one, so the init process runs in a private IPC namespace and every exec'd process stays in the guest's root one.

The effect is that an exec cannot see SysV IPC segments or POSIX message queues created by the workload — and anything the exec creates leaks into the guest's root namespace, where it outlives the container. IPC-namespaced sysctls (kernel.shm*, kernel.msg*, kernel.sem, fs.mqueue.*) also read back as the guest default, because they resolve against the reading process's IPC namespace. That last one is what fails critest's "should support safe sysctls" and "should support unsafe sysctls", which set such a sysctl and read it back over ExecSync.

Add CLONE_NEWIPC to the mask. setns(2) into a namespace the caller is already in is a no-op, so the mask is now a superset of everything setupNamespaces can unshare rather than a set that has to be kept in sync by hand. CLONE_NEWUSER stays out deliberately: nothing puts a container in a user namespace today, and entering one carries constraints that deserve their own change.

The integration test asserts the general invariant rather than the specific sysctl: inside an exec, /proc/self/ns/* must equal /proc/1/ns/* for ipc, uts, mnt, pid, cgroup, and net. kernel.shm_rmid_forced is checked alongside it as the consumer-visible symptom.

`ExecCommand.execInNamespaces` entered a hardcoded
`CLONE_NEWCGROUP | CLONE_NEWPID | CLONE_NEWUTS | CLONE_NEWNS`, while the
init process gets its namespaces from the OCI spec via
`RunCommand.setupNamespaces` — which includes `CLONE_NEWIPC` whenever the
spec lists an `ipc` namespace. `LinuxContainer` (and `LinuxPod`) always
declare one, so the init process runs in a private IPC namespace and every
exec'd process stays in the guest's root one.

The effect is that an exec cannot see SysV IPC segments or POSIX message
queues created by the workload — and anything the exec creates leaks into
the guest's root namespace, where it outlives the container. IPC-namespaced
sysctls (`kernel.shm*`, `kernel.msg*`, `kernel.sem`, `fs.mqueue.*`) also
read back as the guest default, because they resolve against the reading
process's IPC namespace. That last one is what fails critest's "should
support safe sysctls" and "should support unsafe sysctls", which set such a
sysctl and read it back over ExecSync.

Add `CLONE_NEWIPC` to the mask. `setns(2)` into a namespace the caller is
already in is a no-op, so the mask is now a superset of everything
`setupNamespaces` can unshare rather than a set that has to be kept in sync
by hand. `CLONE_NEWUSER` stays out deliberately: nothing puts a container in
a user namespace today, and entering one carries constraints that deserve
their own change.

The integration test asserts the general invariant rather than the specific
sysctl: inside an exec, `/proc/self/ns/*` must equal `/proc/1/ns/*` for
`ipc`, `uts`, `mnt`, `pid`, `cgroup`, and `net`. `kernel.shm_rmid_forced` is
checked alongside it as the consumer-visible symptom.

Signed-off-by: michael_crosby <michael_crosby@apple.com>
@crosbymichael
crosbymichael merged commit 4294c0f into apple:main Aug 27, 2026
7 checks passed
@crosbymichael
crosbymichael deleted the exec-ipc-namespace branch August 27, 2026 19:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants