]>
Commit | Line | Data |
---|---|---|
12557dcb JJ |
1 | /* |
2 | * AppArmor security module | |
3 | * | |
4 | * This file contains AppArmor lib definitions | |
5 | * | |
6 | * 2017 Canonical Ltd. | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public License as | |
10 | * published by the Free Software Foundation, version 2 of the | |
11 | * License. | |
12 | */ | |
13 | ||
14 | #ifndef __AA_LIB_H | |
15 | #define __AA_LIB_H | |
16 | ||
17 | #include <linux/slab.h> | |
18 | #include <linux/fs.h> | |
19 | ||
20 | #include "match.h" | |
21 | ||
22 | /* | |
23 | * DEBUG remains global (no per profile flag) since it is mostly used in sysctl | |
24 | * which is not related to profile accesses. | |
25 | */ | |
26 | ||
680cd62e JJ |
27 | #define DEBUG_ON (aa_g_debug) |
28 | #define dbg_printk(__fmt, __args...) pr_debug(__fmt, ##__args) | |
12557dcb JJ |
29 | #define AA_DEBUG(fmt, args...) \ |
30 | do { \ | |
680cd62e | 31 | if (DEBUG_ON) \ |
12557dcb JJ |
32 | pr_debug_ratelimited("AppArmor: " fmt, ##args); \ |
33 | } while (0) | |
34 | ||
680cd62e JJ |
35 | #define AA_WARN(X) WARN((X), "APPARMOR WARN %s: %s\n", __func__, #X) |
36 | ||
37 | #define AA_BUG(X, args...) AA_BUG_FMT((X), "" args) | |
38 | #ifdef CONFIG_SECURITY_APPARMOR_DEBUG_ASSERTS | |
39 | #define AA_BUG_FMT(X, fmt, args...) \ | |
40 | WARN((X), "AppArmor WARN %s: (" #X "): " fmt, __func__, ##args) | |
41 | #else | |
42 | #define AA_BUG_FMT(X, fmt, args...) | |
43 | #endif | |
44 | ||
12557dcb JJ |
45 | #define AA_ERROR(fmt, args...) \ |
46 | pr_err_ratelimited("AppArmor: " fmt, ##args) | |
47 | ||
48 | /* Flag indicating whether initialization completed */ | |
545de8fe | 49 | extern int apparmor_initialized; |
12557dcb JJ |
50 | |
51 | /* fn's in lib */ | |
b91deb9d | 52 | const char *skipn_spaces(const char *str, size_t n); |
12557dcb | 53 | char *aa_split_fqname(char *args, char **ns_name); |
3b0aaf58 JJ |
54 | const char *aa_splitn_fqname(const char *fqname, size_t n, const char **ns_name, |
55 | size_t *ns_len); | |
12557dcb | 56 | void aa_info_message(const char *str); |
12557dcb | 57 | |
12557dcb JJ |
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 | static inline bool aa_strneq(const char *str, const char *sub, int len) | |
67 | { | |
68 | 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 | return aa_dfa_next(dfa, start, 0); | |
85 | } | |
86 | ||
efeee83a | 87 | static inline bool path_mediated_fs(struct dentry *dentry) |
12557dcb | 88 | { |
1751e8a6 | 89 | return !(dentry->d_sb->s_flags & SB_NOUSER); |
12557dcb JJ |
90 | } |
91 | ||
a1bd627b JJ |
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 | 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 | if (str) | |
118 | kref_put(&str_to_counted(str)->count, aa_str_kref); | |
119 | } | |
120 | ||
121 | ||
fe6bb31f JJ |
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 { | |
bbe4a7c8 | 129 | const char *name; |
a1bd627b | 130 | __counted char *hname; |
fe6bb31f JJ |
131 | struct list_head list; |
132 | struct list_head profiles; | |
133 | }; | |
134 | ||
135 | /** | |
6e474e30 | 136 | * basename - find the last component of an hname |
fe6bb31f JJ |
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 | */ | |
6e474e30 | 141 | static inline const char *basename(const char *hname) |
fe6bb31f JJ |
142 | { |
143 | char *split; | |
144 | ||
145 | hname = strim((char *)hname); | |
146 | for (split = strstr(hname, "//"); split; split = strstr(hname, "//")) | |
147 | hname = split + 2; | |
148 | ||
149 | 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 | 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 | list_for_each_entry_rcu(policy, head, list) { | |
192 | if (aa_strneq(policy->name, str, len)) | |
193 | return policy; | |
194 | } | |
195 | ||
196 | return NULL; | |
197 | } | |
198 | ||
199 | bool aa_policy_init(struct aa_policy *policy, const char *prefix, | |
d102d895 | 200 | const char *name, gfp_t gfp); |
fe6bb31f JJ |
201 | void aa_policy_destroy(struct aa_policy *policy); |
202 | ||
93c98a48 JJ |
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 */ |