diff options
| author | Mickaël Salaün <mic@digikod.net> | 2026-10-14 10:27:09 +0200 |
|---|---|---|
| committer | Mickaël Salaün <mic@digikod.net> | 2026-10-14 10:33:56 +0200 |
| commit | d69b4e79336fafb4775fcad9a55c544a22020823 (patch) | |
| tree | 32d39e6148ea23752c71e7730fb9577453172989 /include/uapi/linux | |
| parent | c3a32f3c277d8d1efc487632853c18b8672e1fb8 (diff) | |
| download | linux-next-d69b4e79336fafb4775fcad9a55c544a22020823.tar.gz linux-next-d69b4e79336fafb4775fcad9a55c544a22020823.zip | |
landlock: Enforce namespace use restrictions
Add Landlock enforcement for namespace use through the LSM
namespace_init and namespace_install hooks. This lets a sandboxed
process restrict which namespace types it can create, join, or acquire a
file descriptor for, using LANDLOCK_PERMISSION_NAMESPACE_USE and
per-type rules.
Introduce the handled_permissions field in struct landlock_ruleset_attr:
each permission gates every use of a kernel-defined category (CLONE_NEW*
namespace types, CAP_* capabilities) with complete deny-by-default
coverage, so unknown member values need no validation, being denied
until a rule allows them. This UAPI extension advances the Landlock ABI
from 11 to 12.
There is no domain-ancestry bypass and no namespace-creator tracking,
only a flat per-layer allowed-types bitmask: hook_namespace_init()
covers creation through clone(2), unshare(2), open_tree(2) and
fsmount(2), and hook_namespace_install() covers setns(2). Each
permission hook maps its member mask explicitly in the shared permission
walker, which warns and denies if a future caller omits that mapping.
These categorical denials return -EPERM, matching Landlock's scope and
mount-topology denials rather than its object-access -EACCES convention.
struct permission_masks is forced to eight bytes with __packed and
__aligned because it must eventually hold both the eight namespace types
and all capabilities, and because m68k GCC otherwise packs its u64
bitfields at byte granularity, making the structure smaller than
sizeof(u64). Carrying it grows struct layer_config from 4 to 16 bytes,
so the largest 16-entry domain FAM grows from 64 to 256 bytes.
The permissions selector keeps the rule attribute self-describing:
- User space can mask it against handled_permissions, as it masks
allowed_access against handled_access_fs, so a program built against
newer headers still adds the rules an older kernel supports.
- It tells apart two attributes that share the same three-u64 layout.
Unknown member bits are ignored, so without it a mismatched rule type
would apply a capability mask as namespace types.
- It leaves room for a rule to carry several permissions, or for another
rule type to key the same permission differently.
The rule also carries a quiet_namespace_types bitmask that suppresses
audit submission for denied members without granting them. A sandbox
knowingly running a caller that probes a type it will never be granted
would otherwise flood the audit log and drown the surprising denials
that matter. Quiet is per-member rather than a coarse per-category
ruleset bit, so a sandbox can silence CLONE_NEWNET while still auditing
CLONE_NEWUTS; making it the complement of the allowed set would be
broad, could not audit a member that is neither allowed nor explicitly
quieted, and would auto-hide members added by future kernels. It is a
per-rule bitmask rather than the LANDLOCK_ADD_RULE_QUIET flag and the
ruleset quiet_access_* masks, which suit the unbounded rb-tree objects
of filesystem and network rules, so that flag is rejected here. Only
the youngest denying layer's quiet mask decides, so a parent cannot
silence a denial made by a deeper layer.
Trace the handled permission mask, every successful namespace rule, and
namespace denials. Successful effective no-ops advance the version, and
quiet denials remain trace-visible with logged=0. The denial event
takes the blockers argument of the filesystem and network events and
records the same blockers_type and blockers_access fields, so one filter
expression spans the mask-bearing denial events. Handled and rule
permission masks may contain permissions from multiple domains in one
field, so their names are domain-qualified, such as namespace.use. A
blocker is already interpreted in the domain supplied by the audit
prefix or denial event, so it retains the bare action name use, matching
existing access blockers such as read_file.
User namespace creation does not require capabilities, so Landlock can
restrict it directly. Non-user namespace types require CAP_SYS_ADMIN
before the Landlock check is reached; when the capability permission
added by the next commit is also handled, both must allow the operation.
Cc: Christian Brauner <brauner@kernel.org>
Cc: Günther Noack <gnoack@google.com>
Cc: Paul Moore <paul@paul-moore.com>
Cc: Serge E. Hallyn <serge@hallyn.com>
Link: https://patch.msgid.link/20261014082718.1435842-4-mic@digikod.net
Signed-off-by: Mickaël Salaün <mic@digikod.net>
Diffstat (limited to 'include/uapi/linux')
| -rw-r--r-- | include/uapi/linux/landlock.h | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/include/uapi/linux/landlock.h b/include/uapi/linux/landlock.h index cceda3b3b961..bb8ec589ddac 100644 --- a/include/uapi/linux/landlock.h +++ b/include/uapi/linux/landlock.h @@ -78,6 +78,11 @@ struct landlock_ruleset_attr { * @quiet_scoped: Bitmask of scoped actions which should not be logged. */ __u64 quiet_scoped; + /** + * @handled_permissions: Bitmask of handled permissions (cf. `Permission + * flags`_). + */ + __u64 handled_permissions; }; /** @@ -228,6 +233,10 @@ enum landlock_rule_type { * landlock_net_port_attr . */ LANDLOCK_RULE_NET_PORT, + /** + * @LANDLOCK_RULE_NAMESPACE: Type of a &struct landlock_namespace_attr . + */ + LANDLOCK_RULE_NAMESPACE, }; /** @@ -282,6 +291,41 @@ struct landlock_net_port_attr { }; /** + * struct landlock_namespace_attr - Namespace type definition + * + * Argument of sys_landlock_add_rule() with %LANDLOCK_RULE_NAMESPACE. + */ +struct landlock_namespace_attr { + /** + * @permissions: Must be set to %LANDLOCK_PERMISSION_NAMESPACE_USE. + */ + __u64 permissions; + /** + * @allowed_namespace_types: Bitmask of namespace types (``CLONE_NEW*`` + * flags) to allow under this rule. Unknown bits are silently ignored + * for forward compatibility. + */ + __u64 allowed_namespace_types; + /** + * @quiet_namespace_types: Bitmask of namespace types (``CLONE_NEW*`` + * flags) whose denial by this layer should not be submitted to audit, + * even when landlock_restrict_self() enables audit logging. Only audit + * records attributed to this layer are suppressed; denial tracepoints + * still fire (see `Permission flags`_). Bits also set in + * @allowed_namespace_types have no effect, since an allowed type is + * never denied. Unknown bits are silently ignored. + * + * At least one of @allowed_namespace_types or @quiet_namespace_types + * must be non-zero, otherwise the call returns ``-ENOMSG``. The + * non-zero check runs on the raw input before unknown-bit masking, so a + * rule that sets only bits unknown to the running kernel succeeds but + * has no runtime effect. Programs should omit this rule when they + * neither allow nor quiet a namespace type. + */ + __u64 quiet_namespace_types; +}; + +/** * DOC: fs_access * * A set of actions on kernel objects may be defined by an attribute (e.g. @@ -507,4 +551,33 @@ struct landlock_net_port_attr { #define LANDLOCK_SCOPE_SIGNAL (1ULL << 1) /* clang-format on*/ +/** + * DOC: permission + * + * Permission flags + * ~~~~~~~~~~~~~~~~ + * + * These flags restrict the use of members of a category, each member being + * identified by a constant from another kernel subsystem (e.g. CLONE_NEW* + * namespace types, CAP_* capabilities). A flag covers every kernel path that + * uses a member of its category, and members that no rule explicitly allows are + * denied. Values unknown to the running kernel are silently accepted for + * forward compatibility and stay denied by default. See + * Documentation/security/landlock.rst for design details. + * + * When a ruleset handles multiple permissions whose operations overlap (e.g. a + * non-user namespace needs both its namespace type and CAP_SYS_ADMIN), the + * operation is allowed only if each handled permission independently allows it. + * See Documentation/userspace-api/landlock.rst. + * + * - %LANDLOCK_PERMISSION_NAMESPACE_USE: Restrict the use of specific namespace + * types: creation (:manpage:`unshare(2)`, :manpage:`clone(2)`, + * :manpage:`clone3(2)`), joining (:manpage:`setns(2)`), and acquiring an fd + * reference (:manpage:`open_tree(2)`, :manpage:`fsmount(2)`). A process in a + * Landlock domain that handles this permission is denied from using namespace + * types that are not explicitly allowed by a %LANDLOCK_RULE_NAMESPACE rule. + * Support added in Landlock ABI version 12. + */ +#define LANDLOCK_PERMISSION_NAMESPACE_USE (1ULL << 0) + #endif /* _UAPI_LINUX_LANDLOCK_H */ |
