| /* SPDX-License-Identifier: GPL-2.0-only */ | |
| /* | |
| * Landlock - Domain management | |
| * | |
| * Copyright © 2016-2020 Mickaël Salaün <mic@digikod.net> | |
| * Copyright © 2018-2020 ANSSI | |
| * Copyright © 2024-2025 Microsoft Corporation | |
| */ | |
| #ifndef _SECURITY_LANDLOCK_DOMAIN_H | |
| #define _SECURITY_LANDLOCK_DOMAIN_H | |
| #include <linux/limits.h> | |
| #include <linux/mm.h> | |
| #include <linux/path.h> | |
| #include <linux/pid.h> | |
| #include <linux/refcount.h> | |
| #include <linux/sched.h> | |
| #include <linux/slab.h> | |
| #include "access.h" | |
| #include "audit.h" | |
| enum landlock_log_status { | |
| LANDLOCK_LOG_PENDING = 0, | |
| LANDLOCK_LOG_RECORDED, | |
| LANDLOCK_LOG_DISABLED, | |
| }; | |
| /** | |
| * struct landlock_details - Domain's creation information | |
| * | |
| * 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_details { | |
| /** | |
| * @pid: PID 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. | |
| */ | |
| struct pid *pid; | |
| /** | |
| * @uid: UID of the task that initially restricted itself, at creation time. | |
| */ | |
| uid_t uid; | |
| /** | |
| * @comm: Command line of the task that initially restricted itself, at | |
| * creation time. Always NULL terminated. | |
| */ | |
| char comm[TASK_COMM_LEN]; | |
| /** | |
| * @exe_path: Executable path of the task that initially restricted | |
| * itself, at creation time. Always NULL terminated, and never greater | |
| * than LANDLOCK_PATH_MAX_SIZE. | |
| */ | |
| char exe_path[]; | |
| }; | |
| /* Adds 11 extra characters for the potential " (deleted)" suffix. */ | |
| #define LANDLOCK_PATH_MAX_SIZE (PATH_MAX + 11) | |
| /* Makes sure the greatest landlock_details can be allocated. */ | |
| static_assert(struct_size_t(struct landlock_details, exe_path, | |
| LANDLOCK_PATH_MAX_SIZE) <= KMALLOC_MAX_SIZE); | |
| /** | |
| * struct landlock_hierarchy - Node in a domain hierarchy | |
| */ | |
| struct landlock_hierarchy { | |
| /** | |
| * @parent: Pointer to the parent node, or NULL if it is a root | |
| * Landlock domain. | |
| */ | |
| struct landlock_hierarchy *parent; | |
| /** | |
| * @usage: Number of potential children domains plus their parent | |
| * domain. | |
| */ | |
| refcount_t usage; | |
| #ifdef CONFIG_AUDIT | |
| /** | |
| * @log_status: Whether 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. | |
| */ | |
| enum landlock_log_status log_status; | |
| /** | |
| * @num_denials: Number of access requests denied by this domain. | |
| * Masked (i.e. never logged) denials are still counted. | |
| */ | |
| atomic64_t num_denials; | |
| /** | |
| * @id: Landlock domain ID, set once at domain creation time. | |
| */ | |
| u64 id; | |
| /** | |
| * @details: Information about the related domain. | |
| */ | |
| const struct landlock_details *details; | |
| /** | |
| * @log_same_exec: Set if the domain is *not* configured with | |
| * %LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF. Set to true by default. | |
| */ | |
| u32 log_same_exec : 1, | |
| /** | |
| * @log_new_exec: Set if the domain is configured with | |
| * %LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON. Set to false by default. | |
| */ | |
| log_new_exec : 1; | |
| /** | |
| * @quiet_masks: Bitmasks of access that should be quieted (i.e. not | |
| * logged) if the related object is marked as quiet. | |
| */ | |
| struct access_masks quiet_masks; | |
| #endif /* CONFIG_AUDIT */ | |
| }; | |
| #ifdef CONFIG_AUDIT | |
| deny_masks_t | |
| landlock_get_deny_masks(const access_mask_t all_existing_optional_access, | |
| const access_mask_t optional_access, | |
| const struct layer_masks *const masks); | |
| optional_access_t landlock_get_quiet_optional_accesses( | |
| const access_mask_t all_existing_optional_access, | |
| const deny_masks_t deny_masks, const struct layer_masks *const masks); | |
| int landlock_init_hierarchy_log(struct landlock_hierarchy *const hierarchy); | |
| static inline void | |
| landlock_free_hierarchy_details(struct landlock_hierarchy *const hierarchy) | |
| { | |
| if (!hierarchy || !hierarchy->details) | |
| return; | |
| put_pid(hierarchy->details->pid); | |
| kfree(hierarchy->details); | |
| } | |
| #else /* CONFIG_AUDIT */ | |
| static inline int | |
| landlock_init_hierarchy_log(struct landlock_hierarchy *const hierarchy) | |
| { | |
| return 0; | |
| } | |
| static inline void | |
| landlock_free_hierarchy_details(struct landlock_hierarchy *const hierarchy) | |
| { | |
| } | |
| #endif /* CONFIG_AUDIT */ | |
| static inline void | |
| landlock_get_hierarchy(struct landlock_hierarchy *const hierarchy) | |
| { | |
| if (hierarchy) | |
| refcount_inc(&hierarchy->usage); | |
| } | |
| static inline void landlock_put_hierarchy(struct landlock_hierarchy *hierarchy) | |
| { | |
| while (hierarchy && refcount_dec_and_test(&hierarchy->usage)) { | |
| const struct landlock_hierarchy *const freeme = hierarchy; | |
| landlock_log_drop_domain(hierarchy); | |
| landlock_free_hierarchy_details(hierarchy); | |
| hierarchy = hierarchy->parent; | |
| kfree(freeme); | |
| } | |
| } | |
| #endif /* _SECURITY_LANDLOCK_DOMAIN_H */ |