Landlock LSM: kernel documentation¶
- Author:
Mickaël Salaün
- Date:
October 2026
Landlock’s goal is to create scoped access-control (i.e. sandboxing). To harden a whole system, this feature should be available to any process, including unprivileged ones. Because such a process may be compromised or backdoored (i.e. untrusted), Landlock’s features must be safe to use from the kernel and other processes point of view. Landlock’s interface must therefore expose a minimal attack surface.
Landlock is designed to be usable by unprivileged processes while following the system security policy enforced by other access control mechanisms (e.g. DAC, LSM). A Landlock rule shall not interfere with other access-controls enforced on the system, only add more restrictions.
Any user can enforce Landlock rulesets on their processes. They are merged and evaluated against inherited rulesets in a way that ensures that only more constraints can be added.
User space documentation can be found here: Landlock: unprivileged access control.
Guiding principles for safe access controls¶
A Landlock rule shall be focused on access control on kernel objects instead of syscall filtering (i.e. syscall arguments), which is the purpose of seccomp-bpf.
To avoid multiple kinds of side-channel attacks (e.g. leak of security policies, CPU-based attacks), Landlock rules shall not be able to programmatically communicate with user space.
Kernel access check shall not slow down access request from unsandboxed processes.
Computation related to Landlock operations (e.g. enforcing a ruleset) shall only impact the processes requesting them.
Resources (e.g. file descriptors) directly obtained from the kernel by a sandboxed process shall retain their scoped accesses (at the time of resource acquisition) whatever process uses them. Cf. File descriptor access rights.
Access denials shall be logged according to system and Landlock domain configurations. Log entries must contain information about the cause of the denial and the owner of the related security policy. Such log generation should have a negligible performance and memory impact on allowed requests.
Design choices¶
Inode access rights¶
All access rights are tied to an inode and what can be accessed through it.
Reading the content of a directory does not imply to be allowed to read the
content of a listed inode. Indeed, a file name is local to its parent
directory, and an inode can be referenced by multiple file names thanks to
(hard) links. Being able to unlink a file only has a direct impact on the
directory, not the unlinked inode. This is the reason why
LANDLOCK_ACCESS_FS_REMOVE_FILE or LANDLOCK_ACCESS_FS_REFER are not
allowed to be tied to files but only to directories.
File descriptor access rights¶
Access rights are checked and tied to file descriptors at open time. The underlying principle is that equivalent sequences of operations should lead to the same results, when they are executed under the same Landlock domain.
Taking the LANDLOCK_ACCESS_FS_TRUNCATE right as an example, it may be
allowed to open a file for writing without being allowed to
ftruncate the resulting file descriptor if the related file
hierarchy doesn’t grant that access right. The following sequences of
operations have the same semantic and should then have the same result:
truncate(path);int fd = open(path, O_WRONLY); ftruncate(fd); close(fd);
Similarly to file access modes (e.g. O_RDWR), Landlock access rights
attached to file descriptors are retained even if they are passed between
processes (e.g. through a Unix domain socket). Such access rights will then be
enforced even if the receiving process is not sandboxed by Landlock. Indeed,
this is required to keep access controls consistent over the whole system, and
this avoids unattended bypasses through file descriptor passing (i.e. confused
deputy attack).
Interaction between scoped flags and other access rights¶
The scoped flags in &struct landlock_ruleset_attr restrict the
use of outgoing IPC from the created Landlock domain, while they
permit reaching out to IPC endpoints within the created Landlock
domain.
In the future, scoped flags may interact with other access rights, e.g. so that abstract UNIX sockets can be allow-listed by name, or so that signals can be allow-listed by signal number or target process.
When introducing LANDLOCK_ACCESS_FS_RESOLVE_UNIX, we defined it to
implicitly have the same scoping semantics as a
LANDLOCK_SCOPE_PATHNAME_UNIX_SOCKET flag would have: connecting to
UNIX sockets within the same domain (where
LANDLOCK_ACCESS_FS_RESOLVE_UNIX is used) is unconditionally
allowed.
The reasoning is:
Like other IPC mechanisms, connecting to named UNIX sockets in the same domain should be expected and harmless. (If needed, users can further refine their Landlock policies with nested domains or by restricting
LANDLOCK_ACCESS_FS_MAKE_SOCK.)We reserve the option to still introduce
LANDLOCK_SCOPE_PATHNAME_UNIX_SOCKETin the future. (This would be useful if we wanted to have a Landlock rule to permit IPC access to other Landlock domains.)But we can postpone the point in time when users have to deal with two interacting flags visible in the userspace API. (In particular, it is possible that it won’t be needed in practice, in which case we can avoid the second flag altogether.)
If we do introduce
LANDLOCK_SCOPE_PATHNAME_UNIX_SOCKETin the future, setting this scoped flag in a ruleset does not reduce the restrictions, because access within the same scope is already allowed based onLANDLOCK_ACCESS_FS_RESOLVE_UNIX.
Composability with user namespaces¶
Landlock domain-based scoping and the kernel’s user-namespace-based capability
scoping enforce isolation over independent hierarchies. Landlock checks domain
ancestry; the kernel’s ns_capable() checks user namespace ancestry. These
hierarchies are orthogonal: Landlock enforcement is deterministic with respect
to its own configuration, regardless of namespace or capability state, and vice
versa. This orthogonality is a design invariant that must hold for all Landlock
access controls.
Design philosophy¶
Landlock’s goal is to restrict a sandboxed process’s access to three kinds of resources: data (files, sockets, pipes), other processes (signals, ptrace), and kernel-internal resources whose use widens the kernel attack surface (capabilities, namespace types). Each access right or permission gates one or more operations that grant such access; restricting the operations is how Landlock restricts the underlying access.
When designing a new access control, identify the protected resource kind first (data, processes, or kernel-internal resources). The operations to restrict follow from the protected resource, by identifying which kernel code paths grant access to the resource and at which place in the code the access to the resource can be gated. Do not design a permission around “restrict the unshare(2) syscall” or similar mechanism-centric framings; design it around “restrict the process from acquiring access to namespace types” (the protected resource), letting the operation set follow.
Ruleset restriction models¶
Landlock provides three restriction models that differ in how rules identify the resource being restricted.
In general, the struct landlock_ruleset_attr specifies the operations to be
denied by default under the enforced policy. The rules added to the ruleset
define the exceptions to these restrictions, allow-listing specific conditions
under which these operations are still permitted.
Per-object access rights (handled_access_*)¶
Per-object access rights control operations on a specific resource instance,
identified in the rule key by a value drawn from an open-ended space: a file
hierarchy referenced by parent_fd, or a network port identified by its
16-bit number.
Each handled_access_* field declares a set of access rights, operations
which are to be denied by default once the ruleset is enforced.
The rule body declares which of the multiple distinct operations on that object instance are allowed (open, read, write, truncate; bind, connect).
Operations are grouped by object type in the respective handled_access_*
field: a new operation on an existing type extends that field, and a new object
type gets its own handled_access_* field.
Per-category permissions (handled_permissions)¶
Per-category permissions control the process’s exercise of category members,
where the category is a small kernel-defined enumeration (a Linux capability
number CAP_*, a namespace type CLONE_NEW*). Unlike per-object access
rights, which restrict specific operations on a single resource instance,
per-category permissions gate the prerequisite operation itself (exercising a
capability, acquiring access to a namespace), so gating it transitively covers a
broad set of downstream operations (e.g. denying CAP_SYS_ADMIN blocks all
admin operations such as mounts).
These category members are the LSM-level access-control objects (the entities
the process is authorized against) even though they are enum values rather than
externally-instantiated kernel data structures. Per-category permissions apply
where the controlled operation collapses to “may the process use this category
member at all” (use a capability; acquire access to a namespace), so the rule
body lists which category members the process may exercise.
Each LANDLOCK_PERMISSION_* flag maps to its own rule type and covers every
kernel path that exercises a member. When a ruleset handles a permission, all
uses of category members are denied unless explicitly allowed by a rule.
Logging of a denied member can be suppressed at the same granularity as the
restriction itself: per rule and per member. A rule names the members whose
denial should not be audited; suppression only affects the audit record, never
the denial or its trace event, which reports logged=0. Suppression only
applies when the layer owning the rule is the one that denied the member.
See Landlock: unprivileged access control for the concrete syscall paths covered by each permission.
The category enum is owned by the corresponding kernel subsystem (capabilities,
namespaces, etc.). Userspace policy authors query category member availability
via the relevant non-Landlock interfaces:
For capabilities:
<linux/capability.h>,/proc/sys/kernel/cap_last_cap,prctl(PR_CAPBSET_READ).For namespaces:
<linux/sched.h>,/proc/$$/ns/*, unshare(2) runtime probe.
The Landlock ABI version does not encode this availability; ABI versioning describes which Landlock features (rule types, access rights, scopes, permissions) the kernel implements, not which category members the kernel knows about.
Forward compatibility for new category members follows a simple rule set:
New members in future kernels are automatically denied: rules whitelist specific values, and a member not in any rule is denied.
Kernel-side compatibility for split categories is handled by the owning subsystem (e.g., when
CAP_BPFwas split fromCAP_SYS_ADMIN, either capability became sufficient for the affected operations, so a rule allowingCAP_SYS_ADMINcontinues to allow operations now gated byCAP_SYS_ADMIN || CAP_BPF).Unknown values in the rule body are silently accepted rather than rejected. Rejecting them would tie Landlock policy semantics to the running kernel’s category-member set: a rule built against future headers would fail to load on older kernels, forcing policy authors to know each kernel’s enumeration. Acceptance is fail-safe in both directions: a rule referring to a value the running kernel does not yet know has no effect (deny-by-default still applies to that operation), and a rule written against future headers loads identically across kernels so the same policy keeps the same restrictions. When a value becomes real on a future kernel, the policy activates as written by the author.
In contrast, unknown
LANDLOCK_PERMISSION_*flags inhandled_permissionsare rejected (-EINVAL), since Landlock owns that bit space.
Cross-domain scopes (scoped)¶
Scopes restrict cross-domain interactions categorically, without rules.
Setting a scope flag (e.g. LANDLOCK_SCOPE_SIGNAL) denies the operation to
targets outside the Landlock domain or its children. Like per-category
permissions, scopes provide complete coverage of the controlled operation.
Choosing a model for a new feature¶
If the new feature controls operations on resource objects supplied by the sandbox author, extend or add a per-object access right (
handled_access_*).If the new feature controls a per-category operation gated by an enum (a Linux capability, a namespace type, a socket family, etc.), use a per-category permission (
handled_permissions). When several such enums could classify the operation, prefer theenum theoriginating subsystem already uses for capability/access checks (e.g.CAP_*forcapable()hooks,CLONE_NEW*for namespace hooks).When an operation is gated by multiple kernel-defined enums (a classic example being
CAP_SYS_ADMINplus aCLONE_NEW*flag for non-user namespace creation), define one per-category permission perenum dimension. Sandbox authors handle each dimension’s permission inhandled_permissionsand add rules for each; the kernel enforces each dimension at its own LSM hook.LANDLOCK_PERMISSION_NAMESPACE_USEandLANDLOCK_PERMISSION_CAPABILITY_USEfollow this pattern.If the new feature restricts a categorical cross-domain interaction with no per-target granularity, use a cross-domain scope (
scoped).For all three models, confirm a single LSM hook (or small set of related hooks) covers every kernel path that exercises the operation.
Tests¶
Userspace tests for backward compatibility, ptrace restrictions and filesystem support can be found here: tools/testing/selftests/landlock/.
Kernel structures¶
Object¶
-
struct landlock_object_underops¶
Operations on an underlying object
Definition:
struct landlock_object_underops {
void (*release)(struct landlock_object *const object) __releases(object->lock);
};
Members
releaseReleases the underlying object (e.g.
iput()for an inode).
-
struct landlock_object¶
Security blob tied to a kernel object
Definition:
struct landlock_object {
refcount_t usage;
spinlock_t lock;
void *underobj;
union {
struct rcu_head rcu_free;
const struct landlock_object_underops *underops;
};
};
Members
usageThis counter is used to tie an object to the rules matching it or to keep it alive while adding a new rule. If this counter reaches zero, this
struct mustnot be modified, but this counter can still be read from within an RCU read-side critical section. When adding a new rule to an object with a usage counter of zero, we must wait until the pointer to this object is set to NULL (or recycled).lockProtects against concurrent modifications. This lock must be held from the time usage drops to zero until any weak references from underobj to this object have been cleaned up.
Lock ordering: inode->i_lock nests inside this.
underobjUsed when cleaning up an object and to mark an object as tied to its underlying kernel structure. This pointer is protected by lock. Cf.
landlock_release_inodes()andrelease_inode().{unnamed_union}anonymous
rcu_freeEnables lockless use of usage, lock and underobj from within an RCU read-side critical section. rcu_free and underops are only used by
landlock_put_object().underopsEnables
landlock_put_object()to release the underlying object (e.g. inode).
Description
The goal of this structure is to enable to tie a set of ephemeral access rights (pertaining to different domains) to a kernel object (e.g an inode) in a safe way. This implies to handle concurrent use and modification.
The lifetime of a struct landlock_object depends on the rules referring to
it.
Filesystem¶
-
struct landlock_inode_security¶
Inode security blob
Definition:
struct landlock_inode_security {
struct landlock_object *object;
};
Members
objectWeak pointer to an allocated object. All assignments of a new object are protected by the underlying inode->i_lock. However, atomically disassociating object from the inode is only protected by object->lock, from the time object’s usage refcount drops to zero to the time this pointer is nulled out (cf.
release_inode()andhook_sb_delete()). Indeed, such disassociation doesn’t require inode->i_lock thanks to the carefulrcu_access_pointer()check performed byget_inode_object().
Description
Enable to reference a struct landlock_object tied to an inode (i.e.
underlying object).
-
struct landlock_file_security¶
File security blob
Definition:
struct landlock_file_security {
access_mask_t allowed_access;
#ifdef CONFIG_SECURITY_LANDLOCK_LOG;
deny_masks_t deny_masks;
optional_access_t quiet_optional_accesses;
u8 fown_layer;
#endif ;
struct landlock_cred_security fown_subject;
struct pid *fown_tg;
};
Members
allowed_accessAccess rights that were available at the time of opening the file. This is not necessarily the full set of access rights available at that time, but it’s the necessary subset as needed to authorize later operations on the open file.
deny_masksDomain layer levels that deny an optional access (see _LANDLOCK_ACCESS_FS_OPTIONAL).
quiet_optional_accessesStores which optional accesses are covered by quiet rules within the layer referred to in deny_masks, one access per bit. Does not take into account whether the quiet access bits are actually set in the layer’s corresponding landlock_hierarchy.
fown_layerLayer level of fown_subject->domain with LANDLOCK_SCOPE_SIGNAL.
fown_subjectLandlock credential of the task that set the PID that may receive a signal e.g., SIGURG when writing MSG_OOB to the related socket. This pointer is protected by the related file->f_owner->lock, as for fown_struct’s members: pid, uid, and euid.
fown_tgThread group of the task that set the file owner, pinned while fown_subject holds a domain. It lets
hook_file_send_sigiotask()always allow a SIGIO delivered to the owner’s own process -- e.g. the thread-group leader reached through a process-group owner -- matching the same-process exemption ofhook_task_kill(). NULL when no domain is recorded. Protected by file->f_owner->lock, like fown_subject.
Description
This information is populated when opening a file in hook_file_open, and tracks the relevant Landlock access rights that were available at the time of opening the file. Other LSM hooks use these rights in order to authorize operations on already opened files.
-
struct landlock_superblock_security¶
Superblock security blob
Definition:
struct landlock_superblock_security {
atomic_long_t inode_refs;
};
Members
inode_refsNumber of pending inodes (from this superblock) that are being released by
release_inode(). Cf.struct super_block->s_fsnotify_inode_refs .
Description
Enable hook_sb_delete() to wait for concurrent calls to release_inode().
-
const char *resolve_path_for_trace(const struct path *path, char *buf)¶
Resolve a path for tracepoint display
Parameters
const struct path *pathThe path to resolve.
char *bufA buffer of at least PATH_MAX bytes for the resolved path.
Description
Uses d_absolute_path() to produce a namespace-independent absolute path,
unlike d_path() which resolves relative to the process’s chroot. This
ensures trace output is deterministic regardless of the tracer’s mount
namespace.
Return
A pointer into buf with the resolved path, or an error string (“<too_long>”, “<unreachable>”).
Namespace¶
Capability¶
-
u64 landlock_cap_to_bit(const int cap)¶
Convert a capability number to a compact bitmask
Parameters
const int capCapability number (CAP_*).
Return
BIT_ULL(cap), or 0 if cap is invalid (with a WARN).
-
u64 landlock_caps_to_bits(const u64 capabilities)¶
Validate and mask a capability bitmask
Parameters
const u64 capabilitiesBitmask of capabilities (e.g. from user space).
Return
capabilities masked to known capabilities. Warns if unknown bits are present (callers must pre-mask for user input).
Process credential¶
-
struct landlock_cred_security¶
Credential security blob
Definition:
struct landlock_cred_security {
struct landlock_domain *domain;
#ifdef CONFIG_SECURITY_LANDLOCK_LOG;
u16 domain_exec;
u8 log_subdomains_off : 1;
#endif ;
};
Members
domainImmutable domain enforced on a task.
domain_execBitmask identifying the domain layers that were enforced by the current task’s executed file (i.e. no new execve(2) since landlock_restrict_self(2)).
log_subdomains_offSet if the domain descendants’s log_status should be set to
LANDLOCK_LOG_DISABLED. This is not a landlock_hierarchy configuration because it applies to future descendant domains and it does not require a current domain.
Description
This structure is packed to minimize the size of struct
landlock_file_security. However, it is always aligned in the LSM cred blob,
see lsm_set_blob_size().
When updating this, also update landlock_cred_copy() if needed.
-
const struct landlock_cred_security *landlock_get_applicable_subject(const struct cred *const cred, const struct access_masks masks, size_t *const handle_layer)¶
Return the subject’s Landlock credential if its enforced domain applies to (i.e. handles) at least one of the access rights specified in masks
Parameters
const struct cred *const credcredential
const struct access_masks masksaccess masks
size_t *const handle_layerreturned youngest layer handling a subset of masks. Not set if the function returns NULL.
Return
landlock_cred(cred) if any access rights specified in masks is handled, or NULL otherwise.
Ruleset and domain¶
A domain is a read-only ruleset tied to a set of subjects (i.e. tasks’ credentials). Each time a ruleset is enforced on a task, the current domain is duplicated and the ruleset is imported as a new layer of rules in the new domain. Indeed, once in a domain, each rule is tied to a layer level. To grant access to an object, at least one rule of each layer must allow the requested action on the object. A task can then only transit to a new domain that is the intersection of the constraints from the current domain and those of a ruleset provided by the task.
The definition of a subject is implicit for a task sandboxing itself, which makes the reasoning much easier and helps avoid pitfalls.
-
struct landlock_layer¶
Access rights for a given layer
Definition:
struct landlock_layer {
u8 level;
struct {
u8 quiet : 1;
} flags;
access_mask_t access;
};
Members
levelPosition of this layer in the layer stack. Starts from 1.
flagsBitfield for special flags attached to this rule.
flags.quietSuppresses denial logs for the object covered by this rule in this domain. For filesystem rules, this inherits down the file hierarchy.
accessBitfield of allowed actions on the kernel object. They are relative to the object type (e.g.
LANDLOCK_ACTION_FS_READ).
-
union landlock_key¶
Key of a ruleset’s red-black tree
Definition:
union landlock_key {
struct landlock_object *object;
uintptr_t data;
};
Members
objectPointer to identify a kernel object (e.g. an inode).
dataRaw data to identify an arbitrary 32-bit value (e.g. a TCP port).
-
enum landlock_key_type¶
Type of
union landlock_key
Constants
LANDLOCK_KEY_INODEType of
landlock_rules.root_inode’s node keys.LANDLOCK_KEY_NET_PORTType of
landlock_rules.root_net_port’s node keys.
-
struct landlock_id¶
Unique rule identifier for a ruleset
Definition:
struct landlock_id {
union landlock_key key;
const enum landlock_key_type type;
};
Members
keyIdentifies either a kernel object (e.g. an inode) or a raw value (e.g. a TCP port).
typeType of a landlock_ruleset’s root tree.
-
struct landlock_rule¶
Access rights tied to an object
Definition:
struct landlock_rule {
struct rb_node node;
union landlock_key key;
u32 num_layers;
struct landlock_layer layers[];
};
Members
nodeNode in the ruleset’s red-black tree.
keyA
union toidentify either a kernel object (e.g. an inode) or a raw data value (e.g. a network socket port). This is used as a key for this ruleset element. The pointer is set once and never modified. It always points to an allocated object because each rule increments the refcount of its object.num_layersNumber of entries in layers.
layersStack of layers, from the latest to the newest, implemented as a flexible array member (FAM).
-
struct landlock_rules¶
Red-black tree storage for Landlock rules
Definition:
struct landlock_rules {
struct rb_root root_inode;
#if IS_ENABLED(CONFIG_INET);
struct rb_root root_net_port;
#endif ;
u32 num_rules;
};
Members
root_inodeRoot of a red-black tree containing
struct landlock_rulenodes with inode object. Immutable for domains.root_net_portRoot of a red-black tree containing
struct landlock_rulenodes with network port. Immutable for domains.num_rulesNumber of non-overlapping (i.e. not for the same object) rules in this tree storage.
Description
This structure holds the rule trees shared by both rulesets and domains.
-
struct landlock_ruleset¶
Landlock ruleset
Definition:
struct landlock_ruleset {
struct landlock_rules rules;
struct mutex lock;
refcount_t usage;
#ifdef CONFIG_TRACEPOINTS;
u64 version;
u64 id;
#endif ;
struct access_masks quiet_access;
#ifdef CONFIG_SECURITY_LANDLOCK_LOG;
struct permission_masks quiet_permission;
#endif ;
struct layer_config layer;
};
Members
rulesRed-black tree storage for rules.
lockProtects against concurrent modifications of rules, if usage is greater than zero.
usageNumber of file descriptors referencing this ruleset.
versionCounter incremented on each successful landlock_add_rule(2), including when it only extends an existing rule’s access rights. Used by tracepoints to correlate a domain with the exact successful rule history it was created from. Protected by lock.
idUnique identifier for this ruleset, used for tracing.
quiet_accessStores the quiet flags for an unmerged ruleset. For a merged domain, this is stored in each layer’s
struct landlock_hierarchyinstead. Its permissions member is unused because permission quieting is per member rather than per permission.quiet_permissionPer-member quiet bitmasks for permission types in this ruleset. A denied member whose bit is set here is not submitted to audit when this layer denies it.
layerAccess configuration for this ruleset’s single mutable layer.
Description
This data structure must contain unique entries, be updatable, and quick to match an object.
-
struct rb_root *landlock_get_rule_root(struct landlock_rules *const rules, const enum landlock_key_type key_type)¶
Get the root of a rule tree by key type
Parameters
struct landlock_rules *const rulesThe rules storage to look up.
const enum landlock_key_type key_typeThe type of key to select the tree for.
Return
A pointer to the rb_root, or ERR_PTR(-EINVAL) on unknown type.
-
struct landlock_details¶
Domain’s creation information
Definition:
struct landlock_details {
struct pid *pid;
uid_t uid;
char comm[TASK_COMM_LEN];
char exe_path[];
};
Members
pidPID of the task that initially restricted itself. It still identifies the same task. Keeping a reference to this PID ensures that it will not be recycled.
uidUID of the task that initially restricted itself, at creation time.
commCommand line of the task that initially restricted itself, at creation time. Always NULL terminated.
exe_pathExecutable path of the task that initially restricted itself, at creation time. Always NULL terminated, and never greater than LANDLOCK_PATH_MAX_SIZE.
Description
Rarely accessed, mainly when logging the first domain’s denial.
The contained pointers are initialized at the domain creation time and never changed again.
-
struct landlock_hierarchy¶
Node in a domain hierarchy
Definition:
struct landlock_hierarchy {
struct landlock_hierarchy *parent;
refcount_t usage;
#ifdef CONFIG_SECURITY_LANDLOCK_LOG;
enum landlock_log_status log_status;
atomic64_t num_denials;
u64 id;
const struct landlock_details *details;
u32 log_same_exec : 1, log_new_exec : 1;
struct access_masks quiet_access;
struct permission_masks quiet_permission;
#endif ;
};
Members
parentPointer to the parent node, or NULL if it is a root Landlock domain.
usageNumber of potential children domains plus their parent domain.
log_statusWhether this domain should be logged or not. Because concurrent log entries may be created at the same time, it is still possible to have several domain records of the same domain.
num_denialsNumber of access requests denied by this domain. Masked (i.e. never logged) denials are still counted.
idLandlock domain ID, set once at domain creation time.
detailsInformation about the related domain.
log_same_execSet if the domain is not configured with
LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF. Set to true by default.log_new_execSet if the domain is configured with
LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON. Set to false by default.quiet_accessBitmasks of access that should be quieted (i.e. not logged) if the related object is marked as quiet.
quiet_permissionPer-member quiet bitmasks for permission types in this layer.
-
struct landlock_domain¶
Immutable Landlock domain
Definition:
struct landlock_domain {
struct landlock_rules rules;
struct landlock_hierarchy *hierarchy;
union {
struct work_struct work_free;
struct {
refcount_t usage;
u32 num_layers;
struct layer_config layers[];
};
};
};
Members
rulesRed-black tree storage for rules.
hierarchyEnables hierarchy identification even when a parent domain vanishes. This is needed for the ptrace and scope restrictions.
{unnamed_union}anonymous
work_freeEnables to free a domain within a lockless section. This is only used by
landlock_put_domain_deferred()when usage reaches zero. The fields usage, num_layers and layers are then unused.{unnamed_struct}anonymous
usageNumber of credentials referencing this domain.
num_layersNumber of layers that are used in this domain. This enables to check that all the layers allow an access request.
layersPer-layer access configuration. A domain saves all layers of merged rulesets in a stack (FAM), starting from the first layer to the last one. These layers are used when merging rulesets, for user space backward compatibility (i.e. future-proof), and to properly handle merged rulesets without overlapping access rights. These layers are set once and never changed for the lifetime of the domain.
Not annotated with __counted_by(num_layers): clang miscomputes the counter address for a FAM nested in an anonymous
struct withina union, which trips FORTIFY: https://github.com/llvm/llvm-project/pull/228309
Description
A domain is created from a ruleset by landlock_merge_ruleset() and enforced
on a task. Once created, its rules and access masks are immutable. Unlike
struct landlock_ruleset, a domain has no lock field.
-
struct access_masks landlock_union_access_masks(const struct landlock_domain *const domain)¶
Return all access rights handled in the domain
Parameters
const struct landlock_domain *const domainLandlock domain
Return
An access_masks result of the OR of all the domain’s access masks.
-
size_t landlock_permission_is_denied(const struct landlock_domain *const domain, const access_mask_t permission_bit, const u64 request_value)¶
Check if a permission request is denied
Parameters
const struct landlock_domain *const domainThe enforced domain.
const access_mask_t permission_bitThe LANDLOCK_PERMISSION_* flag to check. Must have exactly one bit set.
const u64 request_valueCompact bitmask to look for (e.g. the result of
landlock_ns_type_to_bit()). Must have exactly one bit set.
Description
Iterate from the youngest layer to the oldest. For each layer that handles permission_bit, check whether request_value is present in the layer’s allowed bitmask. Return on the first (youngest) denying layer.
Return
The youngest denying layer + 1, or 0 if allowed.
Denial logging¶
Access denials are logged through two independent channels: audit
records and tracepoints. Both are managed by the common denial
framework in log.c, compiled under CONFIG_SECURITY_LANDLOCK_LOG
(automatically selected by CONFIG_AUDIT or CONFIG_TRACEPOINTS).
Audit records respect audit configuration, the domain’s Landlock log
flags, and LANDLOCK_LOG_DISABLED. Tracepoints fire unconditionally,
independent of these settings. The denial counter (num_denials) is
always incremented regardless of logging configuration.
Each denial tracepoint carries a logged field reporting the
audit-logging verdict: whether the denial would be written to the audit
log if audit were configured and active. This verdict is the same
whether or not the kernel is built with audit support, so a
tracepoints-only build reports the selection audit would make. A quiet
rule (LANDLOCK_ADD_RULE_QUIET with the access in the quiet_*
fields of struct landlock_ruleset_attr) suppresses logging by
setting logged=0 the same way, as do the per-member quiet_*
masks of capability and namespace rules.
See Landlock: system-wide management for audit record format, tracepoint usage, and filtering examples.
Trace events¶
See Landlock Trace Events for trace event usage and format details; the full event reference lives there and is not duplicated here.