ima: Align ima_file_mmap() parameters with mmap_file LSM hook
[platform/kernel/linux-starfive.git] / security / apparmor / lib.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * AppArmor security module
4  *
5  * This file contains basic common functions used in AppArmor
6  *
7  * Copyright (C) 1998-2008 Novell/SUSE
8  * Copyright 2009-2010 Canonical Ltd.
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  * aa_split_fqname - split a fqname into a profile and namespace name
30  * @fqname: a full qualified name in namespace profile format (NOT NULL)
31  * @ns_name: pointer to portion of the string containing the ns name (NOT NULL)
32  *
33  * Returns: profile name or NULL if one is not specified
34  *
35  * Split a namespace name from a profile name (see policy.c for naming
36  * description).  If a portion of the name is missing it returns NULL for
37  * that portion.
38  *
39  * NOTE: may modify the @fqname string.  The pointers returned point
40  *       into the @fqname string.
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                         /* overwrite ':' with \0 */
52                         *split++ = 0;
53                         if (strncmp(split, "//", 2) == 0)
54                                 split += 2;
55                         name = skip_spaces(split);
56                 } else
57                         /* a ns name without a following profile is allowed */
58                         name = NULL;
59         }
60         if (name && *name == 0)
61                 name = NULL;
62
63         return name;
64 }
65
66 /**
67  * skipn_spaces - Removes leading whitespace from @str.
68  * @str: The string to be stripped.
69  *
70  * Returns a pointer to the first non-whitespace character in @str.
71  * if all whitespace will return NULL
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                         /* a ns name without a following profile is allowed */
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  * aa_info_message - log a none profile related status message
122  * @str: message to log
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(struct_size(str, name, 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  * aa_perm_mask_to_str - convert a perm mask to its short string
198  * @str: character buffer to store string in (at least 10 characters)
199  * @str_size: size of the @str buffer
200  * @chrs: NUL-terminated character buffer of permission characters
201  * @mask: permission mask to convert
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                         /* Ensure that one byte is left for NUL-termination */
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  * aa_audit_perms_cb - generic callback fn for auditing perms
259  * @ab: audit buffer (NOT NULL)
260  * @va: audit struct to audit values of (NOT NULL)
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  * aa_apply_modes_to_perms - apply namespace and profile flags to perms
285  * @profile: that perms where computed from
286  * @perms: perms to apply mode modifiers to
287  *
288  * TODO: split into profile and ns based flags for when accumulating perms
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                 fallthrough;
296         case AUDIT_NOQUIET:
297                 perms->quiet = 0;
298                 break;
299         case AUDIT_QUIET:
300                 perms->audit = 0;
301                 fallthrough;
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  *  TODO:
313  *      else if (PROMPT_MODE(profile))
314  *              perms->prompt = ALL_PERMS_MASK;
315  */
316 }
317
318 static u32 map_other(u32 x)
319 {
320         return ((x & 0x3) << 8) |       /* SETATTR/GETATTR */
321                 ((x & 0x1c) << 18) |    /* ACCEPT/BIND/LISTEN */
322                 ((x & 0x60) << 19);     /* SETOPT/GETOPT */
323 }
324
325 static u32 map_xbits(u32 x)
326 {
327         return ((x & 0x1) << 7) |
328                 ((x & 0x7e) << 9);
329 }
330
331 void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
332                       struct aa_perms *perms)
333 {
334         /* This mapping is convulated due to history.
335          * v1-v4: only file perms
336          * v5: added policydb which dropped in perm user conditional to
337          *     gain new perm bits, but had to map around the xbits because
338          *     the userspace compiler was still munging them.
339          * v9: adds using the xbits in policydb because the compiler now
340          *     supports treating policydb permission bits different.
341          *     Unfortunately there is not way to force auditing on the
342          *     perms represented by the xbits
343          */
344         *perms = (struct aa_perms) {
345                 .allow = dfa_user_allow(dfa, state) |
346                          map_xbits(dfa_user_xbits(dfa, state)),
347                 .audit = dfa_user_audit(dfa, state),
348                 .quiet = dfa_user_quiet(dfa, state) |
349                          map_xbits(dfa_other_xbits(dfa, state)),
350         };
351
352         /* for v5-v9 perm mapping in the policydb, the other set is used
353          * to extend the general perm set
354          */
355         perms->allow |= map_other(dfa_other_allow(dfa, state));
356         perms->audit |= map_other(dfa_other_audit(dfa, state));
357         perms->quiet |= map_other(dfa_other_quiet(dfa, state));
358 }
359
360 /**
361  * aa_perms_accum_raw - accumulate perms with out masking off overlapping perms
362  * @accum - perms struct to accumulate into
363  * @addend - perms struct to add to @accum
364  */
365 void aa_perms_accum_raw(struct aa_perms *accum, struct aa_perms *addend)
366 {
367         accum->deny |= addend->deny;
368         accum->allow &= addend->allow & ~addend->deny;
369         accum->audit |= addend->audit & addend->allow;
370         accum->quiet &= addend->quiet & ~addend->allow;
371         accum->kill |= addend->kill & ~addend->allow;
372         accum->stop |= addend->stop & ~addend->allow;
373         accum->complain |= addend->complain & ~addend->allow & ~addend->deny;
374         accum->cond |= addend->cond & ~addend->allow & ~addend->deny;
375         accum->hide &= addend->hide & ~addend->allow;
376         accum->prompt |= addend->prompt & ~addend->allow & ~addend->deny;
377 }
378
379 /**
380  * aa_perms_accum - accumulate perms, masking off overlapping perms
381  * @accum - perms struct to accumulate into
382  * @addend - perms struct to add to @accum
383  */
384 void aa_perms_accum(struct aa_perms *accum, struct aa_perms *addend)
385 {
386         accum->deny |= addend->deny;
387         accum->allow &= addend->allow & ~accum->deny;
388         accum->audit |= addend->audit & accum->allow;
389         accum->quiet &= addend->quiet & ~accum->allow;
390         accum->kill |= addend->kill & ~accum->allow;
391         accum->stop |= addend->stop & ~accum->allow;
392         accum->complain |= addend->complain & ~accum->allow & ~accum->deny;
393         accum->cond |= addend->cond & ~accum->allow & ~accum->deny;
394         accum->hide &= addend->hide & ~accum->allow;
395         accum->prompt |= addend->prompt & ~accum->allow & ~accum->deny;
396 }
397
398 void aa_profile_match_label(struct aa_profile *profile, struct aa_label *label,
399                             int type, u32 request, struct aa_perms *perms)
400 {
401         /* TODO: doesn't yet handle extended types */
402         unsigned int state;
403
404         state = aa_dfa_next(profile->policy.dfa,
405                             profile->policy.start[AA_CLASS_LABEL],
406                             type);
407         aa_label_match(profile, label, state, false, request, perms);
408 }
409
410
411 /* currently unused */
412 int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target,
413                           u32 request, int type, u32 *deny,
414                           struct common_audit_data *sa)
415 {
416         struct aa_perms perms;
417
418         aad(sa)->label = &profile->label;
419         aad(sa)->peer = &target->label;
420         aad(sa)->request = request;
421
422         aa_profile_match_label(profile, &target->label, type, request, &perms);
423         aa_apply_modes_to_perms(profile, &perms);
424         *deny |= request & perms.deny;
425         return aa_check_perms(profile, &perms, request, sa, aa_audit_perms_cb);
426 }
427
428 /**
429  * aa_check_perms - do audit mode selection based on perms set
430  * @profile: profile being checked
431  * @perms: perms computed for the request
432  * @request: requested perms
433  * @deny: Returns: explicit deny set
434  * @sa: initialized audit structure (MAY BE NULL if not auditing)
435  * @cb: callback fn for type specific fields (MAY BE NULL)
436  *
437  * Returns: 0 if permission else error code
438  *
439  * Note: profile audit modes need to be set before calling by setting the
440  *       perm masks appropriately.
441  *
442  *       If not auditing then complain mode is not enabled and the
443  *       error code will indicate whether there was an explicit deny
444  *       with a positive value.
445  */
446 int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms,
447                    u32 request, struct common_audit_data *sa,
448                    void (*cb)(struct audit_buffer *, void *))
449 {
450         int type, error;
451         u32 denied = request & (~perms->allow | perms->deny);
452
453         if (likely(!denied)) {
454                 /* mask off perms that are not being force audited */
455                 request &= perms->audit;
456                 if (!request || !sa)
457                         return 0;
458
459                 type = AUDIT_APPARMOR_AUDIT;
460                 error = 0;
461         } else {
462                 error = -EACCES;
463
464                 if (denied & perms->kill)
465                         type = AUDIT_APPARMOR_KILL;
466                 else if (denied == (denied & perms->complain))
467                         type = AUDIT_APPARMOR_ALLOWED;
468                 else
469                         type = AUDIT_APPARMOR_DENIED;
470
471                 if (denied == (denied & perms->hide))
472                         error = -ENOENT;
473
474                 denied &= ~perms->quiet;
475                 if (!sa || !denied)
476                         return error;
477         }
478
479         if (sa) {
480                 aad(sa)->label = &profile->label;
481                 aad(sa)->request = request;
482                 aad(sa)->denied = denied;
483                 aad(sa)->error = error;
484                 aa_audit_msg(type, sa, cb);
485         }
486
487         if (type == AUDIT_APPARMOR_ALLOWED)
488                 error = 0;
489
490         return error;
491 }
492
493
494 /**
495  * aa_policy_init - initialize a policy structure
496  * @policy: policy to initialize  (NOT NULL)
497  * @prefix: prefix name if any is required.  (MAYBE NULL)
498  * @name: name of the policy, init will make a copy of it  (NOT NULL)
499  * @gfp: allocation mode
500  *
501  * Note: this fn creates a copy of strings passed in
502  *
503  * Returns: true if policy init successful
504  */
505 bool aa_policy_init(struct aa_policy *policy, const char *prefix,
506                     const char *name, gfp_t gfp)
507 {
508         char *hname;
509
510         /* freed by policy_free */
511         if (prefix) {
512                 hname = aa_str_alloc(strlen(prefix) + strlen(name) + 3, gfp);
513                 if (hname)
514                         sprintf(hname, "%s//%s", prefix, name);
515         } else {
516                 hname = aa_str_alloc(strlen(name) + 1, gfp);
517                 if (hname)
518                         strcpy(hname, name);
519         }
520         if (!hname)
521                 return false;
522         policy->hname = hname;
523         /* base.name is a substring of fqname */
524         policy->name = basename(policy->hname);
525         INIT_LIST_HEAD(&policy->list);
526         INIT_LIST_HEAD(&policy->profiles);
527
528         return true;
529 }
530
531 /**
532  * aa_policy_destroy - free the elements referenced by @policy
533  * @policy: policy that is to have its elements freed  (NOT NULL)
534  */
535 void aa_policy_destroy(struct aa_policy *policy)
536 {
537         AA_BUG(on_list_rcu(&policy->profiles));
538         AA_BUG(on_list_rcu(&policy->list));
539
540         /* don't free name as its a subset of hname */
541         aa_put_str(policy->hname);
542 }