1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Landlock - Credential hooks 4 * 5 * Copyright © 2019-2020 Mickaël Salaün <mic@digikod.net> 6 * Copyright © 2019-2020 ANSSI 7 * Copyright © 2021-2025 Microsoft Corporation 8 */ 9 10 #ifndef _SECURITY_LANDLOCK_CRED_H 11 #define _SECURITY_LANDLOCK_CRED_H 12 13 #include <linux/container_of.h> 14 #include <linux/cred.h> 15 #include <linux/init.h> 16 #include <linux/rcupdate.h> 17 18 #include "access.h" 19 #include "limits.h" 20 #include "ruleset.h" 21 #include "setup.h" 22 23 /** 24 * struct landlock_cred_security - Credential security blob 25 * 26 * This structure is packed to minimize the size of struct 27 * landlock_file_security. However, it is always aligned in the LSM cred blob, 28 * see lsm_set_blob_size(). 29 * 30 * When updating this, also update landlock_cred_copy() if needed. 31 */ 32 struct landlock_cred_security { 33 /** 34 * @domain: Immutable ruleset enforced on a task. 35 */ 36 struct landlock_ruleset *domain; 37 38 #ifdef CONFIG_AUDIT 39 /** 40 * @domain_exec: Bitmask identifying the domain layers that were enforced by 41 * the current task's executed file (i.e. no new execve(2) since 42 * landlock_restrict_self(2)). 43 */ 44 u16 domain_exec; 45 /** 46 * @log_subdomains_off: Set if the domain descendants's log_status should be 47 * set to %LANDLOCK_LOG_DISABLED. This is not a landlock_hierarchy 48 * configuration because it applies to future descendant domains and it does 49 * not require a current domain. 50 */ 51 u8 log_subdomains_off : 1; 52 #endif /* CONFIG_AUDIT */ 53 } __packed; 54 55 #ifdef CONFIG_AUDIT 56 57 /* Makes sure all layer executions can be stored. */ 58 static_assert(BITS_PER_TYPE(typeof_member(struct landlock_cred_security, 59 domain_exec)) >= 60 LANDLOCK_MAX_NUM_LAYERS); 61 62 #endif /* CONFIG_AUDIT */ 63 64 static inline struct landlock_cred_security * 65 landlock_cred(const struct cred *cred) 66 { 67 return cred->security + landlock_blob_sizes.lbs_cred; 68 } 69 70 static inline void landlock_cred_copy(struct landlock_cred_security *dst, 71 const struct landlock_cred_security *src) 72 { 73 landlock_put_ruleset(dst->domain); 74 75 *dst = *src; 76 77 landlock_get_ruleset(src->domain); 78 } 79 80 static inline struct landlock_ruleset *landlock_get_current_domain(void) 81 { 82 return landlock_cred(current_cred())->domain; 83 } 84 85 /* 86 * The call needs to come from an RCU read-side critical section. 87 */ 88 static inline const struct landlock_ruleset * 89 landlock_get_task_domain(const struct task_struct *const task) 90 { 91 return landlock_cred(__task_cred(task))->domain; 92 } 93 94 static inline bool landlocked(const struct task_struct *const task) 95 { 96 bool has_dom; 97 98 if (task == current) 99 return !!landlock_get_current_domain(); 100 101 rcu_read_lock(); 102 has_dom = !!landlock_get_task_domain(task); 103 rcu_read_unlock(); 104 return has_dom; 105 } 106 107 /** 108 * landlock_get_applicable_subject - Return the subject's Landlock credential 109 * if its enforced domain applies to (i.e. 110 * handles) at least one of the access rights 111 * specified in @masks 112 * 113 * @cred: credential 114 * @masks: access masks 115 * @handle_layer: returned youngest layer handling a subset of @masks. Not set 116 * if the function returns NULL. 117 * 118 * Returns: landlock_cred(@cred) if any access rights specified in @masks is 119 * handled, or NULL otherwise. 120 */ 121 static inline const struct landlock_cred_security * 122 landlock_get_applicable_subject(const struct cred *const cred, 123 const struct access_masks masks, 124 size_t *const handle_layer) 125 { 126 const union access_masks_all masks_all = { 127 .masks = masks, 128 }; 129 const struct landlock_ruleset *domain; 130 ssize_t layer_level; 131 132 if (!cred) 133 return NULL; 134 135 domain = landlock_cred(cred)->domain; 136 if (!domain) 137 return NULL; 138 139 for (layer_level = domain->num_layers - 1; layer_level >= 0; 140 layer_level--) { 141 union access_masks_all layer = { 142 .masks = domain->access_masks[layer_level], 143 }; 144 145 if (layer.all & masks_all.all) { 146 if (handle_layer) 147 *handle_layer = layer_level; 148 149 return landlock_cred(cred); 150 } 151 } 152 153 return NULL; 154 } 155 156 __init void landlock_add_cred_hooks(void); 157 158 #endif /* _SECURITY_LANDLOCK_CRED_H */ 159