Python bindings for the Linux Landlock security module
Project description
py-landlock
Python bindings for the Linux Landlock security module.
Landlock is a Linux kernel feature that enables unprivileged processes to restrict their own access to the filesystem, network, and IPC resources. This library provides both a high-level API for common use cases and low-level access to the underlying syscalls.
Requirements
- Python 3.10 or later
- Linux kernel 5.13 or later with Landlock enabled
- Supported architectures: x86_64, aarch64
Installation
pip install py-landlock
Or with uv:
uv add py-landlock
Examples
Quick Start
from py_landlock import Landlock
Landlock() \
.allow_read("/usr", "/etc") \
.allow_execute("/usr/bin") \
.apply()
# Any attempt to write or access other paths now raises PermissionError
Check Availability
from py_landlock import get_abi_version, LandlockNotAvailableError
try:
version = get_abi_version()
print(f"Landlock ABI v{version}")
except LandlockNotAvailableError as e:
print(f"Not available: {e}")
Sandbox with Network Restrictions
from py_landlock import Landlock
Landlock() \
.allow_read("/usr", "/etc") \
.allow_read_write("/tmp/myapp") \
.allow_network(443, bind=False, connect=True) \
.apply()
For more examples, see the examples/ directory.
Usage
High-Level API
The Landlock class provides a fluent builder interface for constructing and applying security policies.
Filesystem Access Control
| Method | Description |
|---|---|
allow_read(*paths) |
Allow reading files and listing directories |
allow_write(*paths) |
Allow writing, creating, and removing files |
allow_execute(*paths) |
Allow executing files |
allow_read_write(*paths) |
Combination of read and write access |
add_path_rule(*paths, access) |
Add a rule with specific AccessFs flags |
Network Access Control
Network restrictions require kernel ABI version 4 or later.
| Method | Description |
|---|---|
allow_network(*ports, bind, connect) |
Allow TCP bind and/or connect on specified ports |
allow_all_network() |
Disable network restrictions entirely |
Scope Restrictions
Scope restrictions limit IPC and signal delivery to processes within the same Landlock domain. Requires kernel ABI version 6 or later.
| Method | Description |
|---|---|
allow_scope(scope) |
Exempt specific scope restrictions |
allow_all_scope() |
Disable all scope restrictions |
Strict vs Best-Effort Mode
By default, the library operates in strict mode and raises CompatibilityError if a requested feature is not supported by the running kernel. Use Landlock(strict=False) for best-effort mode which silently ignores unsupported features.
ABI Compatibility
Landlock uses ABI versioning to maintain backward compatibility as new features are added. The kernel's ABI version determines which access rights are available:
| ABI Version | Kernel Version | Features Added |
|---|---|---|
| 1 | 5.13 | Basic filesystem access control |
| 2 | 5.19 | File referring (REFER) |
| 3 | 6.2 | File truncation (TRUNCATE) |
| 4 | 6.7 | TCP network restrictions |
| 5 | 6.10 | Device IOCTL (IOCTL_DEV) |
| 6 | 6.12 | Scope restrictions (abstract UNIX, signals) |
| 7 | 6.14 | Audit logging control |
Low-Level API
For advanced use cases, the library exposes the underlying syscall wrappers:
from py_landlock import (
create_ruleset,
add_rule,
restrict_self,
RulesetAttr,
PathBeneathAttr,
AccessFs,
)
attr = RulesetAttr()
attr.handled_access_fs = AccessFs.READ_FILE | AccessFs.WRITE_FILE
ruleset_fd = create_ruleset(attr)
path_attr = PathBeneathAttr.from_path("/tmp", AccessFs.READ_FILE | AccessFs.WRITE_FILE)
add_rule(ruleset_fd, path_attr)
restrict_self(ruleset_fd)
Error Handling
| Exception | Description |
|---|---|
LandlockError |
Base exception for all Landlock errors |
LandlockNotAvailableError |
Landlock not available (wrong platform, architecture, or kernel) |
LandlockDisabledError |
Landlock supported but disabled at boot |
RulesetError |
Failed to create, configure, or apply a ruleset |
PathError |
Specified path does not exist |
CompatibilityError |
Requested feature requires a higher ABI version |
NetworkDisabledError |
TCP/IP not available in kernel |
Threading
Landlock rules apply to the calling thread and are inherited by all threads and processes it creates afterward. Key behaviors:
- Rules cannot be removed once applied
- Each thread can add additional restrictions to itself
- Child threads and processes inherit all restrictions from their parent
- A thread cannot relax restrictions inherited from its parent
Limitations
Landlock has several limitations documented in the kernel documentation:
-
Filesystem topology: Sandboxed threads cannot modify filesystem topology via
mount(2)orpivot_root(2). However,chroot(2)is permitted. -
Special filesystems: Files from non-user-visible filesystems (such as pipes and sockets) accessible through
/proc/<pid>/fd/*cannot be explicitly restricted. Special kernel filesystems like nsfs also cannot be directly restricted. -
Ruleset stacking limit: A maximum of 16 stacked rulesets can be applied. Once this limit is reached,
restrict_self()returnsE2BIG. This can be problematic for programs that launch other sandboxed programs. -
IOCTL restrictions: The
IOCTL_DEVaccess right only applies to device files opened after the ruleset is applied. Pre-existing file descriptors (stdin, stdout, stderr) are unaffected. -
Network restrictions: Only TCP bind and connect operations can be restricted. UDP, ICMP, and other protocols are not covered.
Resources
- Landlock website
- Linux kernel documentation
- rust-landlock - Rust bindings
- go-landlock - Go bindings
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file py_landlock-0.1.0.tar.gz.
File metadata
- Download URL: py_landlock-0.1.0.tar.gz
- Upload date:
- Size: 16.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.9.22 {"installer":{"name":"uv","version":"0.9.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9a458931fd730cbb8201dac43fa36ba665522094dc8cb82e9ed77ecc9368244a
|
|
| MD5 |
81a2c59e93315e4b4909d06871d47fd3
|
|
| BLAKE2b-256 |
077d40bcd6f7afb0a0a3e891593d55eadb0ce72b0afeb62c95e215f5f0b5b344
|
File details
Details for the file py_landlock-0.1.0-py3-none-any.whl.
File metadata
- Download URL: py_landlock-0.1.0-py3-none-any.whl
- Upload date:
- Size: 16.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.9.22 {"installer":{"name":"uv","version":"0.9.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9cbc36a35460fa4b02c0006b7645e1dd20d23e965dff8d7c114b3b0d9812bb70
|
|
| MD5 |
f18ff841fd4e964191ac0265282d66fd
|
|
| BLAKE2b-256 |
7b70701163344a112913d953ab2223f9b7fed135ba9abd94200dfdfecd993855
|