Problem
When a profile includes allowWrite paths under /run/user/<uid>/ (e.g. /run/user/1000/libvirt/*), the directory is not actually writable inside the sandbox because bwrap creates a fresh tmpfs at /run/user with only an empty /run/user/1000/ directory.
The Landlock layer correctly adds write rules for the specified paths, but the bwrap mount structure doesn't include --dir or --bind entries for subdirectories that need to exist, so programs like virsh fail with:
error: failed to connect to the hypervisor
error: Cannot create user runtime directory '/run/user/1000/libvirt': Permission denied
Reproduction
- Create a profile with:
{
"allowRead": ["/run/user/1000/libvirt/*", "/dev/kvm"],
"allowWrite": ["/run/user/1000/libvirt/*", "/dev/kvm"]
}
-
Run: greywall --profile libvirt -- virsh -c qemu:///session list
-
Observe the "Permission denied" error when virsh tries to create /run/user/1000/libvirt/.
Root cause
In the bwrap argument construction, /run/user is mounted as a tmpfs and /run/user/1000 is created with --dir. However, no --dir or --bind entries are added for subdirectories that appear in allowWrite.
The relevant bwrap args:
--tmpfs /run/user --dir /run/user/1000
Expected behavior
When allowWrite includes paths under /run/user/<uid>/, greywall should either:
- Add
--dir entries in bwrap for the parent directories (e.g. --dir /run/user/1000/libvirt)
- Or
--bind the host directory if it already exists (e.g. --bind /run/user/1000/libvirt /run/user/1000/libvirt)
The second option is probably better since it preserves existing sockets/state from the host (like the libvirt daemon socket).
Problem
When a profile includes
allowWritepaths under/run/user/<uid>/(e.g./run/user/1000/libvirt/*), the directory is not actually writable inside the sandbox because bwrap creates a fresh tmpfs at/run/userwith only an empty/run/user/1000/directory.The Landlock layer correctly adds write rules for the specified paths, but the bwrap mount structure doesn't include
--diror--bindentries for subdirectories that need to exist, so programs likevirshfail with:Reproduction
{ "allowRead": ["/run/user/1000/libvirt/*", "/dev/kvm"], "allowWrite": ["/run/user/1000/libvirt/*", "/dev/kvm"] }Run:
greywall --profile libvirt -- virsh -c qemu:///session listObserve the "Permission denied" error when virsh tries to create
/run/user/1000/libvirt/.Root cause
In the bwrap argument construction,
/run/useris mounted as a tmpfs and/run/user/1000is created with--dir. However, no--diror--bindentries are added for subdirectories that appear inallowWrite.The relevant bwrap args:
Expected behavior
When
allowWriteincludes paths under/run/user/<uid>/, greywall should either:--direntries in bwrap for the parent directories (e.g.--dir /run/user/1000/libvirt)--bindthe host directory if it already exists (e.g.--bind /run/user/1000/libvirt /run/user/1000/libvirt)The second option is probably better since it preserves existing sockets/state from the host (like the libvirt daemon socket).