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