Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0-only */ 2 : : /* 3 : : * AppArmor security module 4 : : * 5 : : * This file contains AppArmor lib definitions 6 : : * 7 : : * 2017 Canonical Ltd. 8 : : */ 9 : : 10 : : #ifndef __AA_LIB_H 11 : : #define __AA_LIB_H 12 : : 13 : : #include <linux/slab.h> 14 : : #include <linux/fs.h> 15 : : #include <linux/lsm_hooks.h> 16 : : 17 : : #include "match.h" 18 : : 19 : : /* 20 : : * DEBUG remains global (no per profile flag) since it is mostly used in sysctl 21 : : * which is not related to profile accesses. 22 : : */ 23 : : 24 : : #define DEBUG_ON (aa_g_debug) 25 : : #define dbg_printk(__fmt, __args...) pr_debug(__fmt, ##__args) 26 : : #define AA_DEBUG(fmt, args...) \ 27 : : do { \ 28 : : if (DEBUG_ON) \ 29 : : pr_debug_ratelimited("AppArmor: " fmt, ##args); \ 30 : : } while (0) 31 : : 32 : : #define AA_WARN(X) WARN((X), "APPARMOR WARN %s: %s\n", __func__, #X) 33 : : 34 : : #define AA_BUG(X, args...) AA_BUG_FMT((X), "" args) 35 : : #ifdef CONFIG_SECURITY_APPARMOR_DEBUG_ASSERTS 36 : : #define AA_BUG_FMT(X, fmt, args...) \ 37 : : WARN((X), "AppArmor WARN %s: (" #X "): " fmt, __func__, ##args) 38 : : #else 39 : : #define AA_BUG_FMT(X, fmt, args...) 40 : : #endif 41 : : 42 : : #define AA_ERROR(fmt, args...) \ 43 : : pr_err_ratelimited("AppArmor: " fmt, ##args) 44 : : 45 : : /* Flag indicating whether initialization completed */ 46 : : extern int apparmor_initialized; 47 : : 48 : : /* fn's in lib */ 49 : : const char *skipn_spaces(const char *str, size_t n); 50 : : char *aa_split_fqname(char *args, char **ns_name); 51 : : const char *aa_splitn_fqname(const char *fqname, size_t n, const char **ns_name, 52 : : size_t *ns_len); 53 : : void aa_info_message(const char *str); 54 : : 55 : : /* Security blob offsets */ 56 : : extern struct lsm_blob_sizes apparmor_blob_sizes; 57 : : 58 : : /** 59 : : * aa_strneq - compare null terminated @str to a non null terminated substring 60 : : * @str: a null terminated string 61 : : * @sub: a substring, not necessarily null terminated 62 : : * @len: length of @sub to compare 63 : : * 64 : : * The @str string must be full consumed for this to be considered a match 65 : : */ 66 : 0 : static inline bool aa_strneq(const char *str, const char *sub, int len) 67 : : { 68 : 0 : return !strncmp(str, sub, len) && !str[len]; 69 : : } 70 : : 71 : : /** 72 : : * aa_dfa_null_transition - step to next state after null character 73 : : * @dfa: the dfa to match against 74 : : * @start: the state of the dfa to start matching in 75 : : * 76 : : * aa_dfa_null_transition transitions to the next state after a null 77 : : * character which is not used in standard matching and is only 78 : : * used to separate pairs. 79 : : */ 80 : : static inline unsigned int aa_dfa_null_transition(struct aa_dfa *dfa, 81 : : unsigned int start) 82 : : { 83 : : /* the null transition only needs the string's null terminator byte */ 84 : 0 : return aa_dfa_next(dfa, start, 0); 85 : : } 86 : : 87 : : static inline bool path_mediated_fs(struct dentry *dentry) 88 : : { 89 : 0 : return !(dentry->d_sb->s_flags & SB_NOUSER); 90 : : } 91 : : 92 : : 93 : : struct counted_str { 94 : : struct kref count; 95 : : char name[]; 96 : : }; 97 : : 98 : : #define str_to_counted(str) \ 99 : : ((struct counted_str *)(str - offsetof(struct counted_str, name))) 100 : : 101 : : #define __counted /* atm just a notation */ 102 : : 103 : : void aa_str_kref(struct kref *kref); 104 : : char *aa_str_alloc(int size, gfp_t gfp); 105 : : 106 : : 107 : : static inline __counted char *aa_get_str(__counted char *str) 108 : : { 109 : 0 : if (str) 110 : : kref_get(&(str_to_counted(str)->count)); 111 : : 112 : : return str; 113 : : } 114 : : 115 : : static inline void aa_put_str(__counted char *str) 116 : : { 117 : 0 : if (str) 118 : 0 : kref_put(&str_to_counted(str)->count, aa_str_kref); 119 : : } 120 : : 121 : : 122 : : /* struct aa_policy - common part of both namespaces and profiles 123 : : * @name: name of the object 124 : : * @hname - The hierarchical name 125 : : * @list: list policy object is on 126 : : * @profiles: head of the profiles list contained in the object 127 : : */ 128 : : struct aa_policy { 129 : : const char *name; 130 : : __counted char *hname; 131 : : struct list_head list; 132 : : struct list_head profiles; 133 : : }; 134 : : 135 : : /** 136 : : * basename - find the last component of an hname 137 : : * @name: hname to find the base profile name component of (NOT NULL) 138 : : * 139 : : * Returns: the tail (base profile name) name component of an hname 140 : : */ 141 : 0 : static inline const char *basename(const char *hname) 142 : : { 143 : : char *split; 144 : : 145 : 0 : hname = strim((char *)hname); 146 : 0 : for (split = strstr(hname, "//"); split; split = strstr(hname, "//")) 147 : 0 : hname = split + 2; 148 : : 149 : 0 : return hname; 150 : : } 151 : : 152 : : /** 153 : : * __policy_find - find a policy by @name on a policy list 154 : : * @head: list to search (NOT NULL) 155 : : * @name: name to search for (NOT NULL) 156 : : * 157 : : * Requires: rcu_read_lock be held 158 : : * 159 : : * Returns: unrefcounted policy that match @name or NULL if not found 160 : : */ 161 : : static inline struct aa_policy *__policy_find(struct list_head *head, 162 : : const char *name) 163 : : { 164 : : struct aa_policy *policy; 165 : : 166 : : list_for_each_entry_rcu(policy, head, list) { 167 : : if (!strcmp(policy->name, name)) 168 : : return policy; 169 : : } 170 : : return NULL; 171 : : } 172 : : 173 : : /** 174 : : * __policy_strn_find - find a policy that's name matches @len chars of @str 175 : : * @head: list to search (NOT NULL) 176 : : * @str: string to search for (NOT NULL) 177 : : * @len: length of match required 178 : : * 179 : : * Requires: rcu_read_lock be held 180 : : * 181 : : * Returns: unrefcounted policy that match @str or NULL if not found 182 : : * 183 : : * if @len == strlen(@strlen) then this is equiv to __policy_find 184 : : * other wise it allows searching for policy by a partial match of name 185 : : */ 186 : 0 : static inline struct aa_policy *__policy_strn_find(struct list_head *head, 187 : : const char *str, int len) 188 : : { 189 : : struct aa_policy *policy; 190 : : 191 : 0 : list_for_each_entry_rcu(policy, head, list) { 192 : 0 : if (aa_strneq(policy->name, str, len)) 193 : 0 : return policy; 194 : : } 195 : : 196 : : return NULL; 197 : : } 198 : : 199 : : bool aa_policy_init(struct aa_policy *policy, const char *prefix, 200 : : const char *name, gfp_t gfp); 201 : : void aa_policy_destroy(struct aa_policy *policy); 202 : : 203 : : 204 : : /* 205 : : * fn_label_build - abstract out the build of a label transition 206 : : * @L: label the transition is being computed for 207 : : * @P: profile parameter derived from L by this macro, can be passed to FN 208 : : * @GFP: memory allocation type to use 209 : : * @FN: fn to call for each profile transition. @P is set to the profile 210 : : * 211 : : * Returns: new label on success 212 : : * ERR_PTR if build @FN fails 213 : : * NULL if label_build fails due to low memory conditions 214 : : * 215 : : * @FN must return a label or ERR_PTR on failure. NULL is not allowed 216 : : */ 217 : : #define fn_label_build(L, P, GFP, FN) \ 218 : : ({ \ 219 : : __label__ __cleanup, __done; \ 220 : : struct aa_label *__new_; \ 221 : : \ 222 : : if ((L)->size > 1) { \ 223 : : /* TODO: add cache of transitions already done */ \ 224 : : struct label_it __i; \ 225 : : int __j, __k, __count; \ 226 : : DEFINE_VEC(label, __lvec); \ 227 : : DEFINE_VEC(profile, __pvec); \ 228 : : if (vec_setup(label, __lvec, (L)->size, (GFP))) { \ 229 : : __new_ = NULL; \ 230 : : goto __done; \ 231 : : } \ 232 : : __j = 0; \ 233 : : label_for_each(__i, (L), (P)) { \ 234 : : __new_ = (FN); \ 235 : : AA_BUG(!__new_); \ 236 : : if (IS_ERR(__new_)) \ 237 : : goto __cleanup; \ 238 : : __lvec[__j++] = __new_; \ 239 : : } \ 240 : : for (__j = __count = 0; __j < (L)->size; __j++) \ 241 : : __count += __lvec[__j]->size; \ 242 : : if (!vec_setup(profile, __pvec, __count, (GFP))) { \ 243 : : for (__j = __k = 0; __j < (L)->size; __j++) { \ 244 : : label_for_each(__i, __lvec[__j], (P)) \ 245 : : __pvec[__k++] = aa_get_profile(P); \ 246 : : } \ 247 : : __count -= aa_vec_unique(__pvec, __count, 0); \ 248 : : if (__count > 1) { \ 249 : : __new_ = aa_vec_find_or_create_label(__pvec,\ 250 : : __count, (GFP)); \ 251 : : /* only fails if out of Mem */ \ 252 : : if (!__new_) \ 253 : : __new_ = NULL; \ 254 : : } else \ 255 : : __new_ = aa_get_label(&__pvec[0]->label); \ 256 : : vec_cleanup(profile, __pvec, __count); \ 257 : : } else \ 258 : : __new_ = NULL; \ 259 : : __cleanup: \ 260 : : vec_cleanup(label, __lvec, (L)->size); \ 261 : : } else { \ 262 : : (P) = labels_profile(L); \ 263 : : __new_ = (FN); \ 264 : : } \ 265 : : __done: \ 266 : : if (!__new_) \ 267 : : AA_DEBUG("label build failed\n"); \ 268 : : (__new_); \ 269 : : }) 270 : : 271 : : 272 : : #define __fn_build_in_ns(NS, P, NS_FN, OTHER_FN) \ 273 : : ({ \ 274 : : struct aa_label *__new; \ 275 : : if ((P)->ns != (NS)) \ 276 : : __new = (OTHER_FN); \ 277 : : else \ 278 : : __new = (NS_FN); \ 279 : : (__new); \ 280 : : }) 281 : : 282 : : #define fn_label_build_in_ns(L, P, GFP, NS_FN, OTHER_FN) \ 283 : : ({ \ 284 : : fn_label_build((L), (P), (GFP), \ 285 : : __fn_build_in_ns(labels_ns(L), (P), (NS_FN), (OTHER_FN))); \ 286 : : }) 287 : : 288 : : #endif /* __AA_LIB_H */