Step 1 of 5 · Reading · ~3 min
Read
Linux Namespaces
IPC Namespace
The sixth lie is the quietest: who else is in the room. Two processes that have never heard of each other can still share memory, provided they agree on a number. That is System V IPC, it predates Unix networking, and it has no permissions model worth the name — which is precisely why containers need it namespaced.
Two families, one namespace
CLONE_NEWIPC isolates exactly two things:
- System V IPC —
shmget,msgget,semget. Key-based: you pass an integer key, you get back an identifier. - POSIX message queues, the
/dev/mqueuetree.
And it isolates nothing else. Pipes, UNIX domain sockets, signals and eventfd are not in this namespace — sockets are files, so the mount namespace hides them; signals are addressed by pid, so the PID namespace does. Knowing which mechanism is isolated by which namespace is the difference between a working sidecar and a leak you cannot explain.
Why a key space is a security problem
A SysV key is a small integer that any process may guess, and the lookup was historically global:
(no IPC namespace)
container A: shmget(0xDEAD, 4096, IPC_CREAT) -> id 32768
container B: shmget(0xDEAD, 0, 0) -> id 32768 (!)
container B: shmat(32768) -> reads A's memory
With CLONE_NEWIPC, B's shmget finds nothing under that key: it either returns ENOENT or creates a brand-new segment that has nothing to do with A's. The key was never a secret; the namespace is what makes guessing it useless.
One detail that looks like an inconsistency and is not: ids come from one global allocator, keys are per namespace. Two namespaces can each own key K, and those two segments get different ids — but an id from another namespace is not resolvable in yours, so global uniqueness costs nothing and makes the kernel's own bookkeeping simpler.
Why the exercise is a simulator
unshare(CLONE_NEWIPC) needs CAP_SYS_ADMIN, which the sandbox running your submission does not have. What is left when you remove the syscall wrapper is the part that carries all the meaning: a key table per namespace, one id allocator for the machine, and a FIFO behind each queue.
Your exercise: IPC Namespace Isolation
| The kernel does | Your simulator does |
|---|---|
shmget(key, size, IPC_CREAT) — new segment, or EEXIST if the key is taken in this namespace | SHMGET <ns> <key> <size> — OK <id> or EEXIST |
ipcs -m — segments of the caller's namespace | SHMLIST <ns>, sorted by id |
msgget / msgsnd / msgrcv — a queue is a FIFO, and an empty one has nothing to hand back | MSGGET, MSGSEND, MSGRECV (EMPTY when drained) |
| a lookup crossing a namespace boundary simply finds nothing | PEEK <ns_a> <ns_b> <key> — 1 only when the two namespaces are the same |
PEEK is the exercise's whole thesis in one command: it can never print 1 across two namespaces, because there is no code path in your program — as there is none in the kernel — that reaches another namespace's key table. Isolation is not a check you perform; it is a table you never consult.
Reference: man 7 ipc_namespaces.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…