Summary
internal/assets/apply-nftables.sh emits an nftables rule to block the target cgroup from reaching the leashd control plane, but nft rejects it with a syntax error when TARGET_CGROUP is a filesystem cgroup path (which contains /). leashd then falls back to blocking all local access to the control-plane port, degrading the intended cgroup-scoped isolation to a namespace-wide block.
Where
internal/assets/apply-nftables.sh, the leash:block-control-plane rule:
nft add rule inet leash out_filter socket cgroupv2 level 1 "$TARGET_CGROUP" \
tcp dport $LEASH_PORT reject with tcp reset comment "leash:block-control-plane"
Observed
With TARGET_CGROUP set to a host cgroup path (e.g. /sys/fs/cgroup/system.slice/<unit>), on a Linux host whose kernel does support nft_socket cgroupv2:
Error: syntax error, unexpected /
add rule inet leash out_filter socket cgroupv2 level 1 /sys/fs/cgroup/system.slice/<unit> tcp dport 18080 reject with tcp reset comment leash:block-control-plane
^
leash: WARNING: cgroup-based control plane isolation unavailable (nftables); blocking all local access to control plane port 18080
leash: blocked local access to control plane port 18080 (fallback nftables)
The caret points at the first / of the cgroup path.
Impact
The script's fallback still blocks the port for all local processes, so this is not a security regression — but:
- the intended cgroup-scoped isolation is lost: every local process is blocked from the control-plane port, not just the target cgroup;
- the alarming
Error: / WARNING: output appears on every run.
This is distinct from the existing "kernel lacks nft_socket cgroupv2 support" fallback (e.g. LinuxKit on Docker Desktop). Here the kernel supports the match — the rule text itself fails to parse.
Likely cause
socket cgroupv2 level N <path> needs the path as an nft string literal (and, I believe, relative to the cgroup2 mount root — i.e. without the /sys/fs/cgroup prefix). The shell-level "$TARGET_CGROUP" quoting does not survive to nft (nft receives the bare path via argv and chokes on the /). Quoting the path in nft syntax and/or stripping the /sys/fs/cgroup prefix should fix it — but I have not confirmed the exact form the matcher wants.
Environment
- Linux host,
bpf in the active LSM list, nft_socket cgroupv2 support present
- nftables (
nft) available; the cgroup-scoped rule is attempted and the fallback is taken
Happy to test a proposed fix.
Summary
internal/assets/apply-nftables.shemits an nftables rule to block the target cgroup from reaching the leashd control plane, butnftrejects it with a syntax error whenTARGET_CGROUPis a filesystem cgroup path (which contains/). leashd then falls back to blocking all local access to the control-plane port, degrading the intended cgroup-scoped isolation to a namespace-wide block.Where
internal/assets/apply-nftables.sh, theleash:block-control-planerule:Observed
With
TARGET_CGROUPset to a host cgroup path (e.g./sys/fs/cgroup/system.slice/<unit>), on a Linux host whose kernel does supportnft_socketcgroupv2:The caret points at the first
/of the cgroup path.Impact
The script's fallback still blocks the port for all local processes, so this is not a security regression — but:
Error:/WARNING:output appears on every run.This is distinct from the existing "kernel lacks
nft_socketcgroupv2 support" fallback (e.g. LinuxKit on Docker Desktop). Here the kernel supports the match — the rule text itself fails to parse.Likely cause
socket cgroupv2 level N <path>needs the path as an nft string literal (and, I believe, relative to the cgroup2 mount root — i.e. without the/sys/fs/cgroupprefix). The shell-level"$TARGET_CGROUP"quoting does not survive tonft(nft receives the bare path via argv and chokes on the/). Quoting the path in nft syntax and/or stripping the/sys/fs/cgroupprefix should fix it — but I have not confirmed the exact form the matcher wants.Environment
bpfin the active LSM list,nft_socketcgroupv2 support presentnft) available; the cgroup-scoped rule is attempted and the fallback is takenHappy to test a proposed fix.