1
2
3
4
5
6
7
8
9
10
11
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
24
25
26
27#ifdef CONFIG_SMP
28#define write_is_locked(X) !write_can_lock(X)
29#else
30#define write_is_locked(X) (1)
31#endif
32
33
34
35
36
37
38#define DEBUG_ON (aa_g_debug)
39#define dbg_printk(__fmt, __args...) pr_debug(__fmt, ##__args)
40#define AA_DEBUG(fmt, args...) \
41 do { \
42 if (DEBUG_ON) \
43 pr_debug_ratelimited("AppArmor: " fmt, ##args); \
44 } while (0)
45
46#define AA_WARN(X) WARN((X), "APPARMOR WARN %s: %s\n", __func__, #X)
47
48#define AA_BUG(X, args...) AA_BUG_FMT((X), "" args)
49#ifdef CONFIG_SECURITY_APPARMOR_DEBUG_ASSERTS
50#define AA_BUG_FMT(X, fmt, args...) \
51 WARN((X), "AppArmor WARN %s: (" #X "): " fmt, __func__, ##args)
52#else
53#define AA_BUG_FMT(X, fmt, args...)
54#endif
55
56#define AA_ERROR(fmt, args...) \
57 pr_err_ratelimited("AppArmor: " fmt, ##args)
58
59
60extern int apparmor_initialized;
61
62
63const char *skipn_spaces(const char *str, size_t n);
64char *aa_split_fqname(char *args, char **ns_name);
65const char *aa_splitn_fqname(const char *fqname, size_t n, const char **ns_name,
66 size_t *ns_len);
67void aa_info_message(const char *str);
68
69
70
71
72
73
74
75
76
77static inline bool aa_strneq(const char *str, const char *sub, int len)
78{
79 return !strncmp(str, sub, len) && !str[len];
80}
81
82
83
84
85
86
87
88
89
90
91static inline unsigned int aa_dfa_null_transition(struct aa_dfa *dfa,
92 unsigned int start)
93{
94
95 return aa_dfa_next(dfa, start, 0);
96}
97
98static inline bool path_mediated_fs(struct dentry *dentry)
99{
100 return !(dentry->d_sb->s_flags & MS_NOUSER);
101}
102
103
104struct counted_str {
105 struct kref count;
106 char name[];
107};
108
109#define str_to_counted(str) \
110 ((struct counted_str *)(str - offsetof(struct counted_str, name)))
111
112#define __counted
113
114void aa_str_kref(struct kref *kref);
115char *aa_str_alloc(int size, gfp_t gfp);
116
117
118static inline __counted char *aa_get_str(__counted char *str)
119{
120 if (str)
121 kref_get(&(str_to_counted(str)->count));
122
123 return str;
124}
125
126static inline void aa_put_str(__counted char *str)
127{
128 if (str)
129 kref_put(&str_to_counted(str)->count, aa_str_kref);
130}
131
132
133
134
135
136
137
138
139struct aa_policy {
140 const char *name;
141 __counted char *hname;
142 struct list_head list;
143 struct list_head profiles;
144};
145
146
147
148
149
150
151
152static inline const char *basename(const char *hname)
153{
154 char *split;
155
156 hname = strim((char *)hname);
157 for (split = strstr(hname, "//"); split; split = strstr(hname, "//"))
158 hname = split + 2;
159
160 return hname;
161}
162
163
164
165
166
167
168
169
170
171
172static inline struct aa_policy *__policy_find(struct list_head *head,
173 const char *name)
174{
175 struct aa_policy *policy;
176
177 list_for_each_entry_rcu(policy, head, list) {
178 if (!strcmp(policy->name, name))
179 return policy;
180 }
181 return NULL;
182}
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197static inline struct aa_policy *__policy_strn_find(struct list_head *head,
198 const char *str, int len)
199{
200 struct aa_policy *policy;
201
202 list_for_each_entry_rcu(policy, head, list) {
203 if (aa_strneq(policy->name, str, len))
204 return policy;
205 }
206
207 return NULL;
208}
209
210bool aa_policy_init(struct aa_policy *policy, const char *prefix,
211 const char *name, gfp_t gfp);
212void aa_policy_destroy(struct aa_policy *policy);
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228#define fn_label_build(L, P, GFP, FN) \
229({ \
230 __label__ __cleanup, __done; \
231 struct aa_label *__new_; \
232 \
233 if ((L)->size > 1) { \
234 \
235 struct label_it __i; \
236 int __j, __k, __count; \
237 DEFINE_VEC(label, __lvec); \
238 DEFINE_VEC(profile, __pvec); \
239 if (vec_setup(label, __lvec, (L)->size, (GFP))) { \
240 __new_ = NULL; \
241 goto __done; \
242 } \
243 __j = 0; \
244 label_for_each(__i, (L), (P)) { \
245 __new_ = (FN); \
246 AA_BUG(!__new_); \
247 if (IS_ERR(__new_)) \
248 goto __cleanup; \
249 __lvec[__j++] = __new_; \
250 } \
251 for (__j = __count = 0; __j < (L)->size; __j++) \
252 __count += __lvec[__j]->size; \
253 if (!vec_setup(profile, __pvec, __count, (GFP))) { \
254 for (__j = __k = 0; __j < (L)->size; __j++) { \
255 label_for_each(__i, __lvec[__j], (P)) \
256 __pvec[__k++] = aa_get_profile(P); \
257 } \
258 __count -= aa_vec_unique(__pvec, __count, 0); \
259 if (__count > 1) { \
260 __new_ = aa_vec_find_or_create_label(__pvec,\
261 __count, (GFP)); \
262 \
263 if (!__new_) \
264 __new_ = NULL; \
265 } else \
266 __new_ = aa_get_label(&__pvec[0]->label); \
267 vec_cleanup(profile, __pvec, __count); \
268 } else \
269 __new_ = NULL; \
270__cleanup: \
271 vec_cleanup(label, __lvec, (L)->size); \
272 } else { \
273 (P) = labels_profile(L); \
274 __new_ = (FN); \
275 } \
276__done: \
277 if (!__new_) \
278 AA_DEBUG("label build failed\n"); \
279 (__new_); \
280})
281
282
283#define __fn_build_in_ns(NS, P, NS_FN, OTHER_FN) \
284({ \
285 struct aa_label *__new; \
286 if ((P)->ns != (NS)) \
287 __new = (OTHER_FN); \
288 else \
289 __new = (NS_FN); \
290 (__new); \
291})
292
293#define fn_label_build_in_ns(L, P, GFP, NS_FN, OTHER_FN) \
294({ \
295 fn_label_build((L), (P), (GFP), \
296 __fn_build_in_ns(labels_ns(L), (P), (NS_FN), (OTHER_FN))); \
297})
298
299#endif
300