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 const struct aa_perms nullperms;
24 const struct aa_perms allperms = { .allow = ALL_PERMS_MASK,
25 .quiet = ALL_PERMS_MASK,
26 .hide = ALL_PERMS_MASK };
27
28 struct val_table_ent {
29 const char *str;
30 int value;
31 };
32
33 static const struct val_table_ent debug_values_table[] = {
34 { "N", DEBUG_NONE },
35 { "none", DEBUG_NONE },
36 { "n", DEBUG_NONE },
37 { "0", DEBUG_NONE },
38 { "all", DEBUG_ALL },
39 { "Y", DEBUG_ALL },
40 { "y", DEBUG_ALL },
41 { "1", DEBUG_ALL },
42 { "abs_root", DEBUG_LABEL_ABS_ROOT },
43 { "label", DEBUG_LABEL },
44 { "domain", DEBUG_DOMAIN },
45 { "policy", DEBUG_POLICY },
46 { "interface", DEBUG_INTERFACE },
47 { "unpack", DEBUG_UNPACK },
48 { "tags", DEBUG_TAGS },
49 { NULL, 0 }
50 };
51
52 static const struct val_table_ent *
val_table_find_ent(const struct val_table_ent * table,const char * name,size_t len)53 val_table_find_ent(const struct val_table_ent *table,
54 const char *name, size_t len)
55 {
56 const struct val_table_ent *entry;
57
58 for (entry = table; entry->str != NULL; entry++) {
59 if (strncmp(entry->str, name, len) == 0 &&
60 strlen(entry->str) == len)
61 return entry;
62 }
63 return NULL;
64 }
65
aa_parse_debug_params(const char * str)66 int aa_parse_debug_params(const char *str)
67 {
68 const struct val_table_ent *ent;
69 const char *next;
70 int val = 0;
71
72 do {
73 size_t n = strcspn(str, "\r\n,");
74
75 next = str + n;
76 ent = val_table_find_ent(debug_values_table, str, next - str);
77 if (ent)
78 val |= ent->value;
79 else
80 AA_DEBUG(DEBUG_INTERFACE, "unknown debug type '%.*s'",
81 (int)(next - str), str);
82 str = next + 1;
83 } while (*next != 0);
84 return val;
85 }
86
87 /**
88 * val_mask_to_str - convert a perm mask to its short string
89 * @str: character buffer to store string in (at least 10 characters)
90 * @size: size of the @str buffer
91 * @table: NUL-terminated character buffer of permission characters (NOT NULL)
92 * @mask: permission mask to convert
93 */
val_mask_to_str(char * str,size_t size,const struct val_table_ent * table,u32 mask)94 static int val_mask_to_str(char *str, size_t size,
95 const struct val_table_ent *table, u32 mask)
96 {
97 const struct val_table_ent *ent;
98 int total = 0;
99
100 for (ent = table; ent->str; ent++) {
101 if (ent->value && (ent->value & mask) == ent->value) {
102 int len = scnprintf(str, size, "%s%s", total ? "," : "",
103 ent->str);
104 size -= len;
105 str += len;
106 total += len;
107 mask &= ~ent->value;
108 }
109 }
110
111 return total;
112 }
113
aa_print_debug_params(char * buffer)114 int aa_print_debug_params(char *buffer)
115 {
116 if (!aa_g_debug)
117 return sprintf(buffer, "N");
118 return val_mask_to_str(buffer, PAGE_SIZE, debug_values_table,
119 aa_g_debug);
120 }
121
aa_resize_str_table(struct aa_str_table * t,int newsize,gfp_t gfp)122 bool aa_resize_str_table(struct aa_str_table *t, int newsize, gfp_t gfp)
123 {
124 struct aa_str_table_ent *n;
125 int i;
126
127 if (t->size == newsize)
128 return true;
129 n = kzalloc_objs(*n, newsize, gfp);
130 if (!n)
131 return false;
132 for (i = 0; i < min(t->size, newsize); i++)
133 n[i] = t->table[i];
134 for (; i < t->size; i++)
135 kfree_sensitive(t->table[i].strs);
136 if (newsize > t->size)
137 memset(&n[t->size], 0, (newsize-t->size)*sizeof(*n));
138 kfree_sensitive(t->table);
139 t->table = n;
140 t->size = newsize;
141
142 return true;
143 }
144
145 /**
146 * aa_destroy_str_table - free entries str table
147 * @t: the string table to free (MAYBE NULL)
148 */
aa_destroy_str_table(struct aa_str_table * t)149 void aa_destroy_str_table(struct aa_str_table *t)
150 {
151 int i;
152
153 if (t) {
154 if (!t->table)
155 return;
156
157 for (i = 0; i < t->size; i++)
158 kfree_sensitive(t->table[i].strs);
159 kfree_sensitive(t->table);
160 t->table = NULL;
161 t->size = 0;
162 }
163 }
164
165 /**
166 * skipn_spaces - Removes leading whitespace from @str.
167 * @str: The string to be stripped.
168 * @n: length of str to parse, will stop at \0 if encountered before n
169 *
170 * Returns a pointer to the first non-whitespace character in @str.
171 * if all whitespace will return NULL
172 */
173
skipn_spaces(const char * str,size_t n)174 const char *skipn_spaces(const char *str, size_t n)
175 {
176 for (; n && isspace(*str); --n)
177 ++str;
178 if (n)
179 return (char *)str;
180 return NULL;
181 }
182
aa_splitn_fqname(const char * fqname,size_t n,const char ** ns_name,size_t * ns_len)183 const char *aa_splitn_fqname(const char *fqname, size_t n, const char **ns_name,
184 size_t *ns_len)
185 {
186 const char *end = fqname + n;
187 const char *name = skipn_spaces(fqname, n);
188
189 *ns_name = NULL;
190 *ns_len = 0;
191
192 if (!name)
193 return NULL;
194
195 if (name[0] == ':') {
196 char *split = strnchr(&name[1], end - &name[1], ':');
197 *ns_name = skipn_spaces(&name[1], end - &name[1]);
198 if (!*ns_name)
199 return NULL;
200 if (split) {
201 *ns_len = split - *ns_name;
202 if (*ns_len == 0)
203 *ns_name = NULL;
204 split++;
205 if (end - split > 1 && strncmp(split, "//", 2) == 0)
206 split += 2;
207 name = skipn_spaces(split, end - split);
208 } else {
209 /* a ns name without a following profile is allowed */
210 name = NULL;
211 *ns_len = end - *ns_name;
212 }
213 }
214 if (name && *name == 0)
215 name = NULL;
216
217 return name;
218 }
219
220 /**
221 * aa_info_message - log a none profile related status message
222 * @str: message to log
223 */
aa_info_message(const char * str)224 void aa_info_message(const char *str)
225 {
226 if (audit_enabled) {
227 DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, NULL);
228
229 ad.info = str;
230 aa_audit_msg(AUDIT_APPARMOR_STATUS, &ad, NULL);
231 }
232 printk(KERN_INFO "AppArmor: %s\n", str);
233 }
234
aa_str_alloc(int size,gfp_t gfp)235 __counted char *aa_str_alloc(int size, gfp_t gfp)
236 {
237 struct counted_str *str;
238
239 str = kmalloc_flex(*str, name, size, gfp);
240 if (!str)
241 return NULL;
242
243 kref_init(&str->count);
244 return str->name;
245 }
246
aa_str_kref(struct kref * kref)247 void aa_str_kref(struct kref *kref)
248 {
249 kfree(container_of(kref, struct counted_str, count));
250 }
251
252
253 const char aa_file_perm_chrs[] = "xwracd km l ";
254 const char *aa_file_perm_names[] = {
255 "exec",
256 "write",
257 "read",
258 "append",
259
260 "create",
261 "delete",
262 "open",
263 "rename",
264
265 "setattr",
266 "getattr",
267 "setcred",
268 "getcred",
269
270 "chmod",
271 "chown",
272 "chgrp",
273 "lock",
274
275 "mmap",
276 "mprot",
277 "link",
278 "snapshot",
279
280 "unknown",
281 "unknown",
282 "unknown",
283 "unknown",
284
285 "unknown",
286 "unknown",
287 "unknown",
288 "unknown",
289
290 "stack",
291 "change_onexec",
292 "change_profile",
293 "change_hat",
294 };
295
296 /**
297 * aa_perm_mask_to_str - convert a perm mask to its short string
298 * @str: character buffer to store string in (at least 10 characters)
299 * @str_size: size of the @str buffer
300 * @chrs: NUL-terminated character buffer of permission characters
301 * @mask: permission mask to convert
302 */
aa_perm_mask_to_str(char * str,size_t str_size,const char * chrs,u32 mask)303 void aa_perm_mask_to_str(char *str, size_t str_size, const char *chrs, u32 mask)
304 {
305 unsigned int i, perm = 1;
306 size_t num_chrs = strlen(chrs);
307
308 for (i = 0; i < num_chrs; perm <<= 1, i++) {
309 if (mask & perm) {
310 /* Ensure that one byte is left for NUL-termination */
311 if (WARN_ON_ONCE(str_size <= 1))
312 break;
313
314 *str++ = chrs[i];
315 str_size--;
316 }
317 }
318 *str = '\0';
319 }
320
aa_audit_perm_names(struct audit_buffer * ab,const char * const * names,u32 mask)321 void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names,
322 u32 mask)
323 {
324 const char *fmt = "%s";
325 unsigned int i, perm = 1;
326 bool prev = false;
327
328 for (i = 0; i < 32; perm <<= 1, i++) {
329 if (mask & perm) {
330 audit_log_format(ab, fmt, names[i]);
331 if (!prev) {
332 prev = true;
333 fmt = " %s";
334 }
335 }
336 }
337 }
338
aa_audit_perm_mask(struct audit_buffer * ab,u32 mask,const char * chrs,u32 chrsmask,const char * const * names,u32 namesmask)339 void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
340 u32 chrsmask, const char * const *names, u32 namesmask)
341 {
342 char str[33];
343
344 audit_log_format(ab, "\"");
345 if ((mask & chrsmask) && chrs) {
346 aa_perm_mask_to_str(str, sizeof(str), chrs, mask & chrsmask);
347 mask &= ~chrsmask;
348 audit_log_format(ab, "%s", str);
349 if (mask & namesmask)
350 audit_log_format(ab, " ");
351 }
352 if ((mask & namesmask) && names)
353 aa_audit_perm_names(ab, names, mask & namesmask);
354 audit_log_format(ab, "\"");
355 }
356
357 /**
358 * aa_apply_modes_to_perms - apply namespace and profile flags to perms
359 * @profile: that perms where computed from
360 * @perms: perms to apply mode modifiers to
361 *
362 * TODO: split into profile and ns based flags for when accumulating perms
363 */
aa_apply_modes_to_perms(const struct aa_profile * profile,struct aa_perms * perms)364 void aa_apply_modes_to_perms(const struct aa_profile *profile,
365 struct aa_perms *perms)
366 {
367 if (KILL_MODE(profile))
368 perms->kill = ~perms->allow;
369 else if (COMPLAIN_MODE(profile))
370 perms->complain |= ~(perms->allow | perms->deny);
371 else if (USER_MODE(profile))
372 perms->prompt |= ~(perms->allow | perms->deny);
373
374 switch (AUDIT_MODE(profile)) {
375 case AUDIT_ALL:
376 perms->audit = ALL_PERMS_MASK;
377 fallthrough;
378 case AUDIT_NOQUIET:
379 perms->quiet = 0;
380 break;
381 case AUDIT_QUIET:
382 perms->audit = 0;
383 fallthrough;
384 case AUDIT_QUIET_DENIED:
385 perms->quiet |= ~perms->allow;
386 break;
387 case AUDIT_QUIET_ALLOWED:
388 perms->quiet |= perms->complain | perms->allow;
389 break;
390 }
391 }
392
aa_profile_match_label(const struct aa_profile * profile,struct aa_ruleset * rules,struct aa_label * label,int type,u32 request,struct aa_perms * perms)393 void aa_profile_match_label(const struct aa_profile *profile,
394 struct aa_ruleset *rules,
395 struct aa_label *label,
396 int type, u32 request, struct aa_perms *perms)
397 {
398 /* TODO: doesn't yet handle extended types */
399 aa_state_t state;
400
401 state = aa_dfa_next(rules->policy->dfa,
402 rules->policy->start[AA_CLASS_LABEL],
403 type);
404 aa_label_match(profile, rules, label, state, false, request, perms);
405 }
406
407
408 /**
409 * aa_check_perms - do audit mode selection based on perms set
410 * @profile: profile being checked
411 * @perms: perms computed for the request
412 * @request: requested perms
413 * @ad: initialized audit structure (MAY BE NULL if not auditing)
414 * @cb: callback fn for type specific fields (MAY BE NULL)
415 *
416 * Returns: 0 if permission else error code
417 *
418 * Note: profile audit modes need to be set before calling by setting the
419 * perm masks appropriately.
420 *
421 * If not auditing then complain mode is not enabled and the
422 * error code will indicate whether there was an explicit deny
423 * with a positive value.
424 */
aa_check_perms(struct aa_profile * profile,const struct aa_perms * perms,u32 request,struct apparmor_audit_data * ad,void (* cb)(struct audit_buffer *,void *))425 int aa_check_perms(struct aa_profile *profile, const struct aa_perms *perms,
426 u32 request, struct apparmor_audit_data *ad,
427 void (*cb)(struct audit_buffer *, void *))
428 {
429 int error;
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 || !ad)
436 return 0;
437
438 error = 0;
439 } else {
440 error = -EACCES;
441
442 if (denied == (denied & perms->hide))
443 error = -ENOENT;
444
445 denied &= ~perms->quiet;
446 if (!ad || !denied)
447 return error;
448 }
449
450 int type = aa_select_audit_type(denied, perms);
451
452 if (ad) {
453 ad->subj_label = &profile->label;
454 ad->request = request;
455 ad->denied = denied;
456 ad->error = error;
457 aa_audit_msg(type, ad, cb);
458 }
459
460 if (type == AUDIT_APPARMOR_ALLOWED)
461 error = 0;
462
463 return error;
464 }
465
466
467 /**
468 * aa_policy_init - initialize a policy structure
469 * @policy: policy to initialize (NOT NULL)
470 * @prefix: prefix name if any is required. (MAYBE NULL)
471 * @name: name of the policy, init will make a copy of it (NOT NULL)
472 * @gfp: allocation mode
473 *
474 * Note: this fn creates a copy of strings passed in
475 *
476 * Returns: true if policy init successful
477 */
aa_policy_init(struct aa_policy * policy,const char * prefix,const char * name,gfp_t gfp)478 bool aa_policy_init(struct aa_policy *policy, const char *prefix,
479 const char *name, gfp_t gfp)
480 {
481 char *hname;
482 size_t hname_sz;
483
484 INIT_LIST_HEAD(&policy->list);
485 INIT_LIST_HEAD(&policy->profiles);
486 hname_sz = (prefix ? strlen(prefix) + 2 : 0) + strlen(name) + 1;
487 /* freed by policy_free */
488 hname = aa_str_alloc(hname_sz, gfp);
489 if (!hname)
490 return false;
491 if (prefix)
492 scnprintf(hname, hname_sz, "%s//%s", prefix, name);
493 else
494 strscpy(hname, name, hname_sz);
495 policy->hname = hname;
496 /* base.name is a substring of fqname */
497 policy->name = basename(policy->hname);
498
499 return true;
500 }
501
502 /**
503 * aa_policy_destroy - free the elements referenced by @policy
504 * @policy: policy that is to have its elements freed (NOT NULL)
505 */
aa_policy_destroy(struct aa_policy * policy)506 void aa_policy_destroy(struct aa_policy *policy)
507 {
508 AA_BUG(on_list_rcu(&policy->profiles));
509 AA_BUG(on_list_rcu(&policy->list));
510
511 /* don't free name as its a subset of hname */
512 aa_put_str(policy->hname);
513 }
514
515