### Quick Start Example Source: https://github.com/sebastienwae/py-landlock/blob/main/README.md Demonstrates a basic usage of the Landlock class to allow read and execute permissions on specified paths and then applies the policy. ```APIDOC ## Quick Start Example ### Description This example shows how to initialize the Landlock object, define read and execute permissions for specific directories, and apply the security policy. After applying, any attempt to write or access unauthorized paths will result in a `PermissionError`. ### Code ```python from py_landlock import Landlock Landlock() \ .allow_read("/usr", "/etc") \ .allow_execute("/usr/bin") \ .apply() ``` ``` -------------------------------- ### Install py-landlock Source: https://github.com/sebastienwae/py-landlock/blob/main/README.md Install the library using pip or uv. Ensure Python 3.10+ and a compatible Linux kernel are available. ```bash pip install py-landlock ``` ```bash uv add py-landlock ``` -------------------------------- ### Low-Level API Example Source: https://github.com/sebastienwae/py-landlock/blob/main/README.md Demonstrates the usage of the low-level API for creating rulesets, adding rules, and restricting the current process. ```APIDOC ## Low-Level API Example ### Description This example showcases the low-level API for advanced Landlock configurations. It involves creating a ruleset with specific file access attributes, adding a path-based rule, and then applying the restrictions to the current process. ### Code ```python from py_landlock import ( create_ruleset, add_rule, restrict_self, RulesetAttr, PathBeneathAttr, AccessFs, ) # Define attributes for the ruleset, granting read and write file access attr = RulesetAttr() attr.handled_access_fs = AccessFs.READ_FILE | AccessFs.WRITE_FILE # Create the ruleset file descriptor ruleset_fd = create_ruleset(attr) # Define attributes for a path-based rule, granting read and write access beneath /tmp path_attr = PathBeneathAttr.from_path("/tmp", AccessFs.READ_FILE | AccessFs.WRITE_FILE) # Add the path rule to the ruleset add_rule(ruleset_fd, path_attr) # Apply the ruleset to the current process restrict_self(ruleset_fd) ``` ``` -------------------------------- ### Low-Level Landlock API Example Source: https://github.com/sebastienwae/py-landlock/blob/main/README.md Demonstrates creating a ruleset, adding a path rule with specific access flags, and applying the ruleset to the current process using the low-level syscall wrappers. ```python 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) ``` -------------------------------- ### Quick Start Landlock Policy Source: https://github.com/sebastienwae/py-landlock/blob/main/README.md Apply basic filesystem restrictions: allow reading from /usr and /etc, and executing from /usr/bin. Any write attempts will raise a PermissionError. ```python 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 Landlock Availability Source: https://github.com/sebastienwae/py-landlock/blob/main/README.md Provides an example of how to check if Landlock is available on the system and retrieve its ABI version, handling potential `LandlockNotAvailableError`. ```APIDOC ## Check Landlock Availability ### Description This snippet demonstrates how to check for Landlock availability using `get_abi_version()`. It includes a try-except block to catch `LandlockNotAvailableError` and print an appropriate message if Landlock is not supported or enabled. ### Code ```python 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}") ``` ``` -------------------------------- ### Get Landlock ABI Version Source: https://context7.com/sebastienwae/py-landlock/llms.txt Queries the kernel's Landlock ABI version. Raises `LandlockNotAvailableError` if Landlock is unavailable or `LandlockDisabledError` if disabled at boot. Useful for checking feature availability like TCP network or IPC scope restrictions. ```python from py_landlock import get_abi_version, LandlockNotAvailableError, LandlockDisabledError try: version = get_abi_version() print(f"Landlock ABI version: {version}") # V1 = kernel 5.13, V2 = 5.19, V3 = 6.2, V4 = 6.7, V5 = 6.10, V6 = 6.12, V7 = 6.14 if version >= 4: print("TCP network restrictions available") if version >= 6: print("IPC scope restrictions available") except LandlockNotAvailableError as e: print(f"Landlock not available: {e}") # Requires Linux 5.13+ with CONFIG_SECURITY_LANDLOCK=y except LandlockDisabledError as e: print(f"Landlock disabled at boot: {e}") # Re-enable with: kernel parameter landlock.mode=1 ``` -------------------------------- ### Get Landlock ABI Errata Bitmask Source: https://context7.com/sebastienwae/py-landlock/llms.txt Retrieves a bitmask indicating fixed kernel bugs for the current Landlock ABI version. Each bit corresponds to a documented kernel errata. ```python from py_landlock import get_abi_errata errata = get_abi_errata() print(f"Errata bitmask: {errata:#010b}") # Each bit corresponds to a documented kernel errata being fixed ``` -------------------------------- ### Initialize Landlock Builder (Strict and Best-Effort Modes) Source: https://context7.com/sebastienwae/py-landlock/llms.txt Initializes the `Landlock` builder. Strict mode raises `CompatibilityError` for unsupported features, while best-effort mode silently skips them. Handles `LandlockNotAvailableError` if the module is not available. ```python from py_landlock import Landlock, CompatibilityError, LandlockNotAvailableError # Strict mode (default): raises CompatibilityError on unsupported features try: ll = Landlock(strict=True) print(f"ABI version: {ll.abi_version}") # e.g. 6 except LandlockNotAvailableError as e: print(f"Landlock not available: {e}") # Best-effort mode: silently ignores unsupported features ll = Landlock(strict=False) print(ll.strict) # False print(ll.applied) # False ``` -------------------------------- ### Landlock(strict=True) Source: https://context7.com/sebastienwae/py-landlock/llms.txt Initializes a Landlock sandbox builder. In strict mode (default), unsupported features raise CompatibilityError. In best-effort mode (strict=False), unsupported features are silently skipped. ```APIDOC ## Landlock(strict=True) ### Description Initializes a Landlock sandbox builder. In strict mode (default), unsupported features raise `CompatibilityError`. In best-effort mode (`strict=False`), unsupported features are silently skipped, making the sandbox portable across kernel versions. ### Parameters #### Path Parameters - **strict** (bool) - Optional - If True (default), raises `CompatibilityError` for unsupported features. If False, unsupported features are ignored. ### Request Example ```python from py_landlock import Landlock, CompatibilityError, LandlockNotAvailableError # Strict mode (default): raises CompatibilityError on unsupported features try: ll = Landlock(strict=True) print(f"ABI version: {ll.abi_version}") # e.g. 6 except LandlockNotAvailableError as e: print(f"Landlock not available: {e}") # Best-effort mode: silently ignores unsupported features ll = Landlock(strict=False) print(ll.strict) # False print(ll.applied) # False ``` ``` -------------------------------- ### Create Landlock Ruleset File Descriptor Source: https://context7.com/sebastienwae/py-landlock/llms.txt Directly wraps the `landlock_create_ruleset(2)` syscall. Returns a `RulesetFd` that must be closed after `restrict_self()`. Configures handled filesystem and network access rights. ```python import os from py_landlock import ( create_ruleset, add_rule, restrict_self, RulesetAttr, PathBeneathAttr, NetPortAttr, AccessFs, AccessNet, RulesetError, ) # Define which access rights this ruleset handles attr = RulesetAttr() attr.handled_access_fs = int(AccessFs.READ_FILE | AccessFs.READ_DIR | AccessFs.EXECUTE) attr.handled_access_net = int(AccessNet.CONNECT_TCP) attr.scoped = 0 ruleset_fd = create_ruleset(attr) print(f"Ruleset fd: {ruleset_fd}") ``` -------------------------------- ### Grant Write Access to Filesystem Paths Source: https://context7.com/sebastienwae/py-landlock/llms.txt Allows writing, creating, truncating, and removing files and directories. Includes flags like `WRITE_FILE`, `TRUNCATE`, `MAKE_REG`, `MAKE_DIR`, `MAKE_SYM`, `REMOVE_FILE`, `REMOVE_DIR`. Does not include cross-directory `REFER` or device creation. ```python from py_landlock import Landlock Landlock() \ .allow_read("/usr", "/lib", "/etc") \ .allow_execute("/usr/bin") \ .allow_write("/tmp/myapp/output") \ .apply() # Reading system paths works import os os.listdir("/etc") # OK # Writing to allowed path works with open("/tmp/myapp/output/result.txt", "w") as f: f.write("done") # Writing outside allowed paths raises PermissionError with open("/tmp/other.txt", "w") as f: # raises PermissionError f.write("blocked") ``` -------------------------------- ### Sandbox with Network Restrictions Source: https://github.com/sebastienwae/py-landlock/blob/main/README.md Illustrates how to configure Landlock to allow read and write access to a specific directory and restrict network access to a particular port. ```APIDOC ## Sandbox with Network Restrictions ### Description This example configures a Landlock policy that permits reading and writing to `/tmp/myapp`, allows network connections on port 443 (but not binding to it), and then applies the policy. ### Code ```python from py_landlock import Landlock Landlock() \ .allow_read("/usr", "/etc") \ .allow_read_write("/tmp/myapp") \ .allow_network(443, bind=False, connect=True) \ .apply() ``` ``` -------------------------------- ### allow_all_network() Source: https://context7.com/sebastienwae/py-landlock/llms.txt Disable network sandboxing entirely. Opts out of all TCP network restrictions, allowing the process to bind and connect on any port. Useful when filesystem sandboxing is desired without network restrictions. ```APIDOC ## allow_all_network() ### Description Disable network sandboxing entirely. Opts out of all TCP network restrictions, allowing the process to bind and connect on any port. Useful when filesystem sandboxing is desired without network restrictions. ### Method Landlock ### Request Example ```python from py_landlock import Landlock Landlock() .allow_read("/usr", "/lib", "/etc") .allow_read_write("/tmp/myapp") .allow_execute("/usr/bin") .allow_all_network() # unrestricted TCP .apply() ``` ### Response #### Success Response Disables all TCP network restrictions. #### Response Example (No specific response example provided for this method's success, but it modifies the Landlock context.) ``` -------------------------------- ### Sandbox with Network Restrictions Source: https://github.com/sebastienwae/py-landlock/blob/main/README.md Apply filesystem restrictions and allow network connections on port 443. Network restrictions require kernel ABI version 4 or later. ```python from py_landlock import Landlock Landlock() .allow_read("/usr", "/etc") .allow_read_write("/tmp/myapp") .allow_network(443, bind=False, connect=True) .apply() ``` -------------------------------- ### Add Filesystem and Network Rules to Ruleset Source: https://context7.com/sebastienwae/py-landlock/llms.txt Adds filesystem (`PathBeneathAttr`) or network (`NetPortAttr`) rules to an open ruleset file descriptor. Requires opening the parent directory with `os.open()` and closing the file descriptor afterwards. Handles `os.O_PATH` and `os.O_CLOEXEC` flags. ```python import os from py_landlock import ( create_ruleset, add_rule, restrict_self, RulesetAttr, PathBeneathAttr, NetPortAttr, AccessFs, AccessNet, ) attr = RulesetAttr() attr.handled_access_fs = int(AccessFs.READ_FILE | AccessFs.READ_DIR) attr.handled_access_net = int(AccessNet.CONNECT_TCP) attr.scoped = 0 ruleset_fd = create_ruleset(attr) try: # Add filesystem rule for /usr fd = os.open("/usr", os.O_PATH | os.O_CLOEXEC) try: path_attr = PathBeneathAttr() path_attr.allowed_access = int(AccessFs.READ_FILE | AccessFs.READ_DIR) path_attr.parent_fd = fd add_rule(ruleset_fd, path_attr) finally: os.close(fd) # Add network rule for port 443 (connect only) net_attr = NetPortAttr() net_attr.allowed_access = int(AccessNet.CONNECT_TCP) net_attr.port = 443 add_rule(ruleset_fd, net_attr) restrict_self(ruleset_fd, None) finally: os.close(ruleset_fd) ``` -------------------------------- ### Check Landlock Availability Source: https://github.com/sebastienwae/py-landlock/blob/main/README.md Verify if Landlock is available on the system and retrieve the ABI version. Catches LandlockNotAvailableError if unavailable. ```python 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}") ``` -------------------------------- ### allow_network(*ports, bind, connect) Source: https://context7.com/sebastienwae/py-landlock/llms.txt Restrict TCP access to specific ports. Allows TCP bind and/or connect operations only on specified port numbers. Requires ABI V4+ (Linux 6.7+). At least one of `bind` or `connect` must be `True`. All other TCP ports are blocked. ```APIDOC ## allow_network(*ports, bind, connect) ### Description Restrict TCP access to specific ports. Allows TCP bind and/or connect operations only on specified port numbers. Requires ABI V4+ (Linux 6.7+). At least one of `bind` or `connect` must be `True`. All other TCP ports are blocked. ### Method Landlock ### Parameters - **ports**: tuple of integers - Ports to allow network access on. - **bind**: boolean - Whether to allow binding to the specified ports. - **connect**: boolean - Whether to allow connecting to the specified ports. ### Request Example ```python from py_landlock import Landlock Landlock() .allow_read("/usr", "/lib", "/etc") .allow_execute("/usr/bin") .allow_network(443, bind=False, connect=True) # outbound HTTPS only .allow_network(8080, bind=True, connect=False) # bind to 8080 only .apply() ``` ### Response #### Success Response Applies the network restrictions. #### Response Example (No specific response example provided for this method's success, but it modifies the Landlock context.) ### Error Handling - Raises `CompatibilityError` if the kernel version is less than 6.7. ``` -------------------------------- ### Add Filesystem Rule with add_path_rule Source: https://context7.com/sebastienwae/py-landlock/llms.txt Adds a filesystem rule with a precise bitmask of `AccessFs` flags. Use this when convenience methods do not match exact permission requirements. ```python from py_landlock import Landlock, AccessFs Landlock() \ .add_path_rule( "/tmp/uploads", access=AccessFs.WRITE_FILE | AccessFs.MAKE_REG | AccessFs.REMOVE_FILE, ) \ .add_path_rule( "/data/readonly", access=AccessFs.READ_FILE | AccessFs.READ_DIR, ) \ .add_path_rule( "/data/archive", access=AccessFs.READ_FILE | AccessFs.REFER, # REFER requires ABI V2+ ) \ .apply() ``` -------------------------------- ### Disable Network Sandboxing with allow_all_network Source: https://context7.com/sebastienwae/py-landlock/llms.txt Opts out of all TCP network restrictions, allowing the process to bind and connect on any port. Useful when filesystem sandboxing is desired without network restrictions. ```python from py_landlock import Landlock Landlock() \ .allow_read("/usr", "/lib", "/etc") \ .allow_read_write("/tmp/myapp") \ .allow_execute("/usr/bin") \ .allow_all_network() \ .apply() # Any TCP connection is now allowed import socket s = socket.create_connection(("example.com", 80)) s.close() ``` -------------------------------- ### allow_execute(*paths) Source: https://context7.com/sebastienwae/py-landlock/llms.txt Grants execute permission for binaries located under the specified filesystem paths. This applies `AccessFs.EXECUTE` and is typically used with `allow_read` for shared libraries. Returns the Landlock instance for chaining. ```APIDOC ## allow_execute(*paths) ### Description Grants execute permission for paths. Allows executing binaries found under the given paths. Applies `AccessFs.EXECUTE` only. Typically combined with `allow_read` for shared libraries. Returns `self` for method chaining. ### Parameters #### Path Parameters - **paths** (list of str) - Required - A list of filesystem paths to grant execute access to. ### Request Example ```python from py_landlock import Landlock import subprocess Landlock() .allow_read("/usr", "/lib", "/lib64", "/etc") .allow_execute("/usr/bin") .allow_all_network() .apply() # Executing allowed binary works result = subprocess.run(["/usr/bin/python3", "--version"], capture_output=True) print(result.stdout.decode()) # Python 3.x.y # Executing from other paths raises PermissionError subprocess.run(["/opt/custom/bin/tool"]) # raises PermissionError ``` ``` -------------------------------- ### apply() Source: https://context7.com/sebastienwae/py-landlock/llms.txt Commits the accumulated ruleset to the calling thread, finalizing the sandbox. Once applied, no further rules can be added. ```APIDOC ## apply() ### Description Commits the accumulated ruleset to the calling thread. Internally calls `set_no_new_privs()`, creates the ruleset, adds all rules, and invokes `restrict_self()`. After `apply()`, no further rules can be added; calling `apply()` a second time raises `RulesetError`. ### Method `Landlock.apply()` ### Parameters None ### Request Example ```python from py_landlock import Landlock, RulesetError, LandlockNotAvailableError ll = Landlock(strict=False) \ .allow_read("/usr", "/lib", "/etc") \ .allow_execute("/usr/bin") \ .allow_read_write("/tmp/app") try: ll.apply() print(f"Sandbox applied: {ll.applied}") # True # Attempting to modify after apply raises RulesetError ll.allow_read("/home") # raises RulesetError except LandlockNotAvailableError as e: print(f"Landlock not supported on this system: {e}") except RulesetError as e: print(f"Ruleset error: {e}") ``` ### Response #### Success Response No explicit return value, but the sandbox is applied. `ll.applied` will be `True`. #### Response Example ``` Sandbox applied: True ``` #### Error Response - `RulesetError`: If `apply()` is called more than once. - `LandlockNotAvailableError`: If Landlock is not supported on the system. ``` -------------------------------- ### create_ruleset(attr) Source: https://context7.com/sebastienwae/py-landlock/llms.txt Creates a Landlock ruleset file descriptor, which is a direct wrapper for the `landlock_create_ruleset(2)` syscall. ```APIDOC ## create_ruleset(attr) ### Description Direct wrapper for the `landlock_create_ruleset(2)` syscall. Returns a `RulesetFd` (typed `int`) that must be closed after `restrict_self()`. ### Method `create_ruleset(attr: RulesetAttr)` ### Parameters #### Request Body - **attr** (RulesetAttr) - Required - Attributes defining the ruleset's capabilities, including handled filesystem and network access rights, and whether it is scoped. - `handled_access_fs` (int) - Bitmask of filesystem access rights handled by this ruleset. - `handled_access_net` (int) - Bitmask of network access rights handled by this ruleset. - `scoped` (int) - Indicates if the ruleset is scoped. ### Request Example ```python import os from py_landlock import ( create_ruleset, add_rule, restrict_self, RulesetAttr, PathBeneathAttr, NetPortAttr, AccessFs, AccessNet, RulesetError, ) # Define which access rights this ruleset handles attr = RulesetAttr() attr.handled_access_fs = int(AccessFs.READ_FILE | AccessFs.READ_DIR | AccessFs.EXECUTE) attr.handled_access_net = int(AccessNet.CONNECT_TCP) attr.scoped = 0 ruleset_fd = create_ruleset(attr) print(f"Ruleset fd: {rulesetet_fd}") ``` ### Response #### Success Response (200) - **ruleset_fd** (int) - A file descriptor representing the created ruleset. #### Response Example ``` Ruleset fd: 3 ``` ``` -------------------------------- ### allow_write(*paths) Source: https://context7.com/sebastienwae/py-landlock/llms.txt Grants write access to specified filesystem paths. This allows creating, truncating, and removing files and directories. Returns the Landlock instance for chaining. ```APIDOC ## allow_write(*paths) ### Description Grants write access to filesystem paths. Allows writing, creating, truncating, and removing files and directories under the given paths. Includes `WRITE_FILE`, `TRUNCATE`, `MAKE_REG`, `MAKE_DIR`, `MAKE_SYM`, `REMOVE_FILE`, `REMOVE_DIR`. Does not include cross-directory `REFER` or device creation. Returns `self` for method chaining. ### Parameters #### Path Parameters - **paths** (list of str) - Required - A list of filesystem paths to grant write access to. ### Request Example ```python from py_landlock import Landlock Landlock() .allow_read("/usr", "/lib", "/etc") .allow_execute("/usr/bin") .allow_write("/tmp/myapp/output") .apply() # Reading system paths works import os os.listdir("/etc") # OK # Writing to allowed path works with open("/tmp/myapp/output/result.txt", "w") as f: f.write("done") # Writing outside allowed paths raises PermissionError with open("/tmp/other.txt", "w") as f: # raises PermissionError f.write("blocked") ``` ``` -------------------------------- ### Filesystem Access Control Methods Source: https://github.com/sebastienwae/py-landlock/blob/main/README.md Details the high-level API methods for controlling filesystem access, including read, write, execute, read-write, and custom access rules. ```APIDOC ## Filesystem Access Control ### Description The `Landlock` class provides the following methods for managing filesystem access permissions: - `allow_read(*paths)`: Grants permission to read files and list directories. - `allow_write(*paths)`: Grants permission to write, create, and remove files. - `allow_execute(*paths)`: Grants permission to execute files. - `allow_read_write(*paths)`: Grants both read and write permissions. - `add_path_rule(*paths, access)`: Allows adding a rule with specific `AccessFs` flags for given paths. ``` -------------------------------- ### allow_read(*paths) Source: https://context7.com/sebastienwae/py-landlock/llms.txt Grants read access to specified filesystem paths. This allows opening files for reading and listing directory contents. Returns the Landlock instance for chaining. ```APIDOC ## allow_read(*paths) ### Description Grants read access to filesystem paths. Allows opening files for reading and listing directory contents under the given paths. Applies `AccessFs.READ_FILE | AccessFs.READ_DIR`. Returns `self` for method chaining. ### Parameters #### Path Parameters - **paths** (list of str) - Required - A list of filesystem paths to grant read access to. ### Request Example ```python from py_landlock import Landlock, PathError try: Landlock() .allow_read("/usr", "/lib", "/etc") .allow_execute("/usr/bin", "/usr/lib") .apply() # After apply: reading /etc/hostname succeeds with open("/etc/hostname") as f: print(f.read()) # Writing anywhere raises PermissionError with open("/tmp/test.txt", "w") as f: # raises PermissionError f.write("blocked") except PathError as e: print(f"Path not found: {e.path}") ``` ``` -------------------------------- ### Grant Execute Permission for Paths Source: https://context7.com/sebastienwae/py-landlock/llms.txt Allows executing binaries found under the specified paths. Applies `AccessFs.EXECUTE` only. Often combined with `allow_read` for necessary shared libraries. ```python from py_landlock import Landlock import subprocess Landlock() \ .allow_read("/usr", "/lib", "/lib64", "/etc") \ .allow_execute("/usr/bin") \ .allow_all_network() \ .apply() # Executing allowed binary works result = subprocess.run(["/usr/bin/python3", "--version"], capture_output=True) print(result.stdout.decode()) # Python 3.x.y # Executing from other paths raises PermissionError subprocess.run(["/opt/custom/bin/tool"]) # raises PermissionError ``` -------------------------------- ### Filesystem Access Flags (`AccessFs`) Source: https://context7.com/sebastienwae/py-landlock/llms.txt Defines filesystem operations that Landlock can restrict. Flags can be combined using the `|` operator. Different flags were introduced in various ABI versions. ```python from py_landlock import AccessFs, Landlock # V1 flags (kernel 5.13+) print(AccessFs.EXECUTE) # Execute files print(AccessFs.WRITE_FILE) # Open file for writing print(AccessFs.READ_FILE) # Open file for reading print(AccessFs.READ_DIR) # Open/list directory print(AccessFs.REMOVE_DIR) # Remove empty directory print(AccessFs.REMOVE_FILE) # Unlink file print(AccessFs.MAKE_CHAR) # Create character device print(AccessFs.MAKE_DIR) # Create directory print(AccessFs.MAKE_REG) # Create regular file print(AccessFs.MAKE_SOCK) # Create UNIX domain socket print(AccessFs.MAKE_FIFO) # Create named pipe print(AccessFs.MAKE_BLOCK) # Create block device print(AccessFs.MAKE_SYM) # Create symbolic link # V2+ flag (kernel 5.19+) print(AccessFs.REFER) # Link/rename across directories # V3+ flag (kernel 6.2+) print(AccessFs.TRUNCATE) # Truncate file size # V5+ flag (kernel 6.10+) print(AccessFs.IOCTL_DEV) # ioctl on device files # Combine flags for custom rules custom = AccessFs.READ_FILE | AccessFs.WRITE_FILE | AccessFs.MAKE_REG Landlock().add_path_rule("/tmp/workspace", access=custom).apply() ``` -------------------------------- ### Grant Read Access to Filesystem Paths Source: https://context7.com/sebastienwae/py-landlock/llms.txt Allows reading files and listing directory contents. Applies `AccessFs.READ_FILE | AccessFs.READ_DIR`. Returns `self` for chaining. Catches `PathError` if a specified path does not exist. ```python from py_landlock import Landlock, PathError try: Landlock() \ .allow_read("/usr", "/lib", "/etc") \ .allow_execute("/usr/bin", "/usr/lib") \ .apply() # After apply: reading /etc/hostname succeeds with open("/etc/hostname") as f: print(f.read()) # Writing anywhere raises PermissionError with open("/tmp/test.txt", "w") as f: # raises PermissionError f.write("blocked") except PathError as e: print(f"Path not found: {e.path}") ``` -------------------------------- ### Grant Full Read and Write Access Source: https://context7.com/sebastienwae/py-landlock/llms.txt A convenience shorthand that combines all `allow_read` and `allow_write` flags for a given path. Useful for application working directories requiring both read and write capabilities. ```python from py_landlock import Landlock import tempfile, pathlib work_dir = pathlib.Path("/tmp/myapp") work_dir.mkdir(exist_ok=True) Landlock() \ .allow_read("/usr", "/lib", "/etc") \ .allow_execute("/usr/bin") \ .allow_read_write("/tmp/myapp") \ .apply() # Full read/write in the working directory (work_dir / "data.txt").write_text("hello") print((work_dir / "data.txt").read_text()) # hello (work_dir / "data.txt").unlink() # delete OK ``` -------------------------------- ### add_path_rule(*paths, access) Source: https://context7.com/sebastienwae/py-landlock/llms.txt Add a rule with explicit `AccessFs` flags. Low-level high-API method for adding a filesystem rule with a precise bitmask of `AccessFs` flags. Use this when the convenience methods do not match your exact permission requirements. ```APIDOC ## add_path_rule(*paths, access) ### Description Add a rule with explicit `AccessFs` flags. Low-level high-API method for adding a filesystem rule with a precise bitmask of `AccessFs` flags. Use this when the convenience methods do not match your exact permission requirements. ### Method Landlock ### Parameters - **paths**: tuple of strings - Paths to apply the rule to. - **access**: AccessFs enum - A bitmask of `AccessFs` flags specifying the allowed filesystem operations. ### Request Example ```python from py_landlock import Landlock, AccessFs Landlock() .add_path_rule( "/tmp/uploads", access=AccessFs.WRITE_FILE | AccessFs.MAKE_REG | AccessFs.REMOVE_FILE, ) .add_path_rule( "/data/readonly", access=AccessFs.READ_FILE | AccessFs.READ_DIR, ) .add_path_rule( "/data/archive", access=AccessFs.READ_FILE | AccessFs.REFER, # REFER requires ABI V2+ ) .apply() ``` ### Response #### Success Response Adds a filesystem rule with the specified paths and access flags. #### Response Example (No specific response example provided for this method's success, but it modifies the Landlock context.) ``` -------------------------------- ### Apply Sandbox Rules with Error Handling Source: https://context7.com/sebastienwae/py-landlock/llms.txt Applies a set of Landlock sandbox rules for an application directory. Includes comprehensive error handling for various Landlock-specific exceptions, such as LandlockNotAvailableError, LandlockDisabledError, CompatibilityError, PathError, NetworkDisabledError, and RulesetError. This function is useful for hardening applications by restricting filesystem access and network operations. ```python from py_landlock import ( Landlock, LandlockError, LandlockNotAvailableError, # Wrong platform, arch, or kernel too old LandlockDisabledError, # Kernel has Landlock but it's disabled at boot RulesetError, # Syscall failure, double-apply, modify after apply PathError, # Path does not exist when adding a rule CompatibilityError, # Feature needs higher ABI version (strict mode) NetworkDisabledError, # Kernel built without CONFIG_INET ) def apply_sandbox(app_dir: str) -> bool: try: Landlock() \ .allow_read("/usr", "/lib", "/etc") \ .allow_execute("/usr/bin") \ .allow_read_write(app_dir) \ .allow_network(443, bind=False, connect=True) \ .apply() return True except LandlockNotAvailableError: print("Landlock not available (kernel < 5.13 or non-Linux)") return False except LandlockDisabledError: print("Landlock disabled at boot (set landlock.mode=1 kernel param)") return False except CompatibilityError as e: print(f"Feature {e.feature!r} needs ABI V{e.required_abi}, got V{e.current_abi}") return False except PathError as e: print(f"Path not found: {e.path}") return False except NetworkDisabledError: print("TCP/IP not available in kernel (CONFIG_INET=n)") return False except RulesetError as e: print(f"Ruleset error: {e}") return False except LandlockError as e: print(f"Unexpected Landlock error: {e}") return False apply_sandbox("/tmp/myapp") ``` -------------------------------- ### get_abi_errata() Source: https://context7.com/sebastienwae/py-landlock/llms.txt Queries a bitmask of known bugs that have been fixed in the current kernel version for the current ABI. ```APIDOC ## get_abi_errata() ### Description Returns a bitmask of known bugs that have been fixed in the current kernel version. Useful for detecting whether specific kernel bug fixes are present. ### Method `get_abi_errata()` ### Parameters None ### Request Example ```python from py_landlock import get_abi_errata errata = get_abi_errata() print(f"Errata bitmask: {errata:#010b}") # Each bit corresponds to a documented kernel errata being fixed ``` ### Response #### Success Response (200) - **errata** (int) - A bitmask representing fixed kernel errata. #### Response Example ``` Errata bitmask: 0b00000001 ``` ``` -------------------------------- ### Error Handling Exceptions Source: https://github.com/sebastienwae/py-landlock/blob/main/README.md Lists and describes the various exceptions that can be raised by the py-landlock library, aiding in robust error management. ```APIDOC ## Error Handling ### Description The `py-landlock` library defines the following exceptions to handle errors during Landlock operations: - `LandlockError`: The base exception for all Landlock-related errors. - `LandlockNotAvailableError`: Raised when Landlock is not available on the system (e.g., wrong platform, architecture, or kernel version). - `LandlockDisabledError`: Raised when Landlock is supported by the kernel but disabled at boot. - `RulesetError`: Indicates a failure during the creation, configuration, or application of a ruleset. - `PathError`: Raised when a specified path does not exist. - `CompatibilityError`: Indicates that a requested feature requires a higher ABI version than the current kernel supports. - `NetworkDisabledError`: Raised if TCP/IP networking is not available in the kernel. ``` -------------------------------- ### Network Access Control Methods Source: https://github.com/sebastienwae/py-landlock/blob/main/README.md Explains the high-level API methods for controlling network access, including specific port restrictions and disabling all network restrictions. ```APIDOC ## Network Access Control ### Description Network restrictions require kernel ABI version 4 or later. The following methods are available: - `allow_network(*ports, bind, connect)`: Allows TCP bind and/or connect operations on the specified ports. `bind` and `connect` are boolean flags. - `allow_all_network()`: Disables all network restrictions, allowing all network operations. ``` -------------------------------- ### Restrict TCP Access with allow_network Source: https://context7.com/sebastienwae/py-landlock/llms.txt Allows TCP bind and/or connect operations only on specified port numbers. Requires ABI V4+ (Linux 6.7+). At least one of `bind` or `connect` must be `True`. All other TCP ports are blocked. ```python from py_landlock import Landlock, CompatibilityError try: Landlock() \ .allow_read("/usr", "/lib", "/etc") \ .allow_execute("/usr/bin") \ .allow_network(443, bind=False, connect=True) \ .allow_network(8080, bind=True, connect=False) \ .apply() import urllib.request # HTTPS connect to port 443 works urllib.request.urlopen("https://example.com") # Connect to port 80 raises PermissionError urllib.request.urlopen("http://example.com") # raises PermissionError except CompatibilityError as e: # Kernel < 6.7: use best-effort mode instead print(f"Network restriction not supported: {e}") ``` -------------------------------- ### Network Access Flags (`AccessNet`) Source: https://context7.com/sebastienwae/py-landlock/llms.txt Defines TCP port operations for network access restrictions. Requires ABI V4+ (Linux 6.7+). Only TCP bind and connect are affected. ```python from py_landlock import AccessNet, Landlock print(AccessNet.BIND_TCP) # Bind to a TCP port print(AccessNet.CONNECT_TCP) # Connect to a TCP port # Allow binding on 8080 and connecting to 443 and 5432 Landlock(strict=False) \ .allow_read("/usr", "/lib", "/etc") \ .allow_execute("/usr/bin") \ .add_net_rule(8080, access=AccessNet.BIND_TCP) \ .add_net_rule(443, 5432, access=AccessNet.CONNECT_TCP) \ .apply() ``` -------------------------------- ### allow_read_write(*paths) Source: https://context7.com/sebastienwae/py-landlock/llms.txt A convenience method that grants both read and write access to the specified filesystem paths. It's useful for directories that require full read/write operations. Returns the Landlock instance for chaining. ```APIDOC ## allow_read_write(*paths) ### Description Grants full read and write access to filesystem paths. This is a convenience shorthand combining all `allow_read` and `allow_write` flags for a path. Useful for application working directories that need both read and write access. Returns `self` for method chaining. ### Parameters #### Path Parameters - **paths** (list of str) - Required - A list of filesystem paths to grant both read and write access to. ### Request Example ```python from py_landlock import Landlock import tempfile, pathlib work_dir = pathlib.Path("/tmp/myapp") work_dir.mkdir(exist_ok=True) Landlock() .allow_read("/usr", "/lib", "/etc") .allow_execute("/usr/bin") .allow_read_write("/tmp/myapp") .apply() # Full read/write in the working directory (work_dir / "data.txt").write_text("hello") print((work_dir / "data.txt").read_text()) # hello (work_dir / "data.txt").unlink() # delete OK ``` ``` -------------------------------- ### allow_scope(scope) Source: https://context7.com/sebastienwae/py-landlock/llms.txt Selectively exempt IPC scope restrictions. By default (on ABI V6+), Landlock blocks abstract UNIX socket connections and signal delivery to processes outside the sandboxed domain. `allow_scope` exempts specific restrictions. Requires ABI V6+ (Linux 6.12+). ```APIDOC ## allow_scope(scope) ### Description Selectively exempt IPC scope restrictions. By default (on ABI V6+), Landlock blocks abstract UNIX socket connections and signal delivery to processes outside the sandboxed domain. `allow_scope` exempts specific restrictions. Requires ABI V6+ (Linux 6.12+). ### Method Landlock ### Parameters - **scope**: Scope enum - The IPC scope to exempt (e.g., `Scope.ABSTRACT_UNIX_SOCKET`, `Scope.SIGNAL`). Can be a bitwise OR of multiple scopes. ### Request Example ```python from py_landlock import Landlock, Scope, CompatibilityError try: Landlock() .allow_read("/usr", "/lib") .allow_execute("/usr/bin") .allow_scope(Scope.ABSTRACT_UNIX_SOCKET) # allow abstract UNIX sockets .allow_scope(Scope.SIGNAL) # allow signals to any process .apply() except CompatibilityError as e: print(f"Scope restriction unsupported: {e}") ``` ### Response #### Success Response Exempts the specified IPC scope restrictions. #### Response Example (No specific response example provided for this method's success, but it modifies the Landlock context.) ### Error Handling - Raises `CompatibilityError` if the kernel version is less than 6.12. ``` -------------------------------- ### get_abi_version() Source: https://context7.com/sebastienwae/py-landlock/llms.txt Queries the kernel for the highest Landlock ABI version supported by the running kernel. ```APIDOC ## get_abi_version() ### Description Returns the highest Landlock ABI version supported by the running kernel. Raises an error if Landlock is unavailable or disabled. ### Method `get_abi_version()` ### Parameters None ### Request Example ```python from py_landlock import get_abi_version, LandlockNotAvailableError, LandlockDisabledError try: version = get_abi_version() print(f"Landlock ABI version: {version}") # V1 = kernel 5.13, V2 = 5.19, V3 = 6.2, V4 = 6.7, V5 = 6.10, V6 = 6.12, V7 = 6.14 if version >= 4: print("TCP network restrictions available") if version >= 6: print("IPC scope restrictions available") except LandlockNotAvailableError as e: print(f"Landlock not available: {e}") # Requires Linux 5.13+ with CONFIG_SECURITY_LANDLOCK=y except LandlockDisabledError as e: print(f"Landlock disabled at boot: {e}") # Re-enable with: kernel parameter landlock.mode=1 ``` ### Response #### Success Response (200) - **version** (int) - The highest Landlock ABI version supported by the kernel. #### Response Example ``` Landlock ABI version: 7 TCP network restrictions available IPC scope restrictions available ``` #### Error Response - `LandlockNotAvailableError`: If Landlock is not available or disabled. - `LandlockDisabledError`: If Landlock is disabled at boot. ``` -------------------------------- ### Apply Ruleset to Current Thread with `restrict_self` Source: https://context7.com/sebastienwae/py-landlock/llms.txt Applies a created ruleset to the current thread using the `restrict_self` function. The `flags` argument can control audit logging on ABI V7+ kernels, or be set to `None` for older kernels. ```python from py_landlock import ( create_ruleset, add_rule, restrict_self, RulesetAttr, PathBeneathAttr, AccessFs, RestrictSelfFlag, ) import os attr = RulesetAttr() attr.handled_access_fs = int(AccessFs.READ_FILE | AccessFs.READ_DIR) attr.handled_access_net = 0 attr.scoped = 0 ruleset_fd = create_ruleset(attr) try: fd = os.open("/etc", os.O_PATH | os.O_CLOEXEC) try: rule = PathBeneathAttr() rule.allowed_access = int(AccessFs.READ_FILE | AccessFs.READ_DIR) rule.parent_fd = fd add_rule(ruleset_fd, rule) finally: os.close(fd) # Apply with audit logging flags (ABI V7+ only; pass None for older kernels) restrict_self( ruleset_fd, RestrictSelfFlag.LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON, ) finally: os.close(ruleset_fd) ``` -------------------------------- ### Apply Landlock Sandbox Ruleset Source: https://context7.com/sebastienwae/py-landlock/llms.txt Commits accumulated rules to the calling thread. Further modifications after `apply()` will raise a `RulesetError`. Handles `LandlockNotAvailableError` and `RulesetError`. ```python from py_landlock import Landlock, RulesetError, LandlockNotAvailableError ll = Landlock(strict=False) \ .allow_read("/usr", "/lib", "/etc") \ .allow_execute("/usr/bin") \ .allow_read_write("/tmp/app") try: ll.apply() print(f"Sandbox applied: {ll.applied}") # True # Attempting to modify after apply raises RulesetError ll.allow_read("/home") # raises RulesetError except LandlockNotAvailableError as e: print(f"Landlock not supported on this system: {e}") except RulesetError as e: print(f"Ruleset error: {e}") ``` -------------------------------- ### AccessNet Enum Source: https://context7.com/sebastienwae/py-landlock/llms.txt Defines network access rights flags for TCP port operations. Requires ABI V4+ (Linux 6.7+). Only TCP bind and connect can be restricted. ```APIDOC ## AccessNet ### Description Network access rights flags. `AccessNet` is an `IntFlag` enum for TCP port operations. Requires ABI V4+ (Linux 6.7+). Only TCP bind and connect can be restricted; UDP and other protocols are unaffected. ### Flags - **BIND_TCP** - Bind to a TCP port. - **CONNECT_TCP** - Connect to a TCP port. ### Request Example ```python from py_landlock import AccessNet, Landlock print(AccessNet.BIND_TCP) print(AccessNet.CONNECT_TCP) # Allow binding on 8080 and connecting to 443 and 5432 Landlock(strict=False) \ .allow_read("/usr", "/lib", "/etc") \ .allow_execute("/usr/bin") \ .add_net_rule(8080, access=AccessNet.BIND_TCP) \ .add_net_rule(443, 5432, access=AccessNet.CONNECT_TCP) \ .apply() ``` ``` -------------------------------- ### Add Network Rule with add_net_rule Source: https://context7.com/sebastienwae/py-landlock/llms.txt Adds a TCP port rule with explicit `AccessNet` flags. Port must be in range 0–65535. ```python from py_landlock import Landlock, AccessNet Landlock() \ .allow_read("/usr", "/lib", "/etc") \ .allow_execute("/usr/bin") \ .add_net_rule(80, 443, access=AccessNet.CONNECT_TCP) \ .add_net_rule(8080, access=AccessNet.BIND_TCP) \ .add_net_rule(5432, access=AccessNet.BIND_TCP | AccessNet.CONNECT_TCP) \ .apply() ``` -------------------------------- ### Disable All Scope Restrictions with allow_all_scope Source: https://context7.com/sebastienwae/py-landlock/llms.txt Disables both abstract UNIX socket and signal scope restrictions, restoring unrestricted IPC behavior. Equivalent to calling `allow_scope(Scope.ABSTRACT_UNIX_SOCKET | Scope.SIGNAL)`. ```python from py_landlock import Landlock Landlock() \ .allow_read("/usr", "/lib", "/etc") \ .allow_execute("/usr/bin") \ .allow_all_network() \ .allow_all_scope() \ .apply() ``` -------------------------------- ### Strict vs Best-Effort Mode Source: https://github.com/sebastienwae/py-landlock/blob/main/README.md Explains the two modes of operation for the py-landlock library: strict mode which raises errors for unsupported features, and best-effort mode which silently ignores them. ```APIDOC ## Strict vs Best-Effort Mode ### Description By default, `py-landlock` operates in strict mode, raising a `CompatibilityError` if a requested feature is not supported by the kernel. To enable best-effort mode, instantiate the `Landlock` class with `strict=False`. In best-effort mode, unsupported features are silently ignored. ### Usage ```python from py_landlock import Landlock # Strict mode (default) landlock_strict = Landlock() # Best-effort mode landlock_best_effort = Landlock(strict=False) ``` ```