This source file includes following definitions.
- aa_split_fqname
- skipn_spaces
- aa_splitn_fqname
- aa_info_message
- aa_str_alloc
- aa_str_kref
- aa_perm_mask_to_str
- aa_audit_perm_names
- aa_audit_perm_mask
- aa_audit_perms_cb
- aa_apply_modes_to_perms
- map_other
- aa_compute_perms
- aa_perms_accum_raw
- aa_perms_accum
- aa_profile_match_label
- aa_profile_label_perm
- aa_check_perms
- aa_policy_init
- aa_policy_destroy
1
2
3
4
5
6
7
8
9
10
11 #include <linux/ctype.h>
12 #include <linux/mm.h>
13 #include <linux/slab.h>
14 #include <linux/string.h>
15 #include <linux/vmalloc.h>
16
17 #include "include/audit.h"
18 #include "include/apparmor.h"
19 #include "include/lib.h"
20 #include "include/perms.h"
21 #include "include/policy.h"
22
23 struct aa_perms nullperms;
24 struct aa_perms allperms = { .allow = ALL_PERMS_MASK,
25 .quiet = ALL_PERMS_MASK,
26 .hide = ALL_PERMS_MASK };
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 char *aa_split_fqname(char *fqname, char **ns_name)
43 {
44 char *name = strim(fqname);
45
46 *ns_name = NULL;
47 if (name[0] == ':') {
48 char *split = strchr(&name[1], ':');
49 *ns_name = skip_spaces(&name[1]);
50 if (split) {
51
52 *split++ = 0;
53 if (strncmp(split, "//", 2) == 0)
54 split += 2;
55 name = skip_spaces(split);
56 } else
57
58 name = NULL;
59 }
60 if (name && *name == 0)
61 name = NULL;
62
63 return name;
64 }
65
66
67
68
69
70
71
72
73
74 const char *skipn_spaces(const char *str, size_t n)
75 {
76 for (; n && isspace(*str); --n)
77 ++str;
78 if (n)
79 return (char *)str;
80 return NULL;
81 }
82
83 const char *aa_splitn_fqname(const char *fqname, size_t n, const char **ns_name,
84 size_t *ns_len)
85 {
86 const char *end = fqname + n;
87 const char *name = skipn_spaces(fqname, n);
88
89 *ns_name = NULL;
90 *ns_len = 0;
91
92 if (!name)
93 return NULL;
94
95 if (name[0] == ':') {
96 char *split = strnchr(&name[1], end - &name[1], ':');
97 *ns_name = skipn_spaces(&name[1], end - &name[1]);
98 if (!*ns_name)
99 return NULL;
100 if (split) {
101 *ns_len = split - *ns_name;
102 if (*ns_len == 0)
103 *ns_name = NULL;
104 split++;
105 if (end - split > 1 && strncmp(split, "//", 2) == 0)
106 split += 2;
107 name = skipn_spaces(split, end - split);
108 } else {
109
110 name = NULL;
111 *ns_len = end - *ns_name;
112 }
113 }
114 if (name && *name == 0)
115 name = NULL;
116
117 return name;
118 }
119
120
121
122
123
124 void aa_info_message(const char *str)
125 {
126 if (audit_enabled) {
127 DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, NULL);
128
129 aad(&sa)->info = str;
130 aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL);
131 }
132 printk(KERN_INFO "AppArmor: %s\n", str);
133 }
134
135 __counted char *aa_str_alloc(int size, gfp_t gfp)
136 {
137 struct counted_str *str;
138
139 str = kmalloc(sizeof(struct counted_str) + size, gfp);
140 if (!str)
141 return NULL;
142
143 kref_init(&str->count);
144 return str->name;
145 }
146
147 void aa_str_kref(struct kref *kref)
148 {
149 kfree(container_of(kref, struct counted_str, count));
150 }
151
152
153 const char aa_file_perm_chrs[] = "xwracd km l ";
154 const char *aa_file_perm_names[] = {
155 "exec",
156 "write",
157 "read",
158 "append",
159
160 "create",
161 "delete",
162 "open",
163 "rename",
164
165 "setattr",
166 "getattr",
167 "setcred",
168 "getcred",
169
170 "chmod",
171 "chown",
172 "chgrp",
173 "lock",
174
175 "mmap",
176 "mprot",
177 "link",
178 "snapshot",
179
180 "unknown",
181 "unknown",
182 "unknown",
183 "unknown",
184
185 "unknown",
186 "unknown",
187 "unknown",
188 "unknown",
189
190 "stack",
191 "change_onexec",
192 "change_profile",
193 "change_hat",
194 };
195
196
197
198
199
200
201
202
203 void aa_perm_mask_to_str(char *str, size_t str_size, const char *chrs, u32 mask)
204 {
205 unsigned int i, perm = 1;
206 size_t num_chrs = strlen(chrs);
207
208 for (i = 0; i < num_chrs; perm <<= 1, i++) {
209 if (mask & perm) {
210
211 if (WARN_ON_ONCE(str_size <= 1))
212 break;
213
214 *str++ = chrs[i];
215 str_size--;
216 }
217 }
218 *str = '\0';
219 }
220
221 void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names,
222 u32 mask)
223 {
224 const char *fmt = "%s";
225 unsigned int i, perm = 1;
226 bool prev = false;
227
228 for (i = 0; i < 32; perm <<= 1, i++) {
229 if (mask & perm) {
230 audit_log_format(ab, fmt, names[i]);
231 if (!prev) {
232 prev = true;
233 fmt = " %s";
234 }
235 }
236 }
237 }
238
239 void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
240 u32 chrsmask, const char * const *names, u32 namesmask)
241 {
242 char str[33];
243
244 audit_log_format(ab, "\"");
245 if ((mask & chrsmask) && chrs) {
246 aa_perm_mask_to_str(str, sizeof(str), chrs, mask & chrsmask);
247 mask &= ~chrsmask;
248 audit_log_format(ab, "%s", str);
249 if (mask & namesmask)
250 audit_log_format(ab, " ");
251 }
252 if ((mask & namesmask) && names)
253 aa_audit_perm_names(ab, names, mask & namesmask);
254 audit_log_format(ab, "\"");
255 }
256
257
258
259
260
261
262 static void aa_audit_perms_cb(struct audit_buffer *ab, void *va)
263 {
264 struct common_audit_data *sa = va;
265
266 if (aad(sa)->request) {
267 audit_log_format(ab, " requested_mask=");
268 aa_audit_perm_mask(ab, aad(sa)->request, aa_file_perm_chrs,
269 PERMS_CHRS_MASK, aa_file_perm_names,
270 PERMS_NAMES_MASK);
271 }
272 if (aad(sa)->denied) {
273 audit_log_format(ab, "denied_mask=");
274 aa_audit_perm_mask(ab, aad(sa)->denied, aa_file_perm_chrs,
275 PERMS_CHRS_MASK, aa_file_perm_names,
276 PERMS_NAMES_MASK);
277 }
278 audit_log_format(ab, " peer=");
279 aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer,
280 FLAGS_NONE, GFP_ATOMIC);
281 }
282
283
284
285
286
287
288
289
290 void aa_apply_modes_to_perms(struct aa_profile *profile, struct aa_perms *perms)
291 {
292 switch (AUDIT_MODE(profile)) {
293 case AUDIT_ALL:
294 perms->audit = ALL_PERMS_MASK;
295
296 case AUDIT_NOQUIET:
297 perms->quiet = 0;
298 break;
299 case AUDIT_QUIET:
300 perms->audit = 0;
301
302 case AUDIT_QUIET_DENIED:
303 perms->quiet = ALL_PERMS_MASK;
304 break;
305 }
306
307 if (KILL_MODE(profile))
308 perms->kill = ALL_PERMS_MASK;
309 else if (COMPLAIN_MODE(profile))
310 perms->complain = ALL_PERMS_MASK;
311
312
313
314
315
316 }
317
318 static u32 map_other(u32 x)
319 {
320 return ((x & 0x3) << 8) |
321 ((x & 0x1c) << 18) |
322 ((x & 0x60) << 19);
323 }
324
325 void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
326 struct aa_perms *perms)
327 {
328 *perms = (struct aa_perms) {
329 .allow = dfa_user_allow(dfa, state),
330 .audit = dfa_user_audit(dfa, state),
331 .quiet = dfa_user_quiet(dfa, state),
332 };
333
334
335
336
337 perms->allow |= map_other(dfa_other_allow(dfa, state));
338 perms->audit |= map_other(dfa_other_audit(dfa, state));
339 perms->quiet |= map_other(dfa_other_quiet(dfa, state));
340
341 }
342
343
344
345
346
347
348 void aa_perms_accum_raw(struct aa_perms *accum, struct aa_perms *addend)
349 {
350 accum->deny |= addend->deny;
351 accum->allow &= addend->allow & ~addend->deny;
352 accum->audit |= addend->audit & addend->allow;
353 accum->quiet &= addend->quiet & ~addend->allow;
354 accum->kill |= addend->kill & ~addend->allow;
355 accum->stop |= addend->stop & ~addend->allow;
356 accum->complain |= addend->complain & ~addend->allow & ~addend->deny;
357 accum->cond |= addend->cond & ~addend->allow & ~addend->deny;
358 accum->hide &= addend->hide & ~addend->allow;
359 accum->prompt |= addend->prompt & ~addend->allow & ~addend->deny;
360 }
361
362
363
364
365
366
367 void aa_perms_accum(struct aa_perms *accum, struct aa_perms *addend)
368 {
369 accum->deny |= addend->deny;
370 accum->allow &= addend->allow & ~accum->deny;
371 accum->audit |= addend->audit & accum->allow;
372 accum->quiet &= addend->quiet & ~accum->allow;
373 accum->kill |= addend->kill & ~accum->allow;
374 accum->stop |= addend->stop & ~accum->allow;
375 accum->complain |= addend->complain & ~accum->allow & ~accum->deny;
376 accum->cond |= addend->cond & ~accum->allow & ~accum->deny;
377 accum->hide &= addend->hide & ~accum->allow;
378 accum->prompt |= addend->prompt & ~accum->allow & ~accum->deny;
379 }
380
381 void aa_profile_match_label(struct aa_profile *profile, struct aa_label *label,
382 int type, u32 request, struct aa_perms *perms)
383 {
384
385 unsigned int state;
386
387 state = aa_dfa_next(profile->policy.dfa,
388 profile->policy.start[AA_CLASS_LABEL],
389 type);
390 aa_label_match(profile, label, state, false, request, perms);
391 }
392
393
394
395 int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target,
396 u32 request, int type, u32 *deny,
397 struct common_audit_data *sa)
398 {
399 struct aa_perms perms;
400
401 aad(sa)->label = &profile->label;
402 aad(sa)->peer = &target->label;
403 aad(sa)->request = request;
404
405 aa_profile_match_label(profile, &target->label, type, request, &perms);
406 aa_apply_modes_to_perms(profile, &perms);
407 *deny |= request & perms.deny;
408 return aa_check_perms(profile, &perms, request, sa, aa_audit_perms_cb);
409 }
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429 int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms,
430 u32 request, struct common_audit_data *sa,
431 void (*cb)(struct audit_buffer *, void *))
432 {
433 int type, error;
434 u32 denied = request & (~perms->allow | perms->deny);
435
436 if (likely(!denied)) {
437
438 request &= perms->audit;
439 if (!request || !sa)
440 return 0;
441
442 type = AUDIT_APPARMOR_AUDIT;
443 error = 0;
444 } else {
445 error = -EACCES;
446
447 if (denied & perms->kill)
448 type = AUDIT_APPARMOR_KILL;
449 else if (denied == (denied & perms->complain))
450 type = AUDIT_APPARMOR_ALLOWED;
451 else
452 type = AUDIT_APPARMOR_DENIED;
453
454 if (denied == (denied & perms->hide))
455 error = -ENOENT;
456
457 denied &= ~perms->quiet;
458 if (!sa || !denied)
459 return error;
460 }
461
462 if (sa) {
463 aad(sa)->label = &profile->label;
464 aad(sa)->request = request;
465 aad(sa)->denied = denied;
466 aad(sa)->error = error;
467 aa_audit_msg(type, sa, cb);
468 }
469
470 if (type == AUDIT_APPARMOR_ALLOWED)
471 error = 0;
472
473 return error;
474 }
475
476
477
478
479
480
481
482
483
484
485
486
487
488 bool aa_policy_init(struct aa_policy *policy, const char *prefix,
489 const char *name, gfp_t gfp)
490 {
491 char *hname;
492
493
494 if (prefix) {
495 hname = aa_str_alloc(strlen(prefix) + strlen(name) + 3, gfp);
496 if (hname)
497 sprintf(hname, "%s//%s", prefix, name);
498 } else {
499 hname = aa_str_alloc(strlen(name) + 1, gfp);
500 if (hname)
501 strcpy(hname, name);
502 }
503 if (!hname)
504 return false;
505 policy->hname = hname;
506
507 policy->name = basename(policy->hname);
508 INIT_LIST_HEAD(&policy->list);
509 INIT_LIST_HEAD(&policy->profiles);
510
511 return true;
512 }
513
514
515
516
517
518 void aa_policy_destroy(struct aa_policy *policy)
519 {
520 AA_BUG(on_list_rcu(&policy->profiles));
521 AA_BUG(on_list_rcu(&policy->list));
522
523
524 aa_put_str(policy->hname);
525 }