Linux Landlock - lightweight application sandboxing
Posted on October 1, 2026 • 3 minutes • 596 words
Linux has quite a few ways to restrict applications: permissions, SELinux/AppArmor, namespaces, seccomp, containers, …
A lesser known option is Landlock.
Landlock is a Linux Security Module (LSM) introduced in Linux 5.13. What makes it interesting is that an unprivileged process can restrict itself.
It can’t use Landlock to gain access to anything. It can only take access away.
This makes it quite useful as an additional security layer around applications or scripts you don’t completely trust.
Check if Landlock is available
Landlock needs kernel support and must be enabled as an LSM.
dmesg | grep -i landlock
You should see something similar to:
landlock: Up and running.
Landlock support was introduced in Linux 5.13, but newer kernels support considerably more Landlock features.
What does it actually do?
Imagine an application normally has access to:
/home/svennd/
/tmp/
/etc/
/results/
/work/
Linux permissions allow all of these.
With Landlock we can basically tell the kernel:
/usr read
/etc read
/work read/write
everything else: nope
The important part is that this happens in addition to normal Linux permissions.
Landlock cannot give:
user -> root
or bypass:
chmod
ACL
SELinux
AppArmor
It can only make the existing permissions more restrictive.
Simple example
The kernel contains a small example sandboxer in:
samples/landlock/sandboxer.c
After compiling it, it can be used roughly like:
LL_FS_RO="/usr:/bin:/lib:/lib64:/etc" \
LL_FS_RW="/tmp" \
./sandboxer /bin/bash
Inside the shell:
cat /etc/hostname
works.
Writing there:
echo test > /etc/test
doesn’t.
But:
echo test > /tmp/test
works.
The interesting thing is that the shell itself doesn’t need to run as root to apply these restrictions.
Restricting a program
This becomes more useful when running something potentially dangerous.
For example, imagine some data processing tool only needs:
/data/input read-only
/data/output read/write
/usr read-only
A policy could therefore look conceptually like:
/usr RO
/lib RO
/lib64 RO
/etc RO
/data/input RO
/data/output RW
Then execute:
sandbox -> python process.py
Even if process.py contains:
open("/home/svennd/.ssh/id_ed25519").read()
the kernel denies it.
Normal UNIX permissions might allow the Python process to read the file, but the additional Landlock policy does not.
Children inherit the restrictions
Another nice property is that the restriction applies to child processes.
So:
sandbox
|
+-- bash
|
+-- python
|
+-- curl
|
+-- something-evil
The child processes don’t magically escape the Landlock restrictions.
Once a process enters a Landlock domain it cannot simply remove that policy again. It can add additional restrictions, but not make itself less restricted.
Network restrictions
Landlock isn’t limited to filesystems anymore.
Newer Landlock ABIs can also restrict network operations, including TCP connections.
This means an application could for example be allowed to connect on:
TCP/443
while connections to other TCP ports are denied.
Network support has gradually expanded in newer Landlock versions, so what is available depends heavily on the kernel and Landlock ABI.
Landlock isn’t a container
Landlock should not be confused with Docker, bubblewrap or namespaces.
It doesn’t give an application its own filesystem or PID namespace.
Instead it adds another kernel access-control decision:
normal permissions
+
SELinux/AppArmor
+
Landlock
=
allowed?
That makes it particularly interesting for defence in depth.
For something truly untrusted I would still combine it with other mechanisms such as namespaces, seccomp and resource limits.
Why I like it
Landlock is surprisingly simple conceptually:
This program should only be able to access these things.
No root daemon is required and an application cannot use Landlock to give itself additional permissions.
This makes it an interesting extra layer for scripts, build systems, AI agents or other tools where the process normally runs with all the permissions of your user account.
