summaryrefslogtreecommitdiff
path: root/include/trace
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-10-22 09:58:44 -1000
committerLinus Torvalds <torvalds@linux-foundation.org>2026-10-22 09:58:44 -1000
commit3815f7d55ae18564f4eac57557479f8b3548af95 (patch)
treee8ec39efb4107e35910700c2ea8bc91c9a0bf77e /include/trace
parentbbc48daecac6c69ccbce4005aa2a681298e2fc7d (diff)
parent3e271a27c46fd591d1011c7de5a644a41e2010f1 (diff)
Merge tag 'landlock-7.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mic/linux
Pull Landlock update from Mickaël Salaün: "The main change adds composable Landlock controls for namespace types and Linux capabilities, thanks to new LSM hooks (merged via the LSM tree). A umount race condition is also fixed" * tag 'landlock-7.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mic/linux: landlock: Fix superblock use-after-free in release_inode() selftests/landlock: Fix snprintf truncation checks in test files landlock: Add documentation for capability and namespace restrictions samples/landlock: Add capability and namespace restriction support selftests/landlock: Add capability restriction tests selftests/landlock: Add namespace restriction tests landlock: Enforce capability restrictions landlock: Enforce namespace use restrictions landlock: Wrap per-layer access masks in struct layer_config landlock: Rename quiet_masks to quiet_access
Diffstat (limited to 'include/trace')
-rw-r--r--include/trace/events/landlock.h244
1 files changed, 224 insertions, 20 deletions
diff --git a/include/trace/events/landlock.h b/include/trace/events/landlock.h
index 9e172ea22d95..6d9d9e7c7ca2 100644
--- a/include/trace/events/landlock.h
+++ b/include/trace/events/landlock.h
@@ -36,6 +36,8 @@ static_assert(sizeof(access_mask_t) <= sizeof(u64));
TRACE_DEFINE_ENUM(LANDLOCK_REQUEST_FS_CHANGE_TOPOLOGY);
TRACE_DEFINE_ENUM(LANDLOCK_REQUEST_FS_ACCESS);
TRACE_DEFINE_ENUM(LANDLOCK_REQUEST_NET_ACCESS);
+TRACE_DEFINE_ENUM(LANDLOCK_REQUEST_NAMESPACE);
+TRACE_DEFINE_ENUM(LANDLOCK_REQUEST_CAPABILITY);
#ifdef CREATE_TRACE_POINTS
@@ -276,13 +278,14 @@ static inline const char *__trace_landlock_print_layers(
* Every denial event shares three fields. domain is the ID of the
* innermost domain that blocked the access. same_exec tells whether the
* current task is the same executable that entered that domain. logged is
- * the domain's audit-logging decision for this denial (its log_status is
- * enabled and the per-execution flag selected by same_exec is set); a
- * stateless ftrace filter can select the denials the domain submits to
- * audit with logged==1, without reconstructing it from the per-execution
- * log flags. Denial events order their fields as domain, same_exec,
- * logged, then blockers (deny_access events only), then the type-specific
- * object fields, then any variable-length field.
+ * the complete audit-submission selection for this denial: the domain's
+ * log_status and per-execution flag, per-object or per-member quiet rules,
+ * and request-specific no-audit options. This excludes global audit state
+ * and audit-side filters. A stateless ftrace filter can select the denials
+ * the domain submits to audit with logged==1, without reconstructing those
+ * inputs. Denial events order their shared fields as domain, same_exec,
+ * and logged. Access and permission denial events follow these with the
+ * blockers verdict input, type-specific fields, and any variable-length field.
*
* Relational referents
* ~~~~~~~~~~~~~~~~~~~~~
@@ -302,9 +305,9 @@ static inline const char *__trace_landlock_print_layers(
* Blocker fields
* ~~~~~~~~~~~~~~
*
- * The filesystem and network blocker arguments identify the request type
- * and carry its final missing access subset when applicable. The type
- * determines how to interpret the access value.
+ * Blocker arguments identify the request type and carry its final missing
+ * access subset when applicable. The type determines how to interpret the
+ * access value.
*/
/*
@@ -343,26 +346,31 @@ TRACE_EVENT(landlock_create_ruleset,
TP_ARGS(ruleset),
TP_STRUCT__entry(
- __field( u64, ruleset_id )
- __field( u64, ruleset_version )
- __field( access_mask_t, handled_fs )
- __field( access_mask_t, handled_net )
- __field( access_mask_t, scoped )
+ __field( u64, ruleset_id )
+ __field( u64, ruleset_version )
+ __field( access_mask_t, handled_fs )
+ __field( access_mask_t, handled_net )
+ __field( access_mask_t, scoped )
+ __field( access_mask_t, handled_permissions )
),
TP_fast_assign(
__entry->ruleset_id = ruleset->id;
__entry->ruleset_version = ruleset->version;
- __entry->handled_fs = ruleset->handled_masks.fs;
- __entry->handled_net = ruleset->handled_masks.net;
- __entry->scoped = ruleset->handled_masks.scope;
+ __entry->handled_fs = ruleset->layer.handled.fs;
+ __entry->handled_net = ruleset->layer.handled.net;
+ __entry->scoped = ruleset->layer.handled.scope;
+ __entry->handled_permissions =
+ ruleset->layer.handled.permissions;
),
- TP_printk("ruleset=%llx.%llu handled_fs=%s handled_net=%s scoped=%s",
+ TP_printk("ruleset=%llx.%llu handled_fs=%s handled_net=%s scoped=%s handled_permissions=%s",
__entry->ruleset_id, __entry->ruleset_version,
__print_flags(__entry->handled_fs, "|", _LANDLOCK_ACCESS_FS_NAMES),
__print_flags(__entry->handled_net, "|", _LANDLOCK_ACCESS_NET_NAMES),
- __print_flags(__entry->scoped, "|", _LANDLOCK_SCOPE_NAMES))
+ __print_flags(__entry->scoped, "|", _LANDLOCK_SCOPE_NAMES),
+ __print_flags(__entry->handled_permissions, "|",
+ _LANDLOCK_PERMISSION_NAMES))
);
/**
@@ -497,6 +505,103 @@ TRACE_EVENT(landlock_add_rule_net_port,
);
/**
+ * landlock_add_rule_namespace - Namespace rule added to a ruleset
+ *
+ * @ruleset: Source ruleset (never NULL).
+ * @flags: Complete validated landlock_add_rule_flags value supplied by this
+ * successful call, not the rule's accumulated quiet state.
+ * @permissions: Validated permission mask from the rule attribute.
+ * @allowed_namespace_types: Effective known namespace types allowed by this
+ * call, using CLONE_NEW* values.
+ * @quiet_namespace_types: Effective known namespace types quieted by this
+ * call, using CLONE_NEW* values.
+ *
+ * Emitted by sys_landlock_add_rule() under the modified ruleset's lock, so
+ * the reported ruleset is a stable snapshot that no concurrent writer can
+ * change.
+ */
+TRACE_EVENT(landlock_add_rule_namespace,
+
+ TP_PROTO(const struct landlock_ruleset *ruleset, u32 flags,
+ u64 permissions, u64 allowed_namespace_types,
+ u64 quiet_namespace_types),
+
+ TP_ARGS(ruleset, flags, permissions, allowed_namespace_types,
+ quiet_namespace_types),
+
+ TP_STRUCT__entry(
+ __field( u64, ruleset_id )
+ __field( u64, ruleset_version )
+ __field( access_mask_t, permissions )
+ __field( u64, allowed_namespace_types )
+ __field( u64, quiet_namespace_types )
+ ),
+
+ TP_fast_assign(
+ lockdep_assert_held(&ruleset->lock);
+ __entry->ruleset_id = ruleset->id;
+ __entry->ruleset_version = ruleset->version;
+ __entry->permissions = permissions;
+ __entry->allowed_namespace_types = allowed_namespace_types;
+ __entry->quiet_namespace_types = quiet_namespace_types;
+ ),
+
+ TP_printk("ruleset=%llx.%llu permissions=%s allowed_namespace_types=0x%llx quiet_namespace_types=0x%llx",
+ __entry->ruleset_id, __entry->ruleset_version,
+ __print_flags(__entry->permissions, "|",
+ _LANDLOCK_PERMISSION_NAMES),
+ __entry->allowed_namespace_types,
+ __entry->quiet_namespace_types)
+);
+
+/**
+ * landlock_add_rule_capability - Capability rule added to a ruleset
+ *
+ * @ruleset: Source ruleset (never NULL).
+ * @flags: Complete validated landlock_add_rule_flags value supplied by this
+ * successful call, not the rule's accumulated quiet state.
+ * @permissions: Validated permission mask from the rule attribute.
+ * @allowed_capabilities: Effective known capabilities allowed by this call.
+ * @quiet_capabilities: Effective known capabilities quieted by this call.
+ *
+ * Emitted by sys_landlock_add_rule() under the modified ruleset's lock, so
+ * the reported ruleset is a stable snapshot that no concurrent writer can
+ * change.
+ */
+TRACE_EVENT(landlock_add_rule_capability,
+
+ TP_PROTO(const struct landlock_ruleset *ruleset, u32 flags,
+ u64 permissions, u64 allowed_capabilities,
+ u64 quiet_capabilities),
+
+ TP_ARGS(ruleset, flags, permissions, allowed_capabilities,
+ quiet_capabilities),
+
+ TP_STRUCT__entry(
+ __field( u64, ruleset_id )
+ __field( u64, ruleset_version )
+ __field( access_mask_t, permissions )
+ __field( u64, allowed_capabilities )
+ __field( u64, quiet_capabilities )
+ ),
+
+ TP_fast_assign(
+ lockdep_assert_held(&ruleset->lock);
+ __entry->ruleset_id = ruleset->id;
+ __entry->ruleset_version = ruleset->version;
+ __entry->permissions = permissions;
+ __entry->allowed_capabilities = allowed_capabilities;
+ __entry->quiet_capabilities = quiet_capabilities;
+ ),
+
+ TP_printk("ruleset=%llx.%llu permissions=%s allowed_capabilities=0x%llx quiet_capabilities=0x%llx",
+ __entry->ruleset_id, __entry->ruleset_version,
+ __print_flags(__entry->permissions, "|",
+ _LANDLOCK_PERMISSION_NAMES),
+ __entry->allowed_capabilities, __entry->quiet_capabilities)
+);
+
+/**
* landlock_create_domain - New domain created
*
* @domain: Newly created domain (never NULL, immutable after creation).
@@ -874,6 +979,105 @@ TRACE_EVENT(landlock_deny_access_net,
);
/**
+ * landlock_deny_permission_namespace - Namespace use denied
+ *
+ * @hierarchy: Denying domain's hierarchy node (never NULL); its id is the
+ * domain field.
+ * @same_exec: Whether the current task entered the denying domain itself.
+ * @logged: Whether this denial was selected for audit logging.
+ * @blockers: Request type and final missing permission subset (never NULL).
+ * @namespace_type: CLONE_NEW* namespace type that was denied.
+ * @namespace_id: Namespace ID, or 0 when creation was denied.
+ *
+ * Emitted when a Landlock domain denies namespace use.
+ */
+TRACE_EVENT(landlock_deny_permission_namespace,
+
+ TP_PROTO(const struct landlock_hierarchy *hierarchy, bool same_exec,
+ bool logged, const struct landlock_blockers *blockers,
+ u32 namespace_type, u64 namespace_id),
+
+ TP_ARGS(hierarchy, same_exec, logged, blockers, namespace_type,
+ namespace_id),
+
+ TP_STRUCT__entry(
+ __field( u64, domain_id )
+ __field( bool, same_exec )
+ __field( bool, logged )
+ __field( enum landlock_request_type, blockers_type )
+ __field( access_mask_t, blockers_access )
+ __field( u32, namespace_type )
+ __field( u64, namespace_id )
+ ),
+
+ TP_fast_assign(
+ __entry->domain_id = hierarchy->id;
+ __entry->same_exec = same_exec;
+ __entry->logged = logged;
+ __entry->blockers_type = blockers->type;
+ __entry->blockers_access = blockers->access;
+ __entry->namespace_type = namespace_type;
+ __entry->namespace_id = namespace_id;
+ ),
+
+ TP_printk("domain=%llx same_exec=%d logged=%d blockers=%s namespace_type=0x%x namespace_id=%llu",
+ __entry->domain_id, __entry->same_exec, __entry->logged,
+ __entry->blockers_type == LANDLOCK_REQUEST_NAMESPACE ?
+ __print_flags(__entry->blockers_access, "|",
+ _LANDLOCK_PERMISSION_BLOCKER_NAMES) :
+ "unknown",
+ __entry->namespace_type, __entry->namespace_id)
+);
+
+/**
+ * landlock_deny_permission_capability - Capability use denied
+ *
+ * @hierarchy: Denying domain's hierarchy node (never NULL); its id is the
+ * domain field.
+ * @same_exec: Whether the current task entered the denying domain itself.
+ * @logged: Whether this denial was selected for audit logging.
+ * @blockers: Request type and final missing permission subset (never NULL).
+ * @capability: CAP_* number that was denied.
+ *
+ * Emitted when a Landlock domain denies capability use, except for checks
+ * made with CAP_OPT_NOAUDIT, which are denied without emitting this event.
+ */
+TRACE_EVENT(landlock_deny_permission_capability,
+
+ TP_PROTO(const struct landlock_hierarchy *hierarchy, bool same_exec,
+ bool logged, const struct landlock_blockers *blockers,
+ int capability),
+
+ TP_ARGS(hierarchy, same_exec, logged, blockers, capability),
+
+ TP_STRUCT__entry(
+ __field( u64, domain_id )
+ __field( bool, same_exec )
+ __field( bool, logged )
+ __field( enum landlock_request_type, blockers_type )
+ __field( access_mask_t, blockers_access )
+ __field( int, capability )
+ ),
+
+ TP_fast_assign(
+ __entry->domain_id = hierarchy->id;
+ __entry->same_exec = same_exec;
+ __entry->logged = logged;
+ __entry->blockers_type = blockers->type;
+ __entry->blockers_access = blockers->access;
+ __entry->capability = capability;
+ ),
+
+ TP_printk("domain=%llx same_exec=%d logged=%d blockers=%s capability=%d",
+ __entry->domain_id, __entry->same_exec, __entry->logged,
+ __entry->blockers_type == LANDLOCK_REQUEST_CAPABILITY ?
+ __print_flags(__entry->blockers_access, "|",
+ _LANDLOCK_PERMISSION_BLOCKER_NAMES) :
+ "unknown",
+ __entry->capability)
+);
+
+/**
* landlock_deny_ptrace - Ptrace access denied by a Landlock domain
*
* @hierarchy: Denying domain's hierarchy node (never NULL); its id is the