$RodHat_
MOTD

Landlock has been in the Linux kernel for five years. The adoption numbers are embarrassing.

Published by

Landlock has been in the Linux kernel for five years. The adoption numbers are embarrassing.
Photo: AI-generated — no human photographer / RodHat AI Cover

Linux 5.13 shipped in June 2021 with Landlock, an LSM that lets any process restrict its own access to the filesystem without root, without containers, without a seccomp filter table you have to maintain separately. Linux 6.7 added TCP and UDP socket restrictions on top of that. The kernel documentation has a complete, correct reference implementation.

Five years. I can tell you which production software actually calls landlock_create_ruleset(2). It will not take long.

Systemd uses it in some transient unit configurations, behind a setting maintainers have to know to look for. Bubblejail, the sandbox wrapper that nobody in your org has installed. A handful of experimental daemons with names you do not recognize. Some downstream ssh-agent patches that never made it to OpenSSH upstream.

That is roughly the list.

What OpenBSD did instead

Theo de Raadt shipped pledge(2) in OpenBSD 5.8, October 2015. He did not ship it as a library for motivated developers to adopt at their own pace. He spent the summer auditing the entire OpenBSD base system and wired pledge restrictions into every process before the release went out. The mail utilities, the network daemons, the editor, the compiler support binaries. All of them. By the time 5.8 users ran their first ssh after upgrading, sshd was already restricted to the minimum syscall categories it actually needs. The adoption was complete at release time because adoption was mandatory and the project did it centrally.

unveil(2) came in 2018, same pattern: shipped with the base system already ported. If a base system binary touches a file path it did not declare, the kernel returns ENOENT and the process gets audited. That is the enforcement mechanism. Not documentation. Not a developer option. Enforcement.

Linux does not work that way. Landlock is opt-in, implemented per application by the application’s maintainer, and it breaks when the application’s filesystem access pattern changes and nobody updates the Landlock ruleset to match. The maintenance cost lands on each individual project, and most projects decide there are higher priorities.

That is a structural difference between how OpenBSD and Linux treat security hardening. OpenBSD treats it as a property of the base system, applied once centrally. Linux treats it as a library feature each downstream project adopts independently. Neither approach is wrong as a philosophy. The outcome difference is that OpenBSD’s entire userspace has been pledge-restricted since 2015 and Linux’s has had Landlock available since 2021 with almost nothing using it.

Why the API is not the problem

The Landlock API is genuinely solid. Three syscalls, versioned ABI for forward compatibility, no root required, restrictions inherited by child processes and irrevocable once applied. Linux 6.7’s addition of LANDLOCK_ACCESS_NET_BIND_TCP and LANDLOCK_ACCESS_NET_CONNECT_TCP means a daemon can now declare “I only connect to TCP port 443” and have the kernel enforce that. The API surface is small and the kernel documentation is unusually clear for a Linux security feature.

The technical walkthrough in the tips archive covers the actual syscall wrappers, the ABI version negotiation you cannot skip, and the silent no-op that bites everyone the first time. The pledge and unveil walkthrough is the BSD side of the same picture if you want to see what mandatory adoption looked like in practice.

The gap between “solid API” and “widely deployed” is entirely a process problem. Landlock asks each project to enumerate its own filesystem and network access patterns, write 200 to 400 lines of C for the sandboxing setup, test it against every supported kernel version, and maintain it when the access patterns change. Most maintainers look at that cost and deprioritize it. It is not irrational on a per-project basis. The aggregate result is that a useful piece of kernel infrastructure sits unused.

The io_uring comparison runs the other direction

Yesterday’s post covered io_uring being restricted by default across production fleets: a kernel feature that was widely adopted, turned out to have an ugly security track record, and is now being gated. Landlock is the mirror image. A kernel security feature that nobody adopted that would have actually helped.

The pattern is consistent. Kernel features that make operations easier get adopted immediately. Kernel features that make systems more secure get adopted when something breaks.

What to do about it

If you maintain a daemon with a stable filesystem layout and predictable network access, Landlock is one afternoon of work. Read the kernel documentation linked below. The prctl process hardening reference covers the PR_SET_NO_NEW_PRIVS call you need before the Landlock restriction goes in. Wire it into your daemon’s early initialization, before it opens sockets or drops privileges. Test it against your oldest supported kernel. Add a fallback for kernels older than 5.13 where landlock_create_ruleset(2) returns ENOSYS.

The enforcement will tell you things about your daemon’s actual filesystem access that you probably did not know. That is part of the point.

Five years is long enough to stop waiting for someone else to do this.

Sources

  1. Landlock userspace API (Linux kernel documentation / Mickaël Salaün)
  2. pledge(2) manual page (OpenBSD project)