[Bug]: publish-socket cannot relay a socket on tmpfs with read-only root
- Dominant language
- Swift
- Stars
- 49.9k
- Forks
- 1.8k
- Avg merge
- 1d 20h
- Merged PRs (30d)
- 22
Description
## Summary
`--publish-socket` accepts a host connection but does not relay it to a Unix socket created under `/dev/shm` in a `--read-only` container. The host receives EOF. The same socket server works from inside the container, and a writable-root `/tmp` control relays successfully.
This makes it impossible to combine a read-only root filesystem with a container-to-host Unix control socket whose mutable state lives on tmpfs.
## Minimal reproduction
Start the service:
```sh
container system start
container run --detach --name uds-tmpfs-test \
--platform linux/arm64 \
--network none --no-dns \
--read-only --shm-size 64M \
--publish-socket /tmp/uds-tmpfs-test.sock:/dev/shm/relay.sock \
--entrypoint /usr/local/bin/python3.11 \
python:3.11-slim-bookworm \
-c 'import os,socket; p="/dev/shm/relay.sock"; s=socket.socket(socket.AF_UNIX); s.bind(p); os.chmod(p, 0o777); s.listen(); c,_=s.accept(); c.sendall(c.recv(4))'
```
From the host, after `/tmp/uds-tmpfs-test.sock` exists:
```sh
python3 - <<'PY'
import socket
s = socket.socket(socket.AF_UNIX)
s.connect("/tmp/uds-tmpfs-test.sock")
s.sendall(b"PING")
print(repr(s.recv(4)))
PY
```
Expected: `b'PING'`.
Actual: `b''`.
The server socket is deliberately root-owned and mode `0777`; `/dev/shm` is root-owned and mode `1777`. A direct client run inside the same container receives `b'PING'` from `/dev/shm/relay.sock`.
## Control
The same server and host client work when the root filesystem is writable and the relay target is `/tmp/relay.sock`:
```sh
# Omit --read-only and replace both /dev/shm/relay.sock occurrences with /tmp/relay.sock.
```
The host client then prints `b'PING'`.
A second strict control with `--read-only --tmpfs /run` and target `/run/relay.sock` also returns `b''` from the host.
## Why this appears to be a relay/path-visibility problem
The CLI configures a published socket as an `outOf` Unix socket relay ([source](https://github.com/apple/container/blob/5973b9cc626a3e7a499bb316a958237ebe14e2ed/Sources/Services/RuntimeLinux/Server/RuntimeService.swift#L1023-L1031)). The pinned Containerization dependency resolves that source beneath the container rootfs before asking vminitd to relay it ([source](https://github.com/apple/containerization/blob/44bec8b9933bc491d0cbf44abac90a1f6aaebf6b/Sources/Containerization/LinuxContainer.swift#L1050-L1076)); the guest proxy subsequently opens a Unix socket at that path ([source](https://github.com/apple/containerization/blob/44bec8b9933bc491d0cbf44abac90a1f6aaebf6b/vminitd/Sources/VminitdCore/VsockProxy.swift#L205-L214)).
The observed behavior is consistent with the relay not seeing a socket on the process namespace tmpfs. I cannot directly inspect vminitd's mount namespace through the supported CLI, so this is an inference rather than a claim of root cause.
Is publishing a socket from `/dev/shm` or an explicit container tmpfs expected to work? If not, is there a supported way to expose one container-owned Unix socket while keeping the root filesystem read-only?
## Environment
- macOS 26.5.2 (25F84)
- Container CLI 1.1.0 (`5973b9c`)
- Apple silicon / `linux/arm64`
- Xcode unavailable; Command Line Tools selected
I searched existing issues for published-socket/tmpfs/read-only reports and did not find a match. I agree to follow the Code of Conduct.
Contributor guide
Research direction
Run the minimal reproduction with --read-only and /dev/shm first, then compare it with the writable-root /tmp control. Read RuntimeService.swift around the --publish-socket configuration, followed by LinuxContainer.swift and VsockProxy.swift at the linked lines. Done means establishing whether published sockets on container tmpfs are supported and, if so, making the host client receive b'PING' under the strict controls.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- swift
- Domain
- cli, operating-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 50/100