$RodHat_
Syscall reference · Sandboxing

landlock_create_ruleset(2)

Create a Landlock ruleset fd, step one of unprivileged filesystem/network sandboxing.

Since
Linux 5.13check your kernel →
glibc
none (use syscall(2))
System
Linux
Man page
landlock_create_ruleset(2)

Synopsis

#include <linux/landlock.h>
#include <sys/syscall.h>
#include <unistd.h>

int syscall(SYS_landlock_create_ruleset,
            const struct landlock_ruleset_attr *attr,
            size_t size, uint32_t flags);

Rod's take

Before Landlock, path-based sandboxing on Linux meant root, a MAC policy some other team wrote, or chroot pretending to be security. Now an unprivileged process builds a ruleset, adds paths, and locks itself in for good. The trap: a right you leave out of handled_access_fs isn't restricted at all, so a hardcoded ABI-1 mask on a newer kernel leaves truncate wide open and never says a word. Ask for the ABI version, handle everything the kernel knows, grant back what you need. unveil does it in four lines. Landlock still got the architecture right.

Flags and arguments that matter

NameWhat it does
LANDLOCK_CREATE_RULESET_VERSIONWith attr NULL and size 0, return the highest supported Landlock ABI version (starting at 1).
LANDLOCK_CREATE_RULESET_ERRATAWith attr NULL and size 0, return a bitmask of Landlock errata fixed in the running kernel.
handled_access_fsFilesystem rights this ruleset handles. Rights not listed here are not restricted at all.
handled_access_netNetwork rights (TCP bind/connect) this ruleset handles.
scopedScope flags restricting IPC (abstract UNIX sockets, signals) outside the Landlock domain.
LANDLOCK_ACCESS_FS_REFERCross-directory rename/link right; always denied by default, even if not set in handled_access_fs.

Errors you will actually hit

errnoMeaning
EOPNOTSUPPLandlock is supported by the kernel but disabled at boot.
EINVALUnknown flags, access right, or scope, or size too small.
ENOMSGattr specifies no access rights to restrict.
E2BIGsize is too big.
EFAULTattr is not a valid address.

Example

int abi = syscall(SYS_landlock_create_ruleset, NULL, 0,
                  LANDLOCK_CREATE_RULESET_VERSION);
if (abi < 0)
    err(1, "landlock unavailable");   /* ENOSYS or EOPNOTSUPP */

struct landlock_ruleset_attr attr = {
    .handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE |
                         LANDLOCK_ACCESS_FS_READ_DIR  |
                         LANDLOCK_ACCESS_FS_WRITE_FILE,
};
int rfd = syscall(SYS_landlock_create_ruleset, &attr, sizeof(attr), 0);
if (rfd < 0)
    err(1, "landlock_create_ruleset");
/* landlock_add_rule(2), PR_SET_NO_NEW_PRIVS, landlock_restrict_self(2) */

Trimmed from the full walkthrough in landlock: sandbox your process without root.

BSD equivalent

OpenBSD: unveil(2) (OpenBSD 6.4). FreeBSD: Capsicum capability mode via cap_enter(2).

The long version, from the console

Sources

  1. landlock_create_ruleset(2), man7.org
  2. unveil(2), OpenBSD
  3. cap_enter(2), FreeBSD

Version numbers are read off the cited man pages, not memory. Spot one that's wrong? Tell Rod.