Feature #8606 » Suricata(2).md
Landlock V3/V5 coverage gap in Suricata's src/util-landlock.c
Affected file: src/util-landlock.c (master)
Issue class: Landlock policy declares an incomplete handled_access_fs mask; V3 (LANDLOCK_ACCESS_FS_TRUNCATE) and V5 (LANDLOCK_ACCESS_FS_IOCTL_DEV) access rights are never mediated, even on kernels that support them.
Severity: Moderate. The defect is a structural sandbox coverage gap rather than a memory-safety bug. On a default Fedora deployment no secondary defense layer mediates these access classes either (audit below). Fix is small and uncontroversial.
Suggested coordination window: standard 90 days.
1. The finding
src/util-landlock.c:77-83 declares the WRITE-access mask Suricata's Landlock policy will handle:
#define _LANDLOCK_ACCESS_FS_WRITE \
(LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_REMOVE_DIR | \
LANDLOCK_ACCESS_FS_REMOVE_FILE | LANDLOCK_ACCESS_FS_MAKE_CHAR | \
LANDLOCK_ACCESS_FS_MAKE_DIR | LANDLOCK_ACCESS_FS_MAKE_REG | \
LANDLOCK_ACCESS_FS_MAKE_SOCK | LANDLOCK_ACCESS_FS_MAKE_FIFO | \
LANDLOCK_ACCESS_FS_MAKE_BLOCK | LANDLOCK_ACCESS_FS_MAKE_SYM | \
LANDLOCK_ACCESS_FS_REFER)
This includes V1 access bits + LANDLOCK_ACCESS_FS_REFER (V2). It does NOT include:
-
LANDLOCK_ACCESS_FS_TRUNCATE(V3, bit 14, kernel ≥ 5.19) -
LANDLOCK_ACCESS_FS_IOCTL_DEV(V5, bit 15, kernel ≥ 6.10)
The narrower _LANDLOCK_SURI_ACCESS_FS_WRITE at lines 87-89 (the mask actually used for write-path rules in LandlockSandboxingWritePath) has the same gap.
The ABI gate at lines 107-120 is downgrade-only:
int abi = landlock_create_ruleset(NULL, 0, LANDLOCK_CREATE_RULESET_VERSION);
...
if (abi < 2) {
ruleset->attr.handled_access_fs &= ~LANDLOCK_ACCESS_FS_REFER;
}
The only conditional branch is if (abi < 2) — there is no upward branch for V3, V5, or V6, so on an ABI-7 kernel the handled_access_fs mask is still the V1+REFER subset.
What this means at runtime
Landlock's contract: if the kernel handles an access-right bit but the policy does not include it in handled_access_fs, that access right is not mediated by Landlock at all. So:
- A sandboxed Suricata process can
ftruncate()any file inside a path-beneath grant. The directory was granted "write" viaLANDLOCK_ACCESS_FS_WRITE_FILE, buttruncate()is governed by the separateLANDLOCK_ACCESS_FS_TRUNCATEbit since V3 — and that bit is unhandled, so the kernel passes the syscall straight through. - A sandboxed Suricata process can
ioctl()on any device file inside a path-beneath grant.LANDLOCK_ACCESS_FS_IOCTL_DEVis unhandled, so device-ioctl mediation never happens.
2. Independent verification
Four cross-checks, all agreeing:
2.1 Kernel header (authoritative bit values)
/usr/include/linux/landlock.h on Fedora 43:
LANDLOCK_ACCESS_FS_REFER (1ULL << 13) /* V2 */
LANDLOCK_ACCESS_FS_TRUNCATE (1ULL << 14) /* V3 */
LANDLOCK_ACCESS_FS_IOCTL_DEV (1ULL << 15) /* V5 */
2.2 Symbol grep across src/
$ grep -rn 'LANDLOCK_ACCESS_FS_TRUNCATE\|LANDLOCK_ACCESS_FS_IOCTL_DEV\|LANDLOCK_SCOPED' src/
(no matches)
The bits are not referenced anywhere in the tree — not just absent from the WRITE masks.
2.3 Upstream verification
Diffed local clone of OISF/suricata (master @ 367ca7f430f85be01a6cdc65ddaa1636a50ddefc, 2026-05-16) against a live fetch of https://raw.githubusercontent.com/OISF/suricata/master/src/util-landlock.c:
$ diff -q util-landlock.c upstream-util-landlock.c
(no diff — byte-identical, 293 lines)
The defect is still present on master as of the verification date.
2.4 ABI-gate visual inspection
The only ABI-version conditional in the file is if (abi < 2) at line 112. There is no if (abi >= 3) handled_access_fs |= TRUNCATE branch and no if (abi >= 5) ... |= IOCTL_DEV. Even on an ABI-7 kernel (Fedora 43 ships this), the ruleset declares it handles only the V1+REFER subset.
3. Secondary-defense audit (Fedora 43, suricata-7.0.15-1.fc43)
The question: with the Landlock layer's gap on TRUNCATE and IOCTL_DEV, what other layers in the deployed environment mediate these access classes?
| Layer | Status | Catches TRUNCATE / IOCTL_DEV? |
|---|---|---|
| Upstream Landlock policy (when enabled) | Present in source |
No — handled_access_fs missing both bits (this finding) |
do_setuid / do_setgid privilege drop |
Yes — drops to suricata user |
No — LSM-level bit, not POSIX-perms-based |
PR_SET_NO_NEW_PRIVS |
Only inside the Landlock path (util-landlock.c:133) |
No |
| Fedora systemd unit hardening | Four directives shipped: MemoryDenyWriteExecute=true, LockPersonality=true, ProtectControlGroups=true, ProtectKernelModules=true
|
No — none of these mediate ftruncate() or ioctl(). No SystemCallFilter=, no PrivateDevices=, no ProtectSystem=, no NoNewPrivileges=
|
Fedora SELinux suricata_t domain |
Not shipped. Verified: rpm -ql selinux-policy-targeted | grep suri → empty. seinfo -t | grep suricata → empty. No .fc/.te in the suricata RPM. |
Suricata runs in unconfined_service_t — no SELinux confinement |
| seccomp filter inside Suricata |
Zero references — grep -rn seccomp src/ → no matches |
No |
| AppArmor profile | N/A on Fedora (Fedora is SELinux-only); Debian/Ubuntu untested | — |
Compounding observations
Two adjacent issues compound with the V3/V5 gap on the default Fedora deployment story:
-
Default-disabled sandbox:
util-landlock.c:186-192—security.landlock.enableddefaults to0. An admin who doesn't explicitly opt in gets zero Landlock at all, not just zero V3/V5 mediation. -
Silent-failure mode:
util-landlock.c:131-140—LandlockEnforceRulesetlogs onprctl(PR_SET_NO_NEW_PRIVS)orlandlock_restrict_self()failure and returns silently. The enclosingLandlockSandboxingisvoid-returning, so failure doesn't reach an operational error path.
Conclusion (default Fedora deployment)
A compromised Suricata process can:
-
ftruncate()any file inside a_LANDLOCK_SURI_ACCESS_FS_WRITE-granted directory. No Landlock mediation, no seccomp belt (noSystemCallFilter=), no SELinux confinement. Anti-forensics implication: liveeve.json,fast.log, and rotated log files are all reachable for truncation. -
ioctl()on device files in any allowed path. Suricata typically holds an open file descriptor on/dev/<nic>or equivalent for packet capture; ioctl on that fd is unrestricted. No Landlock mediation, noPrivateDevices=truein the unit file.
4. Suggested patches
Upstream
-
Add the missing bits to
_LANDLOCK_ACCESS_FS_WRITE, conditionally, gated by the probed ABI:/* after the existing `if (abi < 2)` downgrade: */ if (abi >= 3) { ruleset->attr.handled_access_fs |= LANDLOCK_ACCESS_FS_TRUNCATE; } if (abi >= 5) { ruleset->attr.handled_access_fs |= LANDLOCK_ACCESS_FS_IOCTL_DEV; }This needs fallback
#ifndef LANDLOCK_ACCESS_FS_TRUNCATE/#ifndef LANDLOCK_ACCESS_FS_IOCTL_DEVshims for build environments older than the relevant kernel headers, mirroring the existing#ifndef LANDLOCK_ACCESS_FS_REFERshim at line 73.While in the area, V6 scope rules (
LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET,LANDLOCK_SCOPE_SIGNAL) are also worth adopting — they close a separate class of escape via the systemd user bus on user-mode sandboxes (see GHSA-27vp-2mmc-vmh3 for the published shape). -
Flip
security.landlock.enabledto default-on, or document the implication prominently in the deployment guide. -
Make
LandlockSandboxingreturn an error and propagate it. Operational failure to apply the sandbox should be visible to operators, not buried in a log line.
Downstream-distro (worth raising with packagers)
-
Fedora spec file: ask packagers to add
SystemCallFilter=@system-service,PrivateDevices=true,RestrictAddressFamilies=AF_INET AF_INET6 AF_PACKET AF_NETLINK,NoNewPrivileges=trueto/usr/lib/systemd/system/suricata.service. These are independent of Landlock; they catchftruncate/ioctland many other syscalls via systemd's own seccomp/namespace machinery. -
Fedora SELinux: ship a
suricata_tconfined domain. -
Debian/Ubuntu (untested): confirm the AppArmor profile (if any) covers
TRUNCATE/IOCTLon the log dir and device files.
5. Provenance
- Upstream repository:
OISF/suricata, branchmaster, commit367ca7f430f85be01a6cdc65ddaa1636a50ddefc. - Upstream live-fetch URL:
https://raw.githubusercontent.com/OISF/suricata/master/src/util-landlock.c(byte-identical to commit above as of verification date). - Verification dates: 2026-05-22 (initial), 2026-05-24 (secondary-defense audit).
- Kernel headers consulted:
/usr/include/linux/landlock.hon Fedora 43. - Tested Fedora package:
suricata-7.0.15-1.fc43.x86_64(downloaded viadnf download suricata, not installed). - Tested SELinux policy:
selinux-policy-targeted-43.7-1.fc43.noarch.
6. Deliberately out of scope
- No exploit PoC binary included. The compromise primitive ("a compromised Suricata parser") is taken as given — that is the threat model Suricata's own Landlock effort presumes. Building a parser-exploit PoC would shift the framing from "policy gap" to "offensive showcase," which is not the intent of this report.
-
No proof-of-anti-forensics demo included. The
ftruncate(eve.json)exploit is feasible but not implemented; this report points to the gap, not at a working anti-forensics tool. -
No Debian/Ubuntu reproduction. This audit is Fedora-only. If desirable, a follow-up Debian/Ubuntu pass should check the AppArmor profile shipped under
/etc/apparmor.d/usr.sbin.suricata(if any) and the Debian systemd unit's hardening directives.