Merge tag 'for-linus-4.15-rc4-tag' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.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-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
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
27 struct aa_perms nullperms;
28 struct aa_perms allperms = { .allow = ALL_PERMS_MASK,
29                              .quiet = ALL_PERMS_MASK,
30                              .hide = ALL_PERMS_MASK };
31
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  */
46 char *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                         /* overwrite ':' with \0 */
56                         *split++ = 0;
57                         if (strncmp(split, "//", 2) == 0)
58                                 split += 2;
59                         name = skip_spaces(split);
60                 } else
61                         /* a ns name without a following profile is allowed */
62                         name = NULL;
63         }
64         if (name && *name == 0)
65                 name = NULL;
66
67         return name;
68 }
69
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
78 const 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
87 const 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
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
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
149 void aa_str_kref(struct kref *kref)
150 {
151         kfree(container_of(kref, struct counted_str, count));
152 }
153
154
155 const char aa_file_perm_chrs[] = "xwracd         km l     ";
156 const 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  */
203 void 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
214 void 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
231 void 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
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  */
254 static 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
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  */
282 void 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
310 static 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
317 void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
318                       struct aa_perms *perms)
319 {
320         *perms = (struct aa_perms) {
321                 .allow = dfa_user_allow(dfa, state),
322                 .audit = dfa_user_audit(dfa, state),
323                 .quiet = dfa_user_quiet(dfa, state),
324         };
325
326         /* for v5 perm mapping in the policydb, the other set is used
327          * to extend the general perm set
328          */
329         perms->allow |= map_other(dfa_other_allow(dfa, state));
330         perms->audit |= map_other(dfa_other_audit(dfa, state));
331         perms->quiet |= map_other(dfa_other_quiet(dfa, state));
332 //      perms->xindex = dfa_user_xindex(dfa, state);
333 }
334
335 /**
336  * aa_perms_accum_raw - accumulate perms with out masking off overlapping perms
337  * @accum - perms struct to accumulate into
338  * @addend - perms struct to add to @accum
339  */
340 void aa_perms_accum_raw(struct aa_perms *accum, struct aa_perms *addend)
341 {
342         accum->deny |= addend->deny;
343         accum->allow &= addend->allow & ~addend->deny;
344         accum->audit |= addend->audit & addend->allow;
345         accum->quiet &= addend->quiet & ~addend->allow;
346         accum->kill |= addend->kill & ~addend->allow;
347         accum->stop |= addend->stop & ~addend->allow;
348         accum->complain |= addend->complain & ~addend->allow & ~addend->deny;
349         accum->cond |= addend->cond & ~addend->allow & ~addend->deny;
350         accum->hide &= addend->hide & ~addend->allow;
351         accum->prompt |= addend->prompt & ~addend->allow & ~addend->deny;
352 }
353
354 /**
355  * aa_perms_accum - accumulate perms, masking off overlapping perms
356  * @accum - perms struct to accumulate into
357  * @addend - perms struct to add to @accum
358  */
359 void aa_perms_accum(struct aa_perms *accum, struct aa_perms *addend)
360 {
361         accum->deny |= addend->deny;
362         accum->allow &= addend->allow & ~accum->deny;
363         accum->audit |= addend->audit & accum->allow;
364         accum->quiet &= addend->quiet & ~accum->allow;
365         accum->kill |= addend->kill & ~accum->allow;
366         accum->stop |= addend->stop & ~accum->allow;
367         accum->complain |= addend->complain & ~accum->allow & ~accum->deny;
368         accum->cond |= addend->cond & ~accum->allow & ~accum->deny;
369         accum->hide &= addend->hide & ~accum->allow;
370         accum->prompt |= addend->prompt & ~accum->allow & ~accum->deny;
371 }
372
373 void aa_profile_match_label(struct aa_profile *profile, struct aa_label *label,
374                             int type, u32 request, struct aa_perms *perms)
375 {
376         /* TODO: doesn't yet handle extended types */
377         unsigned int state;
378
379         state = aa_dfa_next(profile->policy.dfa,
380                             profile->policy.start[AA_CLASS_LABEL],
381                             type);
382         aa_label_match(profile, label, state, false, request, perms);
383 }
384
385
386 /* currently unused */
387 int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target,
388                           u32 request, int type, u32 *deny,
389                           struct common_audit_data *sa)
390 {
391         struct aa_perms perms;
392
393         aad(sa)->label = &profile->label;
394         aad(sa)->peer = &target->label;
395         aad(sa)->request = request;
396
397         aa_profile_match_label(profile, &target->label, type, request, &perms);
398         aa_apply_modes_to_perms(profile, &perms);
399         *deny |= request & perms.deny;
400         return aa_check_perms(profile, &perms, request, sa, aa_audit_perms_cb);
401 }
402
403 /**
404  * aa_check_perms - do audit mode selection based on perms set
405  * @profile: profile being checked
406  * @perms: perms computed for the request
407  * @request: requested perms
408  * @deny: Returns: explicit deny set
409  * @sa: initialized audit structure (MAY BE NULL if not auditing)
410  * @cb: callback fn for tpye specific fields (MAY BE NULL)
411  *
412  * Returns: 0 if permission else error code
413  *
414  * Note: profile audit modes need to be set before calling by setting the
415  *       perm masks appropriately.
416  *
417  *       If not auditing then complain mode is not enabled and the
418  *       error code will indicate whether there was an explicit deny
419  *       with a positive value.
420  */
421 int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms,
422                    u32 request, struct common_audit_data *sa,
423                    void (*cb)(struct audit_buffer *, void *))
424 {
425         int type, error;
426         u32 denied = request & (~perms->allow | perms->deny);
427
428         if (likely(!denied)) {
429                 /* mask off perms that are not being force audited */
430                 request &= perms->audit;
431                 if (!request || !sa)
432                         return 0;
433
434                 type = AUDIT_APPARMOR_AUDIT;
435                 error = 0;
436         } else {
437                 error = -EACCES;
438
439                 if (denied & perms->kill)
440                         type = AUDIT_APPARMOR_KILL;
441                 else if (denied == (denied & perms->complain))
442                         type = AUDIT_APPARMOR_ALLOWED;
443                 else
444                         type = AUDIT_APPARMOR_DENIED;
445
446                 if (denied == (denied & perms->hide))
447                         error = -ENOENT;
448
449                 denied &= ~perms->quiet;
450                 if (!sa || !denied)
451                         return error;
452         }
453
454         if (sa) {
455                 aad(sa)->label = &profile->label;
456                 aad(sa)->request = request;
457                 aad(sa)->denied = denied;
458                 aad(sa)->error = error;
459                 aa_audit_msg(type, sa, cb);
460         }
461
462         if (type == AUDIT_APPARMOR_ALLOWED)
463                 error = 0;
464
465         return error;
466 }
467
468
469 /**
470  * aa_policy_init - initialize a policy structure
471  * @policy: policy to initialize  (NOT NULL)
472  * @prefix: prefix name if any is required.  (MAYBE NULL)
473  * @name: name of the policy, init will make a copy of it  (NOT NULL)
474  * @gfp: allocation mode
475  *
476  * Note: this fn creates a copy of strings passed in
477  *
478  * Returns: true if policy init successful
479  */
480 bool aa_policy_init(struct aa_policy *policy, const char *prefix,
481                     const char *name, gfp_t gfp)
482 {
483         char *hname;
484
485         /* freed by policy_free */
486         if (prefix) {
487                 hname = aa_str_alloc(strlen(prefix) + strlen(name) + 3, gfp);
488                 if (hname)
489                         sprintf(hname, "%s//%s", prefix, name);
490         } else {
491                 hname = aa_str_alloc(strlen(name) + 1, gfp);
492                 if (hname)
493                         strcpy(hname, name);
494         }
495         if (!hname)
496                 return false;
497         policy->hname = hname;
498         /* base.name is a substring of fqname */
499         policy->name = basename(policy->hname);
500         INIT_LIST_HEAD(&policy->list);
501         INIT_LIST_HEAD(&policy->profiles);
502
503         return true;
504 }
505
506 /**
507  * aa_policy_destroy - free the elements referenced by @policy
508  * @policy: policy that is to have its elements freed  (NOT NULL)
509  */
510 void aa_policy_destroy(struct aa_policy *policy)
511 {
512         AA_BUG(on_list_rcu(&policy->profiles));
513         AA_BUG(on_list_rcu(&policy->list));
514
515         /* don't free name as its a subset of hname */
516         aa_put_str(policy->hname);
517 }