]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blob - security/apparmor/lib.c
783d49859bca67d9b9edb7123b8c83e97480fc92
[mirror_ubuntu-zesty-kernel.git] / security / apparmor / lib.c
1 /*
2 * AppArmor security module
3 *
4 * This file contains basic common functions used in AppArmor
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2013 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
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/apparmor.h"
22 #include "include/audit.h"
23 #include "include/label.h"
24 #include "include/lib.h"
25 #include "include/perms.h"
26 #include "include/policy.h"
27
28 struct aa_perms nullperms;
29 struct aa_perms allperms = { .allow = ALL_PERMS_MASK,
30 .quiet = ALL_PERMS_MASK,
31 .hide = ALL_PERMS_MASK };
32
33 /**
34 * aa_split_fqname - split a fqname into a profile and namespace name
35 * @fqname: a full qualified name in namespace profile format (NOT NULL)
36 * @ns_name: pointer to portion of the string containing the ns name (NOT NULL)
37 *
38 * Returns: profile name or NULL if one is not specified
39 *
40 * Split a namespace name from a profile name (see policy.c for naming
41 * description). If a portion of the name is missing it returns NULL for
42 * that portion.
43 *
44 * NOTE: may modify the @fqname string. The pointers returned point
45 * into the @fqname string.
46 */
47 char *aa_split_fqname(char *fqname, char **ns_name)
48 {
49 char *name = strim(fqname);
50
51 *ns_name = NULL;
52 if (name[0] == ':') {
53 char *split = strchr(&name[1], ':');
54 *ns_name = skip_spaces(&name[1]);
55 if (split) {
56 /* overwrite ':' with \0 */
57 *split++ = 0;
58 if (strncmp(split, "//", 2) == 0)
59 split += 2;
60 name = skip_spaces(split);
61 } else
62 /* a ns name without a following profile is allowed */
63 name = NULL;
64 }
65 if (name && *name == 0)
66 name = NULL;
67
68 return name;
69 }
70
71 /**
72 * skipn_spaces - Removes leading whitespace from @str.
73 * @str: The string to be stripped.
74 *
75 * Returns a pointer to the first non-whitespace character in @str.
76 * if all whitespace will return NULL
77 */
78
79 const char *skipn_spaces(const char *str, size_t n)
80 {
81 for (;n && isspace(*str); --n)
82 ++str;
83 if (n)
84 return (char *)str;
85 return NULL;
86 }
87
88 const char *aa_splitn_fqname(const char *fqname, size_t n, const char **ns_name,
89 size_t *ns_len)
90 {
91 const char *end = fqname + n;
92 const char *name = skipn_spaces(fqname, n);
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 /* a ns name without a following profile is allowed */
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 * aa_info_message - log a none profile related status message
124 * @str: message to log
125 */
126 void aa_info_message(const char *str)
127 {
128 if (audit_enabled) {
129 DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, NULL);
130 aad(&sa)->info = str;
131 aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL);
132 }
133 printk(KERN_INFO "AppArmor: %s\n", str);
134 }
135
136 /**
137 * __aa_kvmalloc - do allocation preferring kmalloc but falling back to vmalloc
138 * @size: how many bytes of memory are required
139 * @flags: the type of memory to allocate (see kmalloc).
140 *
141 * Return: allocated buffer or NULL if failed
142 *
143 * It is possible that policy being loaded from the user is larger than
144 * what can be allocated by kmalloc, in those cases fall back to vmalloc.
145 */
146 void *__aa_kvmalloc(size_t size, gfp_t flags)
147 {
148 void *buffer = NULL;
149
150 if (size == 0)
151 return NULL;
152
153 /* do not attempt kmalloc if we need more than 16 pages at once */
154 if (size <= (16*PAGE_SIZE))
155 buffer = kmalloc(size, flags | GFP_NOIO | __GFP_NOWARN);
156 if (!buffer) {
157 if (flags & __GFP_ZERO)
158 buffer = vzalloc(size);
159 else
160 buffer = vmalloc(size);
161 }
162 return buffer;
163 }
164
165
166 __counted char *aa_str_alloc(int size, gfp_t gfp)
167 {
168 struct counted_str *str;
169 str = kmalloc(sizeof(struct counted_str) + size, gfp);
170 if (!str)
171 return NULL;
172
173 kref_init(&str->count);
174 return str->name;
175 }
176
177 void aa_str_kref(struct kref *kref)
178 {
179 kfree(container_of(kref, struct counted_str, count));
180 }
181
182
183 const char aa_file_perm_chrs[] = "xwracd km l ";
184 const char *aa_file_perm_names[] = {
185 "exec",
186 "write",
187 "read",
188 "append",
189
190 "create",
191 "delete",
192 "open",
193 "rename",
194
195 "setattr",
196 "getattr",
197 "setcred",
198 "getcred",
199
200 "chmod",
201 "chown",
202 "chgrp",
203 "lock",
204
205 "mmap",
206 "mprot",
207 "link",
208 "snapshot",
209
210 "unknown",
211 "unknown",
212 "unknown",
213 "unknown",
214
215 "unknown",
216 "unknown",
217 "unknown",
218 "unknown",
219
220 "stack",
221 "change_onexec",
222 "change_profile",
223 "change_hat",
224 };
225
226 /**
227 * aa_perm_mask_to_str - convert a perm mask to its short string
228 * @str: character buffer to store string in (at least 10 characters)
229 * @mask: permission mask to convert
230 */
231 void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask)
232 {
233 unsigned int i, perm = 1;
234 for (i = 0; i < 32; perm <<= 1, i++) {
235 if (mask & perm)
236 *str++ = chrs[i];
237 }
238 *str = '\0';
239 }
240
241 void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask)
242 {
243 const char *fmt = "%s";
244 unsigned int i, perm = 1;
245 bool prev = false;
246 for (i = 0; i < 32; perm <<= 1, i++) {
247 if (mask & perm) {
248 audit_log_format(ab, fmt, names[i]);
249 if (!prev) {
250 prev = true;
251 fmt = " %s";
252 }
253 }
254 }
255 }
256
257 void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
258 u32 chrsmask, const char **names, u32 namesmask)
259 {
260 char str[33];
261
262 audit_log_format(ab, "\"");
263 if ((mask & chrsmask) && chrs) {
264 aa_perm_mask_to_str(str, chrs, mask & chrsmask);
265 mask &= ~chrsmask;
266 audit_log_format(ab, "%s", str);
267 if (mask & namesmask)
268 audit_log_format(ab, " ");
269 }
270 if ((mask & namesmask) && names)
271 aa_audit_perm_names(ab, names, mask & namesmask);
272 audit_log_format(ab, "\"");
273 }
274
275 /**
276 * aa_audit_perms_cb - generic callback fn for auditing perms
277 * @ab: audit buffer (NOT NULL)
278 * @va: audit struct to audit values of (NOT NULL)
279 */
280 static void aa_audit_perms_cb(struct audit_buffer *ab, void *va)
281 {
282 struct common_audit_data *sa = va;
283
284 if (aad(sa)->request) {
285 audit_log_format(ab, " requested_mask=");
286 aa_audit_perm_mask(ab, aad(sa)->request, aa_file_perm_chrs,
287 PERMS_CHRS_MASK, aa_file_perm_names,
288 PERMS_NAMES_MASK);
289 }
290 if (aad(sa)->denied) {
291 audit_log_format(ab, "denied_mask=");
292 aa_audit_perm_mask(ab, aad(sa)->denied, aa_file_perm_chrs,
293 PERMS_CHRS_MASK, aa_file_perm_names,
294 PERMS_NAMES_MASK);
295 }
296 audit_log_format(ab, " peer=");
297 aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer,
298 FLAGS_NONE, GFP_ATOMIC);
299 }
300
301 /**
302 * aa_apply_modes_to_perms - apply namespace and profile flags to perms
303 * @profile: that perms where computed from
304 * @perms: perms to apply mode modifiers to
305 *
306 * TODO: split into profile and ns based flags for when accumulating perms
307 */
308 void aa_apply_modes_to_perms(struct aa_profile *profile, struct aa_perms *perms)
309 {
310 switch (AUDIT_MODE(profile)) {
311 case AUDIT_ALL:
312 perms->audit = ALL_PERMS_MASK;
313 /* fall through */
314 case AUDIT_NOQUIET:
315 perms->quiet = 0;
316 break;
317 case AUDIT_QUIET:
318 perms->audit = 0;
319 /* fall through */
320 case AUDIT_QUIET_DENIED:
321 perms->quiet = ALL_PERMS_MASK;
322 break;
323 }
324
325 if (KILL_MODE(profile))
326 perms->kill = ALL_PERMS_MASK;
327 else if (COMPLAIN_MODE(profile))
328 perms->complain = ALL_PERMS_MASK;
329 /* TODO:
330 else if (PROMPT_MODE(profile))
331 perms->prompt = ALL_PERMS_MASK;
332 */
333 }
334
335 static u32 map_other(u32 x)
336 {
337 return ((x & 0x3) << 8) | /* SETATTR/GETATTR */
338 ((x & 0x1c) << 18) | /* ACCEPT/BIND/LISTEN */
339 ((x & 0x60) << 19); /* SETOPT/GETOPT */
340 }
341
342 void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
343 struct aa_perms *perms)
344 {
345 perms->deny = 0;
346 perms->kill = perms->stop = 0;
347 perms->complain = perms->cond = 0;
348 perms->hide = 0;
349 perms->prompt = 0;
350 perms->allow = dfa_user_allow(dfa, state);
351 perms->audit = dfa_user_audit(dfa, state);
352 perms->quiet = dfa_user_quiet(dfa, state);
353
354 /* for v5 perm mapping in the policydb, the other set is used
355 * to extend the general perm set
356 */
357 perms->allow |= map_other(dfa_other_allow(dfa, state));
358 perms->audit |= map_other(dfa_other_audit(dfa, state));
359 perms->quiet |= map_other(dfa_other_quiet(dfa, state));
360 // perms->xindex = dfa_user_xindex(dfa, state);
361 }
362
363 /**
364 * aa_perms_accum_raw - accumulate perms with out masking off overlapping perms
365 * @accum - perms struct to accumulate into
366 * @addend - perms struct to add to @accum
367 */
368 void aa_perms_accum_raw(struct aa_perms *accum, struct aa_perms *addend)
369 {
370 accum->deny |= addend->deny;
371 accum->allow &= addend->allow & ~addend->deny;
372 accum->audit |= addend->audit & addend->allow;
373 accum->quiet &= addend->quiet & ~addend->allow;
374 accum->kill |= addend->kill & ~addend->allow;
375 accum->stop |= addend->stop & ~addend->allow;
376 accum->complain |= addend->complain & ~addend->allow & ~addend->deny;
377 accum->cond |= addend->cond & ~addend->allow & ~addend->deny;
378 accum->hide &= addend->hide & ~addend->allow;
379 accum->prompt |= addend->prompt & ~addend->allow & ~addend->deny;
380 }
381
382 /**
383 * aa_perms_accum - accumulate perms, masking off overlapping perms
384 * @accum - perms struct to accumulate into
385 * @addend - perms struct to add to @accum
386 */
387 void aa_perms_accum(struct aa_perms *accum, struct aa_perms *addend)
388 {
389 accum->deny |= addend->deny;
390 accum->allow &= addend->allow & ~accum->deny;
391 accum->audit |= addend->audit & accum->allow;
392 accum->quiet &= addend->quiet & ~accum->allow;
393 accum->kill |= addend->kill & ~accum->allow;
394 accum->stop |= addend->stop & ~accum->allow;
395 accum->complain |= addend->complain & ~accum->allow & ~accum->deny;
396 accum->cond |= addend->cond & ~accum->allow & ~accum->deny;
397 accum->hide &= addend->hide & ~accum->allow;
398 accum->prompt |= addend->prompt & ~accum->allow & ~accum->deny;
399 }
400
401 void aa_profile_match_label(struct aa_profile *profile, struct aa_label *label,
402 int type, u32 request, struct aa_perms *perms)
403 {
404 /* TODO: doesn't yet handle extended types */
405 unsigned int state;
406 state = aa_dfa_next(profile->policy.dfa,
407 profile->policy.start[AA_CLASS_LABEL],
408 type);
409 aa_label_match(profile, label, state, false, request, perms);
410 }
411
412
413 /* currently unused */
414 int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target,
415 u32 request, int type, u32 *deny,
416 struct common_audit_data *sa)
417 {
418 struct aa_perms perms;
419 aad(sa)->label = &profile->label;
420 aad(sa)->peer = &target->label;
421 aad(sa)->request = request;
422
423 aa_profile_match_label(profile, &target->label, type, request, &perms);
424 aa_apply_modes_to_perms(profile, &perms);
425 *deny |= request & perms.deny;
426 return aa_check_perms(profile, &perms, request, sa, aa_audit_perms_cb);
427 }
428
429 /**
430 * aa_check_perms - do audit mode selection based on perms set
431 * @profile: profile being checked
432 * @perms: perms computed for the request
433 * @request: requested perms
434 * @deny: Returns: explicit deny set
435 * @sa: initialized audit structure (MAY BE NULL if not auditing)
436 * @cb: callback fn for tpye specific fields (MAY BE NULL)
437 *
438 * Returns: 0 if permission else error code
439 *
440 * Note: profile audit modes need to be set before calling by setting the
441 * perm masks appropriately.
442 *
443 * If not auditing then complain mode is not enabled and the
444 * error code will indicate whether there was an explicit deny
445 * with a positive value.
446 */
447 int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms,
448 u32 request, struct common_audit_data *sa,
449 void (*cb) (struct audit_buffer *, void *))
450 {
451 int type, error;
452 bool stop = false;
453 u32 denied = request & (~perms->allow | perms->deny);
454 if (likely(!denied)) {
455 /* mask off perms that are not being force audited */
456 request &= perms->audit;
457 if (!request || !sa)
458 return 0;
459
460 type = AUDIT_APPARMOR_AUDIT;
461 error = 0;
462 } else {
463 error = -EACCES;
464
465 if (denied & perms->kill)
466 type = AUDIT_APPARMOR_KILL;
467 else if (denied == (denied & perms->complain))
468 type = AUDIT_APPARMOR_ALLOWED;
469 else
470 type = AUDIT_APPARMOR_DENIED;
471
472 if (denied & perms->stop)
473 stop = true;
474 if (denied == (denied & perms->hide))
475 error = -ENOENT;
476
477 denied &= ~perms->quiet;
478 if (!sa || !denied)
479 return error;
480 }
481
482 if (sa) {
483 aad(sa)->label = &profile->label;
484 aad(sa)->request = request;
485 aad(sa)->denied = denied;
486 aad(sa)->error = error;
487 aa_audit_msg(type, sa, cb);
488 }
489
490 if (type == AUDIT_APPARMOR_ALLOWED)
491 error = 0;
492
493 return error;
494 }
495
496 const char *aa_imode_name(umode_t mode)
497 {
498 switch(mode & S_IFMT) {
499 case S_IFSOCK:
500 return "sock";
501 case S_IFLNK:
502 return "link";
503 case S_IFREG:
504 return "reg";
505 case S_IFBLK:
506 return "blkdev";
507 case S_IFDIR:
508 return "dir";
509 case S_IFCHR:
510 return "chrdev";
511 case S_IFIFO:
512 return "fifo";
513 }
514 return "unknown";
515 }
516
517 /**
518 * aa_policy_init - initialize a policy structure
519 * @policy: policy to initialize (NOT NULL)
520 * @prefix: prefix name if any is required. (MAYBE NULL)
521 * @name: name of the policy, init will make a copy of it (NOT NULL)
522 * @gfp: allocation mode
523 *
524 * Note: this fn creates a copy of strings passed in
525 *
526 * Returns: true if policy init successful
527 */
528 bool aa_policy_init(struct aa_policy *policy, const char *prefix,
529 const char *name, gfp_t gfp)
530 {
531 char *hname;
532
533 /* freed by policy_free */
534 if (prefix) {
535 hname = aa_str_alloc(strlen(prefix) + strlen(name) + 3, gfp);
536 if (hname)
537 sprintf(hname, "%s//%s", prefix, name);
538 } else {
539 hname = aa_str_alloc(strlen(name) + 1, gfp);
540 if (hname)
541 strcpy(hname, name);
542 }
543 if (!hname)
544 return 0;
545 policy->hname = hname;
546 /* base.name is a substring of fqname */
547 policy->name = (char *) basename(policy->hname);
548 INIT_LIST_HEAD(&policy->list);
549 INIT_LIST_HEAD(&policy->profiles);
550
551 return 1;
552 }
553
554 /**
555 * aa_policy_destroy - free the elements referenced by @policy
556 * @policy: policy that is to have its elements freed (NOT NULL)
557 */
558 void aa_policy_destroy(struct aa_policy *policy)
559 {
560 AA_BUG(on_list_rcu(&policy->profiles));
561 AA_BUG(on_list_rcu(&policy->list));
562
563 /* don't free name as its a subset of hname */
564 aa_put_str(policy->hname);
565 }