Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux...
[linux-block.git] / security / apparmor / lib.c
CommitLineData
cdff2642
JJ
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-2010 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
3b0aaf58 15#include <linux/ctype.h>
b7f080cf 16#include <linux/mm.h>
cdff2642
JJ
17#include <linux/slab.h>
18#include <linux/string.h>
19#include <linux/vmalloc.h>
20
21#include "include/audit.h"
32c3df63 22#include "include/apparmor.h"
12557dcb 23#include "include/lib.h"
fc7e0b26 24#include "include/perms.h"
fe6bb31f 25#include "include/policy.h"
cdff2642 26
2d679f3c 27struct aa_perms nullperms;
aa9aeea8
JJ
28struct aa_perms allperms = { .allow = ALL_PERMS_MASK,
29 .quiet = ALL_PERMS_MASK,
30 .hide = ALL_PERMS_MASK };
31
cdff2642
JJ
32/**
33 * aa_split_fqname - split a fqname into a profile and namespace name
34 * @fqname: a full qualified name in namespace profile format (NOT NULL)
35 * @ns_name: pointer to portion of the string containing the ns name (NOT NULL)
36 *
37 * Returns: profile name or NULL if one is not specified
38 *
39 * Split a namespace name from a profile name (see policy.c for naming
40 * description). If a portion of the name is missing it returns NULL for
41 * that portion.
42 *
43 * NOTE: may modify the @fqname string. The pointers returned point
44 * into the @fqname string.
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], ':');
04ccd53f 53 *ns_name = skip_spaces(&name[1]);
cdff2642
JJ
54 if (split) {
55 /* overwrite ':' with \0 */
2654bfbc
JJ
56 *split++ = 0;
57 if (strncmp(split, "//", 2) == 0)
58 split += 2;
59 name = skip_spaces(split);
cdff2642
JJ
60 } else
61 /* a ns name without a following profile is allowed */
62 name = NULL;
cdff2642
JJ
63 }
64 if (name && *name == 0)
65 name = NULL;
66
67 return name;
68}
69
3b0aaf58
JJ
70/**
71 * skipn_spaces - Removes leading whitespace from @str.
72 * @str: The string to be stripped.
73 *
74 * Returns a pointer to the first non-whitespace character in @str.
75 * if all whitespace will return NULL
76 */
77
b91deb9d 78const char *skipn_spaces(const char *str, size_t n)
3b0aaf58
JJ
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 /* 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
cdff2642
JJ
122/**
123 * aa_info_message - log a none profile related status message
124 * @str: message to log
125 */
126void aa_info_message(const char *str)
127{
128 if (audit_enabled) {
ef88a7ac
JJ
129 DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, NULL);
130
131 aad(&sa)->info = str;
cdff2642
JJ
132 aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL);
133 }
134 printk(KERN_INFO "AppArmor: %s\n", str);
135}
136
a1bd627b
JJ
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
e53cfe6c
JJ
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 * aa_perm_mask_to_str - convert a perm mask to its short string
200 * @str: character buffer to store string in (at least 10 characters)
201 * @mask: permission mask to convert
202 */
203void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask)
204{
205 unsigned int i, perm = 1;
206
207 for (i = 0; i < 32; perm <<= 1, i++) {
208 if (mask & perm)
209 *str++ = chrs[i];
210 }
211 *str = '\0';
212}
213
aa9aeea8
JJ
214void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask)
215{
216 const char *fmt = "%s";
217 unsigned int i, perm = 1;
218 bool prev = false;
219
220 for (i = 0; i < 32; perm <<= 1, i++) {
221 if (mask & perm) {
222 audit_log_format(ab, fmt, names[i]);
223 if (!prev) {
224 prev = true;
225 fmt = " %s";
226 }
227 }
228 }
229}
230
231void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
232 u32 chrsmask, const char **names, u32 namesmask)
233{
234 char str[33];
235
236 audit_log_format(ab, "\"");
237 if ((mask & chrsmask) && chrs) {
238 aa_perm_mask_to_str(str, chrs, mask & chrsmask);
239 mask &= ~chrsmask;
240 audit_log_format(ab, "%s", str);
241 if (mask & namesmask)
242 audit_log_format(ab, " ");
243 }
244 if ((mask & namesmask) && names)
245 aa_audit_perm_names(ab, names, mask & namesmask);
246 audit_log_format(ab, "\"");
247}
248
637f688d
JJ
249/**
250 * aa_audit_perms_cb - generic callback fn for auditing perms
251 * @ab: audit buffer (NOT NULL)
252 * @va: audit struct to audit values of (NOT NULL)
253 */
254static void aa_audit_perms_cb(struct audit_buffer *ab, void *va)
255{
256 struct common_audit_data *sa = va;
257
258 if (aad(sa)->request) {
259 audit_log_format(ab, " requested_mask=");
260 aa_audit_perm_mask(ab, aad(sa)->request, aa_file_perm_chrs,
261 PERMS_CHRS_MASK, aa_file_perm_names,
262 PERMS_NAMES_MASK);
263 }
264 if (aad(sa)->denied) {
265 audit_log_format(ab, "denied_mask=");
266 aa_audit_perm_mask(ab, aad(sa)->denied, aa_file_perm_chrs,
267 PERMS_CHRS_MASK, aa_file_perm_names,
268 PERMS_NAMES_MASK);
269 }
270 audit_log_format(ab, " peer=");
271 aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer,
272 FLAGS_NONE, GFP_ATOMIC);
273}
274
aa9aeea8
JJ
275/**
276 * aa_apply_modes_to_perms - apply namespace and profile flags to perms
277 * @profile: that perms where computed from
278 * @perms: perms to apply mode modifiers to
279 *
280 * TODO: split into profile and ns based flags for when accumulating perms
281 */
282void aa_apply_modes_to_perms(struct aa_profile *profile, struct aa_perms *perms)
283{
284 switch (AUDIT_MODE(profile)) {
285 case AUDIT_ALL:
286 perms->audit = ALL_PERMS_MASK;
287 /* fall through */
288 case AUDIT_NOQUIET:
289 perms->quiet = 0;
290 break;
291 case AUDIT_QUIET:
292 perms->audit = 0;
293 /* fall through */
294 case AUDIT_QUIET_DENIED:
295 perms->quiet = ALL_PERMS_MASK;
296 break;
297 }
298
299 if (KILL_MODE(profile))
300 perms->kill = ALL_PERMS_MASK;
301 else if (COMPLAIN_MODE(profile))
302 perms->complain = ALL_PERMS_MASK;
303/*
304 * TODO:
305 * else if (PROMPT_MODE(profile))
306 * perms->prompt = ALL_PERMS_MASK;
307 */
308}
309
310static u32 map_other(u32 x)
311{
312 return ((x & 0x3) << 8) | /* SETATTR/GETATTR */
313 ((x & 0x1c) << 18) | /* ACCEPT/BIND/LISTEN */
314 ((x & 0x60) << 19); /* SETOPT/GETOPT */
315}
316
317void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
318 struct aa_perms *perms)
319{
320 perms->deny = 0;
321 perms->kill = perms->stop = 0;
322 perms->complain = perms->cond = 0;
323 perms->hide = 0;
324 perms->prompt = 0;
325 perms->allow = dfa_user_allow(dfa, state);
326 perms->audit = dfa_user_audit(dfa, state);
327 perms->quiet = dfa_user_quiet(dfa, state);
328
329 /* for v5 perm mapping in the policydb, the other set is used
330 * to extend the general perm set
331 */
332 perms->allow |= map_other(dfa_other_allow(dfa, state));
333 perms->audit |= map_other(dfa_other_audit(dfa, state));
334 perms->quiet |= map_other(dfa_other_quiet(dfa, state));
335// perms->xindex = dfa_user_xindex(dfa, state);
336}
337
637f688d
JJ
338/**
339 * aa_perms_accum_raw - accumulate perms with out masking off overlapping perms
340 * @accum - perms struct to accumulate into
341 * @addend - perms struct to add to @accum
342 */
343void aa_perms_accum_raw(struct aa_perms *accum, struct aa_perms *addend)
344{
345 accum->deny |= addend->deny;
346 accum->allow &= addend->allow & ~addend->deny;
347 accum->audit |= addend->audit & addend->allow;
348 accum->quiet &= addend->quiet & ~addend->allow;
349 accum->kill |= addend->kill & ~addend->allow;
350 accum->stop |= addend->stop & ~addend->allow;
351 accum->complain |= addend->complain & ~addend->allow & ~addend->deny;
352 accum->cond |= addend->cond & ~addend->allow & ~addend->deny;
353 accum->hide &= addend->hide & ~addend->allow;
354 accum->prompt |= addend->prompt & ~addend->allow & ~addend->deny;
355}
356
357/**
358 * aa_perms_accum - accumulate perms, masking off overlapping perms
359 * @accum - perms struct to accumulate into
360 * @addend - perms struct to add to @accum
361 */
362void aa_perms_accum(struct aa_perms *accum, struct aa_perms *addend)
363{
364 accum->deny |= addend->deny;
365 accum->allow &= addend->allow & ~accum->deny;
366 accum->audit |= addend->audit & accum->allow;
367 accum->quiet &= addend->quiet & ~accum->allow;
368 accum->kill |= addend->kill & ~accum->allow;
369 accum->stop |= addend->stop & ~accum->allow;
370 accum->complain |= addend->complain & ~accum->allow & ~accum->deny;
371 accum->cond |= addend->cond & ~accum->allow & ~accum->deny;
372 accum->hide &= addend->hide & ~accum->allow;
373 accum->prompt |= addend->prompt & ~accum->allow & ~accum->deny;
374}
375
376void aa_profile_match_label(struct aa_profile *profile, struct aa_label *label,
377 int type, u32 request, struct aa_perms *perms)
378{
379 /* TODO: doesn't yet handle extended types */
380 unsigned int state;
381
382 state = aa_dfa_next(profile->policy.dfa,
383 profile->policy.start[AA_CLASS_LABEL],
384 type);
385 aa_label_match(profile, label, state, false, request, perms);
386}
387
388
389/* currently unused */
390int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target,
391 u32 request, int type, u32 *deny,
392 struct common_audit_data *sa)
393{
394 struct aa_perms perms;
395
396 aad(sa)->label = &profile->label;
397 aad(sa)->peer = &target->label;
398 aad(sa)->request = request;
399
400 aa_profile_match_label(profile, &target->label, type, request, &perms);
401 aa_apply_modes_to_perms(profile, &perms);
402 *deny |= request & perms.deny;
403 return aa_check_perms(profile, &perms, request, sa, aa_audit_perms_cb);
404}
405
406/**
407 * aa_check_perms - do audit mode selection based on perms set
408 * @profile: profile being checked
409 * @perms: perms computed for the request
410 * @request: requested perms
411 * @deny: Returns: explicit deny set
412 * @sa: initialized audit structure (MAY BE NULL if not auditing)
413 * @cb: callback fn for tpye specific fields (MAY BE NULL)
414 *
415 * Returns: 0 if permission else error code
416 *
417 * Note: profile audit modes need to be set before calling by setting the
418 * perm masks appropriately.
419 *
420 * If not auditing then complain mode is not enabled and the
421 * error code will indicate whether there was an explicit deny
422 * with a positive value.
423 */
424int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms,
425 u32 request, struct common_audit_data *sa,
426 void (*cb)(struct audit_buffer *, void *))
427{
428 int type, error;
429 bool stop = false;
430 u32 denied = request & (~perms->allow | perms->deny);
431
432 if (likely(!denied)) {
433 /* mask off perms that are not being force audited */
434 request &= perms->audit;
435 if (!request || !sa)
436 return 0;
437
438 type = AUDIT_APPARMOR_AUDIT;
439 error = 0;
440 } else {
441 error = -EACCES;
442
443 if (denied & perms->kill)
444 type = AUDIT_APPARMOR_KILL;
445 else if (denied == (denied & perms->complain))
446 type = AUDIT_APPARMOR_ALLOWED;
447 else
448 type = AUDIT_APPARMOR_DENIED;
449
450 if (denied & perms->stop)
451 stop = true;
452 if (denied == (denied & perms->hide))
453 error = -ENOENT;
454
455 denied &= ~perms->quiet;
456 if (!sa || !denied)
457 return error;
458 }
459
460 if (sa) {
461 aad(sa)->label = &profile->label;
462 aad(sa)->request = request;
463 aad(sa)->denied = denied;
464 aad(sa)->error = error;
465 aa_audit_msg(type, sa, cb);
466 }
467
468 if (type == AUDIT_APPARMOR_ALLOWED)
469 error = 0;
470
471 return error;
472}
473
474
fe6bb31f
JJ
475/**
476 * aa_policy_init - initialize a policy structure
477 * @policy: policy to initialize (NOT NULL)
478 * @prefix: prefix name if any is required. (MAYBE NULL)
479 * @name: name of the policy, init will make a copy of it (NOT NULL)
a1bd627b 480 * @gfp: allocation mode
fe6bb31f
JJ
481 *
482 * Note: this fn creates a copy of strings passed in
483 *
484 * Returns: true if policy init successful
485 */
486bool aa_policy_init(struct aa_policy *policy, const char *prefix,
d102d895 487 const char *name, gfp_t gfp)
fe6bb31f 488{
a1bd627b
JJ
489 char *hname;
490
fe6bb31f
JJ
491 /* freed by policy_free */
492 if (prefix) {
a1bd627b
JJ
493 hname = aa_str_alloc(strlen(prefix) + strlen(name) + 3, gfp);
494 if (hname)
495 sprintf(hname, "%s//%s", prefix, name);
496 } else {
497 hname = aa_str_alloc(strlen(name) + 1, gfp);
498 if (hname)
499 strcpy(hname, name);
500 }
501 if (!hname)
b9c42ac7 502 return false;
a1bd627b 503 policy->hname = hname;
fe6bb31f 504 /* base.name is a substring of fqname */
d102d895 505 policy->name = basename(policy->hname);
fe6bb31f
JJ
506 INIT_LIST_HEAD(&policy->list);
507 INIT_LIST_HEAD(&policy->profiles);
508
b9c42ac7 509 return true;
fe6bb31f
JJ
510}
511
512/**
513 * aa_policy_destroy - free the elements referenced by @policy
514 * @policy: policy that is to have its elements freed (NOT NULL)
515 */
516void aa_policy_destroy(struct aa_policy *policy)
517{
5fd1b95f
JJ
518 AA_BUG(on_list_rcu(&policy->profiles));
519 AA_BUG(on_list_rcu(&policy->list));
fe6bb31f
JJ
520
521 /* don't free name as its a subset of hname */
a1bd627b 522 aa_put_str(policy->hname);
fe6bb31f 523}