Description
Files listed in allowWrite (such as ~/.claude.json) appear as read-only inside the sandbox when the sandboxed program uses atomic file writes. This affects Claude Code login, which writes to ~/.claude.json, and likely other tools that follow the same pattern (ssh writing known_hosts, git config, etc.).
Steps to Reproduce
- Add
~/.claude.json to allowWrite in a greywall profile
- Run
greywall -- claude login (or any command that triggers a write to ~/.claude.json)
- Claude reports "read only file system" for
~/.claude.json
Root Cause
Many programs use atomic file writes: they write to a temporary file (e.g. ~/.claude.json.tmp.PID.TIMESTAMP), then rename() the temp file over the target. This pattern breaks in greywall's Linux sandbox at two layers:
1. Bwrap: Cross-filesystem rename (EXDEV)
In DefaultDenyRead mode, the home directory is a tmpfs (--dir /home/user). Writable files get individual bind mounts from the host (--bind ~/.claude.json ~/.claude.json). When the program creates a temp file, it lands on the tmpfs. The target file is on the host filesystem (bind-mounted). rename() across different filesystems fails with EXDEV.
2. Landlock: No MAKE_REG on parent directory
When Landlock adds write rules for individual files (not directories), it strips directory-only rights like MAKE_REG, REMOVE_FILE, and REFER from the access mask. The file only gets WRITE_FILE + TRUNCATE (0x4002). Creating temp files in the parent directory is blocked by Landlock because the parent directory doesn't have MAKE_REG permission.
Impact
Any program that uses atomic writes to individually-listed writable files outside of CWD will fail. This includes:
- Claude Code (
~/.claude.json)
- SSH (
~/.ssh/known_hosts)
- Various CLI tools that write config files atomically
Environment
- Linux with Landlock (kernel 5.13+)
- DefaultDenyRead mode enabled
- Writable files listed individually in
allowWrite (not inside an already-writable directory like CWD)
Description
Files listed in
allowWrite(such as~/.claude.json) appear as read-only inside the sandbox when the sandboxed program uses atomic file writes. This affects Claude Code login, which writes to~/.claude.json, and likely other tools that follow the same pattern (ssh writingknown_hosts, git config, etc.).Steps to Reproduce
~/.claude.jsontoallowWritein a greywall profilegreywall -- claude login(or any command that triggers a write to~/.claude.json)~/.claude.jsonRoot Cause
Many programs use atomic file writes: they write to a temporary file (e.g.
~/.claude.json.tmp.PID.TIMESTAMP), thenrename()the temp file over the target. This pattern breaks in greywall's Linux sandbox at two layers:1. Bwrap: Cross-filesystem rename (EXDEV)
In DefaultDenyRead mode, the home directory is a tmpfs (
--dir /home/user). Writable files get individual bind mounts from the host (--bind ~/.claude.json ~/.claude.json). When the program creates a temp file, it lands on the tmpfs. The target file is on the host filesystem (bind-mounted).rename()across different filesystems fails withEXDEV.2. Landlock: No MAKE_REG on parent directory
When Landlock adds write rules for individual files (not directories), it strips directory-only rights like
MAKE_REG,REMOVE_FILE, andREFERfrom the access mask. The file only getsWRITE_FILE + TRUNCATE(0x4002). Creating temp files in the parent directory is blocked by Landlock because the parent directory doesn't haveMAKE_REGpermission.Impact
Any program that uses atomic writes to individually-listed writable files outside of CWD will fail. This includes:
~/.claude.json)~/.ssh/known_hosts)Environment
allowWrite(not inside an already-writable directory like CWD)