1b886d83cSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2cdff2642SJohn Johansen /* 3cdff2642SJohn Johansen * AppArmor security module 4cdff2642SJohn Johansen * 5cdff2642SJohn Johansen * This file contains basic common functions used in AppArmor 6cdff2642SJohn Johansen * 7cdff2642SJohn Johansen * Copyright (C) 1998-2008 Novell/SUSE 8cdff2642SJohn Johansen * Copyright 2009-2010 Canonical Ltd. 9cdff2642SJohn Johansen */ 10cdff2642SJohn Johansen 113b0aaf58SJohn Johansen #include <linux/ctype.h> 12b7f080cfSAlexey Dobriyan #include <linux/mm.h> 13cdff2642SJohn Johansen #include <linux/slab.h> 14cdff2642SJohn Johansen #include <linux/string.h> 15cdff2642SJohn Johansen #include <linux/vmalloc.h> 16cdff2642SJohn Johansen 17cdff2642SJohn Johansen #include "include/audit.h" 1832c3df63SJames Morris #include "include/apparmor.h" 1912557dcbSJohn Johansen #include "include/lib.h" 20fc7e0b26SJohn Johansen #include "include/perms.h" 21fe6bb31fSJohn Johansen #include "include/policy.h" 22cdff2642SJohn Johansen 232d679f3cSJohn Johansen struct aa_perms nullperms; 24aa9aeea8SJohn Johansen struct aa_perms allperms = { .allow = ALL_PERMS_MASK, 25aa9aeea8SJohn Johansen .quiet = ALL_PERMS_MASK, 26aa9aeea8SJohn Johansen .hide = ALL_PERMS_MASK }; 27aa9aeea8SJohn Johansen 28cdff2642SJohn Johansen /** 2990917d5bSJohn Johansen * aa_free_str_table - free entries str table 3073221ebeSGaosheng Cui * @t: the string table to free (MAYBE NULL) 3190917d5bSJohn Johansen */ 3290917d5bSJohn Johansen void aa_free_str_table(struct aa_str_table *t) 3390917d5bSJohn Johansen { 3490917d5bSJohn Johansen int i; 3590917d5bSJohn Johansen 3690917d5bSJohn Johansen if (t) { 3790917d5bSJohn Johansen if (!t->table) 3890917d5bSJohn Johansen return; 3990917d5bSJohn Johansen 4090917d5bSJohn Johansen for (i = 0; i < t->size; i++) 4190917d5bSJohn Johansen kfree_sensitive(t->table[i]); 4290917d5bSJohn Johansen kfree_sensitive(t->table); 4390917d5bSJohn Johansen t->table = NULL; 44*337c86dcSFedor Pchelkin t->size = 0; 4590917d5bSJohn Johansen } 4690917d5bSJohn Johansen } 4790917d5bSJohn Johansen 4890917d5bSJohn Johansen /** 49cdff2642SJohn Johansen * aa_split_fqname - split a fqname into a profile and namespace name 50cdff2642SJohn Johansen * @fqname: a full qualified name in namespace profile format (NOT NULL) 51cdff2642SJohn Johansen * @ns_name: pointer to portion of the string containing the ns name (NOT NULL) 52cdff2642SJohn Johansen * 53cdff2642SJohn Johansen * Returns: profile name or NULL if one is not specified 54cdff2642SJohn Johansen * 55cdff2642SJohn Johansen * Split a namespace name from a profile name (see policy.c for naming 56cdff2642SJohn Johansen * description). If a portion of the name is missing it returns NULL for 57cdff2642SJohn Johansen * that portion. 58cdff2642SJohn Johansen * 59cdff2642SJohn Johansen * NOTE: may modify the @fqname string. The pointers returned point 60cdff2642SJohn Johansen * into the @fqname string. 61cdff2642SJohn Johansen */ 62cdff2642SJohn Johansen char *aa_split_fqname(char *fqname, char **ns_name) 63cdff2642SJohn Johansen { 64cdff2642SJohn Johansen char *name = strim(fqname); 65cdff2642SJohn Johansen 66cdff2642SJohn Johansen *ns_name = NULL; 67cdff2642SJohn Johansen if (name[0] == ':') { 68cdff2642SJohn Johansen char *split = strchr(&name[1], ':'); 6904ccd53fSJohn Johansen *ns_name = skip_spaces(&name[1]); 70cdff2642SJohn Johansen if (split) { 71cdff2642SJohn Johansen /* overwrite ':' with \0 */ 722654bfbcSJohn Johansen *split++ = 0; 732654bfbcSJohn Johansen if (strncmp(split, "//", 2) == 0) 742654bfbcSJohn Johansen split += 2; 752654bfbcSJohn Johansen name = skip_spaces(split); 76cdff2642SJohn Johansen } else 77cdff2642SJohn Johansen /* a ns name without a following profile is allowed */ 78cdff2642SJohn Johansen name = NULL; 79cdff2642SJohn Johansen } 80cdff2642SJohn Johansen if (name && *name == 0) 81cdff2642SJohn Johansen name = NULL; 82cdff2642SJohn Johansen 83cdff2642SJohn Johansen return name; 84cdff2642SJohn Johansen } 85cdff2642SJohn Johansen 86cdff2642SJohn Johansen /** 873b0aaf58SJohn Johansen * skipn_spaces - Removes leading whitespace from @str. 883b0aaf58SJohn Johansen * @str: The string to be stripped. 8973221ebeSGaosheng Cui * @n: length of str to parse, will stop at \0 if encountered before n 903b0aaf58SJohn Johansen * 913b0aaf58SJohn Johansen * Returns a pointer to the first non-whitespace character in @str. 923b0aaf58SJohn Johansen * if all whitespace will return NULL 933b0aaf58SJohn Johansen */ 943b0aaf58SJohn Johansen 95b91deb9dSJohn Johansen const char *skipn_spaces(const char *str, size_t n) 963b0aaf58SJohn Johansen { 973b0aaf58SJohn Johansen for (; n && isspace(*str); --n) 983b0aaf58SJohn Johansen ++str; 993b0aaf58SJohn Johansen if (n) 1003b0aaf58SJohn Johansen return (char *)str; 1013b0aaf58SJohn Johansen return NULL; 1023b0aaf58SJohn Johansen } 1033b0aaf58SJohn Johansen 1043b0aaf58SJohn Johansen const char *aa_splitn_fqname(const char *fqname, size_t n, const char **ns_name, 1053b0aaf58SJohn Johansen size_t *ns_len) 1063b0aaf58SJohn Johansen { 1073b0aaf58SJohn Johansen const char *end = fqname + n; 1083b0aaf58SJohn Johansen const char *name = skipn_spaces(fqname, n); 1093b0aaf58SJohn Johansen 1103b0aaf58SJohn Johansen *ns_name = NULL; 1113b0aaf58SJohn Johansen *ns_len = 0; 112250f2da4SZubin Mithra 113250f2da4SZubin Mithra if (!name) 114250f2da4SZubin Mithra return NULL; 115250f2da4SZubin Mithra 1163b0aaf58SJohn Johansen if (name[0] == ':') { 1173b0aaf58SJohn Johansen char *split = strnchr(&name[1], end - &name[1], ':'); 1183b0aaf58SJohn Johansen *ns_name = skipn_spaces(&name[1], end - &name[1]); 1193b0aaf58SJohn Johansen if (!*ns_name) 1203b0aaf58SJohn Johansen return NULL; 1213b0aaf58SJohn Johansen if (split) { 1223b0aaf58SJohn Johansen *ns_len = split - *ns_name; 1233b0aaf58SJohn Johansen if (*ns_len == 0) 1243b0aaf58SJohn Johansen *ns_name = NULL; 1253b0aaf58SJohn Johansen split++; 1263b0aaf58SJohn Johansen if (end - split > 1 && strncmp(split, "//", 2) == 0) 1273b0aaf58SJohn Johansen split += 2; 1283b0aaf58SJohn Johansen name = skipn_spaces(split, end - split); 1293b0aaf58SJohn Johansen } else { 1303b0aaf58SJohn Johansen /* a ns name without a following profile is allowed */ 1313b0aaf58SJohn Johansen name = NULL; 1323b0aaf58SJohn Johansen *ns_len = end - *ns_name; 1333b0aaf58SJohn Johansen } 1343b0aaf58SJohn Johansen } 1353b0aaf58SJohn Johansen if (name && *name == 0) 1363b0aaf58SJohn Johansen name = NULL; 1373b0aaf58SJohn Johansen 1383b0aaf58SJohn Johansen return name; 1393b0aaf58SJohn Johansen } 1403b0aaf58SJohn Johansen 1413b0aaf58SJohn Johansen /** 142cdff2642SJohn Johansen * aa_info_message - log a none profile related status message 143cdff2642SJohn Johansen * @str: message to log 144cdff2642SJohn Johansen */ 145cdff2642SJohn Johansen void aa_info_message(const char *str) 146cdff2642SJohn Johansen { 147cdff2642SJohn Johansen if (audit_enabled) { 148c57bc80fSJohn Johansen DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, NULL); 149ef88a7acSJohn Johansen 150c57bc80fSJohn Johansen ad.info = str; 151c57bc80fSJohn Johansen aa_audit_msg(AUDIT_APPARMOR_STATUS, &ad, NULL); 152cdff2642SJohn Johansen } 153cdff2642SJohn Johansen printk(KERN_INFO "AppArmor: %s\n", str); 154cdff2642SJohn Johansen } 155cdff2642SJohn Johansen 156a1bd627bSJohn Johansen __counted char *aa_str_alloc(int size, gfp_t gfp) 157a1bd627bSJohn Johansen { 158a1bd627bSJohn Johansen struct counted_str *str; 159a1bd627bSJohn Johansen 160c0ea4b91SGustavo A. R. Silva str = kmalloc(struct_size(str, name, size), gfp); 161a1bd627bSJohn Johansen if (!str) 162a1bd627bSJohn Johansen return NULL; 163a1bd627bSJohn Johansen 164a1bd627bSJohn Johansen kref_init(&str->count); 165a1bd627bSJohn Johansen return str->name; 166a1bd627bSJohn Johansen } 167a1bd627bSJohn Johansen 168a1bd627bSJohn Johansen void aa_str_kref(struct kref *kref) 169a1bd627bSJohn Johansen { 170a1bd627bSJohn Johansen kfree(container_of(kref, struct counted_str, count)); 171a1bd627bSJohn Johansen } 172a1bd627bSJohn Johansen 173a1bd627bSJohn Johansen 174e53cfe6cSJohn Johansen const char aa_file_perm_chrs[] = "xwracd km l "; 175e53cfe6cSJohn Johansen const char *aa_file_perm_names[] = { 176e53cfe6cSJohn Johansen "exec", 177e53cfe6cSJohn Johansen "write", 178e53cfe6cSJohn Johansen "read", 179e53cfe6cSJohn Johansen "append", 180e53cfe6cSJohn Johansen 181e53cfe6cSJohn Johansen "create", 182e53cfe6cSJohn Johansen "delete", 183e53cfe6cSJohn Johansen "open", 184e53cfe6cSJohn Johansen "rename", 185e53cfe6cSJohn Johansen 186e53cfe6cSJohn Johansen "setattr", 187e53cfe6cSJohn Johansen "getattr", 188e53cfe6cSJohn Johansen "setcred", 189e53cfe6cSJohn Johansen "getcred", 190e53cfe6cSJohn Johansen 191e53cfe6cSJohn Johansen "chmod", 192e53cfe6cSJohn Johansen "chown", 193e53cfe6cSJohn Johansen "chgrp", 194e53cfe6cSJohn Johansen "lock", 195e53cfe6cSJohn Johansen 196e53cfe6cSJohn Johansen "mmap", 197e53cfe6cSJohn Johansen "mprot", 198e53cfe6cSJohn Johansen "link", 199e53cfe6cSJohn Johansen "snapshot", 200e53cfe6cSJohn Johansen 201e53cfe6cSJohn Johansen "unknown", 202e53cfe6cSJohn Johansen "unknown", 203e53cfe6cSJohn Johansen "unknown", 204e53cfe6cSJohn Johansen "unknown", 205e53cfe6cSJohn Johansen 206e53cfe6cSJohn Johansen "unknown", 207e53cfe6cSJohn Johansen "unknown", 208e53cfe6cSJohn Johansen "unknown", 209e53cfe6cSJohn Johansen "unknown", 210e53cfe6cSJohn Johansen 211e53cfe6cSJohn Johansen "stack", 212e53cfe6cSJohn Johansen "change_onexec", 213e53cfe6cSJohn Johansen "change_profile", 214e53cfe6cSJohn Johansen "change_hat", 215e53cfe6cSJohn Johansen }; 216e53cfe6cSJohn Johansen 217e53cfe6cSJohn Johansen /** 218e53cfe6cSJohn Johansen * aa_perm_mask_to_str - convert a perm mask to its short string 219e53cfe6cSJohn Johansen * @str: character buffer to store string in (at least 10 characters) 2207f3ebcf2STyler Hicks * @str_size: size of the @str buffer 2217f3ebcf2STyler Hicks * @chrs: NUL-terminated character buffer of permission characters 222e53cfe6cSJohn Johansen * @mask: permission mask to convert 223e53cfe6cSJohn Johansen */ 2247f3ebcf2STyler Hicks void aa_perm_mask_to_str(char *str, size_t str_size, const char *chrs, u32 mask) 225e53cfe6cSJohn Johansen { 226e53cfe6cSJohn Johansen unsigned int i, perm = 1; 2277f3ebcf2STyler Hicks size_t num_chrs = strlen(chrs); 228e53cfe6cSJohn Johansen 2297f3ebcf2STyler Hicks for (i = 0; i < num_chrs; perm <<= 1, i++) { 2307f3ebcf2STyler Hicks if (mask & perm) { 2317f3ebcf2STyler Hicks /* Ensure that one byte is left for NUL-termination */ 2327f3ebcf2STyler Hicks if (WARN_ON_ONCE(str_size <= 1)) 2337f3ebcf2STyler Hicks break; 2347f3ebcf2STyler Hicks 235e53cfe6cSJohn Johansen *str++ = chrs[i]; 2367f3ebcf2STyler Hicks str_size--; 2377f3ebcf2STyler Hicks } 238e53cfe6cSJohn Johansen } 239e53cfe6cSJohn Johansen *str = '\0'; 240e53cfe6cSJohn Johansen } 241e53cfe6cSJohn Johansen 24256974a6fSJohn Johansen void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names, 24356974a6fSJohn Johansen u32 mask) 244aa9aeea8SJohn Johansen { 245aa9aeea8SJohn Johansen const char *fmt = "%s"; 246aa9aeea8SJohn Johansen unsigned int i, perm = 1; 247aa9aeea8SJohn Johansen bool prev = false; 248aa9aeea8SJohn Johansen 249aa9aeea8SJohn Johansen for (i = 0; i < 32; perm <<= 1, i++) { 250aa9aeea8SJohn Johansen if (mask & perm) { 251aa9aeea8SJohn Johansen audit_log_format(ab, fmt, names[i]); 252aa9aeea8SJohn Johansen if (!prev) { 253aa9aeea8SJohn Johansen prev = true; 254aa9aeea8SJohn Johansen fmt = " %s"; 255aa9aeea8SJohn Johansen } 256aa9aeea8SJohn Johansen } 257aa9aeea8SJohn Johansen } 258aa9aeea8SJohn Johansen } 259aa9aeea8SJohn Johansen 260aa9aeea8SJohn Johansen void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs, 26156974a6fSJohn Johansen u32 chrsmask, const char * const *names, u32 namesmask) 262aa9aeea8SJohn Johansen { 263aa9aeea8SJohn Johansen char str[33]; 264aa9aeea8SJohn Johansen 265aa9aeea8SJohn Johansen audit_log_format(ab, "\""); 266aa9aeea8SJohn Johansen if ((mask & chrsmask) && chrs) { 2677f3ebcf2STyler Hicks aa_perm_mask_to_str(str, sizeof(str), chrs, mask & chrsmask); 268aa9aeea8SJohn Johansen mask &= ~chrsmask; 269aa9aeea8SJohn Johansen audit_log_format(ab, "%s", str); 270aa9aeea8SJohn Johansen if (mask & namesmask) 271aa9aeea8SJohn Johansen audit_log_format(ab, " "); 272aa9aeea8SJohn Johansen } 273aa9aeea8SJohn Johansen if ((mask & namesmask) && names) 274aa9aeea8SJohn Johansen aa_audit_perm_names(ab, names, mask & namesmask); 275aa9aeea8SJohn Johansen audit_log_format(ab, "\""); 276aa9aeea8SJohn Johansen } 277aa9aeea8SJohn Johansen 278aa9aeea8SJohn Johansen /** 279637f688dSJohn Johansen * aa_audit_perms_cb - generic callback fn for auditing perms 280637f688dSJohn Johansen * @ab: audit buffer (NOT NULL) 281637f688dSJohn Johansen * @va: audit struct to audit values of (NOT NULL) 282637f688dSJohn Johansen */ 283637f688dSJohn Johansen static void aa_audit_perms_cb(struct audit_buffer *ab, void *va) 284637f688dSJohn Johansen { 285637f688dSJohn Johansen struct common_audit_data *sa = va; 286c57bc80fSJohn Johansen struct apparmor_audit_data *ad = aad(sa); 287637f688dSJohn Johansen 288c57bc80fSJohn Johansen if (ad->request) { 289637f688dSJohn Johansen audit_log_format(ab, " requested_mask="); 290c57bc80fSJohn Johansen aa_audit_perm_mask(ab, ad->request, aa_file_perm_chrs, 291637f688dSJohn Johansen PERMS_CHRS_MASK, aa_file_perm_names, 292637f688dSJohn Johansen PERMS_NAMES_MASK); 293637f688dSJohn Johansen } 294c57bc80fSJohn Johansen if (ad->denied) { 295637f688dSJohn Johansen audit_log_format(ab, "denied_mask="); 296c57bc80fSJohn Johansen aa_audit_perm_mask(ab, ad->denied, aa_file_perm_chrs, 297637f688dSJohn Johansen PERMS_CHRS_MASK, aa_file_perm_names, 298637f688dSJohn Johansen PERMS_NAMES_MASK); 299637f688dSJohn Johansen } 300637f688dSJohn Johansen audit_log_format(ab, " peer="); 30130b3669dSJohn Johansen aa_label_xaudit(ab, labels_ns(ad->subj_label), ad->peer, 302637f688dSJohn Johansen FLAGS_NONE, GFP_ATOMIC); 303637f688dSJohn Johansen } 304637f688dSJohn Johansen 305637f688dSJohn Johansen /** 306aa9aeea8SJohn Johansen * aa_apply_modes_to_perms - apply namespace and profile flags to perms 307aa9aeea8SJohn Johansen * @profile: that perms where computed from 308aa9aeea8SJohn Johansen * @perms: perms to apply mode modifiers to 309aa9aeea8SJohn Johansen * 310aa9aeea8SJohn Johansen * TODO: split into profile and ns based flags for when accumulating perms 311aa9aeea8SJohn Johansen */ 312aa9aeea8SJohn Johansen void aa_apply_modes_to_perms(struct aa_profile *profile, struct aa_perms *perms) 313aa9aeea8SJohn Johansen { 314aa9aeea8SJohn Johansen switch (AUDIT_MODE(profile)) { 315aa9aeea8SJohn Johansen case AUDIT_ALL: 316aa9aeea8SJohn Johansen perms->audit = ALL_PERMS_MASK; 317df561f66SGustavo A. R. Silva fallthrough; 318aa9aeea8SJohn Johansen case AUDIT_NOQUIET: 319aa9aeea8SJohn Johansen perms->quiet = 0; 320aa9aeea8SJohn Johansen break; 321aa9aeea8SJohn Johansen case AUDIT_QUIET: 322aa9aeea8SJohn Johansen perms->audit = 0; 323df561f66SGustavo A. R. Silva fallthrough; 324aa9aeea8SJohn Johansen case AUDIT_QUIET_DENIED: 325aa9aeea8SJohn Johansen perms->quiet = ALL_PERMS_MASK; 326aa9aeea8SJohn Johansen break; 327aa9aeea8SJohn Johansen } 328aa9aeea8SJohn Johansen 329aa9aeea8SJohn Johansen if (KILL_MODE(profile)) 330aa9aeea8SJohn Johansen perms->kill = ALL_PERMS_MASK; 331aa9aeea8SJohn Johansen else if (COMPLAIN_MODE(profile)) 332aa9aeea8SJohn Johansen perms->complain = ALL_PERMS_MASK; 33322fac8a0SJohn Johansen else if (USER_MODE(profile)) 33422fac8a0SJohn Johansen perms->prompt = ALL_PERMS_MASK; 335aa9aeea8SJohn Johansen } 336aa9aeea8SJohn Johansen 337217af7e2SJohn Johansen void aa_profile_match_label(struct aa_profile *profile, 338217af7e2SJohn Johansen struct aa_ruleset *rules, 339217af7e2SJohn Johansen struct aa_label *label, 340637f688dSJohn Johansen int type, u32 request, struct aa_perms *perms) 341637f688dSJohn Johansen { 342637f688dSJohn Johansen /* TODO: doesn't yet handle extended types */ 34333fc95d8SJohn Johansen aa_state_t state; 344637f688dSJohn Johansen 345217af7e2SJohn Johansen state = aa_dfa_next(rules->policy.dfa, 346217af7e2SJohn Johansen rules->policy.start[AA_CLASS_LABEL], 347637f688dSJohn Johansen type); 348217af7e2SJohn Johansen aa_label_match(profile, rules, label, state, false, request, perms); 349637f688dSJohn Johansen } 350637f688dSJohn Johansen 351637f688dSJohn Johansen 352637f688dSJohn Johansen /* currently unused */ 353637f688dSJohn Johansen int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target, 354637f688dSJohn Johansen u32 request, int type, u32 *deny, 355c57bc80fSJohn Johansen struct apparmor_audit_data *ad) 356637f688dSJohn Johansen { 3571ad22fccSJohn Johansen struct aa_ruleset *rules = list_first_entry(&profile->rules, 3581ad22fccSJohn Johansen typeof(*rules), list); 359637f688dSJohn Johansen struct aa_perms perms; 360637f688dSJohn Johansen 361c57bc80fSJohn Johansen ad->peer = &target->label; 362c57bc80fSJohn Johansen ad->request = request; 363637f688dSJohn Johansen 3641ad22fccSJohn Johansen aa_profile_match_label(profile, rules, &target->label, type, request, 3651ad22fccSJohn Johansen &perms); 366637f688dSJohn Johansen aa_apply_modes_to_perms(profile, &perms); 367637f688dSJohn Johansen *deny |= request & perms.deny; 368c57bc80fSJohn Johansen return aa_check_perms(profile, &perms, request, ad, aa_audit_perms_cb); 369637f688dSJohn Johansen } 370637f688dSJohn Johansen 371637f688dSJohn Johansen /** 372637f688dSJohn Johansen * aa_check_perms - do audit mode selection based on perms set 373637f688dSJohn Johansen * @profile: profile being checked 374637f688dSJohn Johansen * @perms: perms computed for the request 375637f688dSJohn Johansen * @request: requested perms 376c57bc80fSJohn Johansen * @ad: initialized audit structure (MAY BE NULL if not auditing) 37769ad4a44SZygmunt Krynicki * @cb: callback fn for type specific fields (MAY BE NULL) 378637f688dSJohn Johansen * 379637f688dSJohn Johansen * Returns: 0 if permission else error code 380637f688dSJohn Johansen * 381637f688dSJohn Johansen * Note: profile audit modes need to be set before calling by setting the 382637f688dSJohn Johansen * perm masks appropriately. 383637f688dSJohn Johansen * 384637f688dSJohn Johansen * If not auditing then complain mode is not enabled and the 385637f688dSJohn Johansen * error code will indicate whether there was an explicit deny 386637f688dSJohn Johansen * with a positive value. 387637f688dSJohn Johansen */ 388637f688dSJohn Johansen int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms, 389c57bc80fSJohn Johansen u32 request, struct apparmor_audit_data *ad, 390637f688dSJohn Johansen void (*cb)(struct audit_buffer *, void *)) 391637f688dSJohn Johansen { 392637f688dSJohn Johansen int type, error; 393637f688dSJohn Johansen u32 denied = request & (~perms->allow | perms->deny); 394637f688dSJohn Johansen 395637f688dSJohn Johansen if (likely(!denied)) { 396637f688dSJohn Johansen /* mask off perms that are not being force audited */ 397637f688dSJohn Johansen request &= perms->audit; 398c57bc80fSJohn Johansen if (!request || !ad) 399637f688dSJohn Johansen return 0; 400637f688dSJohn Johansen 401637f688dSJohn Johansen type = AUDIT_APPARMOR_AUDIT; 402637f688dSJohn Johansen error = 0; 403637f688dSJohn Johansen } else { 404637f688dSJohn Johansen error = -EACCES; 405637f688dSJohn Johansen 406637f688dSJohn Johansen if (denied & perms->kill) 407637f688dSJohn Johansen type = AUDIT_APPARMOR_KILL; 408637f688dSJohn Johansen else if (denied == (denied & perms->complain)) 409637f688dSJohn Johansen type = AUDIT_APPARMOR_ALLOWED; 410637f688dSJohn Johansen else 411637f688dSJohn Johansen type = AUDIT_APPARMOR_DENIED; 412637f688dSJohn Johansen 413637f688dSJohn Johansen if (denied == (denied & perms->hide)) 414637f688dSJohn Johansen error = -ENOENT; 415637f688dSJohn Johansen 416637f688dSJohn Johansen denied &= ~perms->quiet; 417c57bc80fSJohn Johansen if (!ad || !denied) 418637f688dSJohn Johansen return error; 419637f688dSJohn Johansen } 420637f688dSJohn Johansen 421c57bc80fSJohn Johansen if (ad) { 42230b3669dSJohn Johansen ad->subj_label = &profile->label; 423c57bc80fSJohn Johansen ad->request = request; 424c57bc80fSJohn Johansen ad->denied = denied; 425c57bc80fSJohn Johansen ad->error = error; 426c57bc80fSJohn Johansen aa_audit_msg(type, ad, cb); 427637f688dSJohn Johansen } 428637f688dSJohn Johansen 429637f688dSJohn Johansen if (type == AUDIT_APPARMOR_ALLOWED) 430637f688dSJohn Johansen error = 0; 431637f688dSJohn Johansen 432637f688dSJohn Johansen return error; 433637f688dSJohn Johansen } 434637f688dSJohn Johansen 435637f688dSJohn Johansen 436637f688dSJohn Johansen /** 437fe6bb31fSJohn Johansen * aa_policy_init - initialize a policy structure 438fe6bb31fSJohn Johansen * @policy: policy to initialize (NOT NULL) 439fe6bb31fSJohn Johansen * @prefix: prefix name if any is required. (MAYBE NULL) 440fe6bb31fSJohn Johansen * @name: name of the policy, init will make a copy of it (NOT NULL) 441a1bd627bSJohn Johansen * @gfp: allocation mode 442fe6bb31fSJohn Johansen * 443fe6bb31fSJohn Johansen * Note: this fn creates a copy of strings passed in 444fe6bb31fSJohn Johansen * 445fe6bb31fSJohn Johansen * Returns: true if policy init successful 446fe6bb31fSJohn Johansen */ 447fe6bb31fSJohn Johansen bool aa_policy_init(struct aa_policy *policy, const char *prefix, 448d102d895SJohn Johansen const char *name, gfp_t gfp) 449fe6bb31fSJohn Johansen { 450a1bd627bSJohn Johansen char *hname; 451a1bd627bSJohn Johansen 452fe6bb31fSJohn Johansen /* freed by policy_free */ 453fe6bb31fSJohn Johansen if (prefix) { 454a1bd627bSJohn Johansen hname = aa_str_alloc(strlen(prefix) + strlen(name) + 3, gfp); 455a1bd627bSJohn Johansen if (hname) 456a1bd627bSJohn Johansen sprintf(hname, "%s//%s", prefix, name); 457a1bd627bSJohn Johansen } else { 458a1bd627bSJohn Johansen hname = aa_str_alloc(strlen(name) + 1, gfp); 459a1bd627bSJohn Johansen if (hname) 460a1bd627bSJohn Johansen strcpy(hname, name); 461a1bd627bSJohn Johansen } 462a1bd627bSJohn Johansen if (!hname) 463b9c42ac7Skbuild test robot return false; 464a1bd627bSJohn Johansen policy->hname = hname; 465fe6bb31fSJohn Johansen /* base.name is a substring of fqname */ 466d102d895SJohn Johansen policy->name = basename(policy->hname); 467fe6bb31fSJohn Johansen INIT_LIST_HEAD(&policy->list); 468fe6bb31fSJohn Johansen INIT_LIST_HEAD(&policy->profiles); 469fe6bb31fSJohn Johansen 470b9c42ac7Skbuild test robot return true; 471fe6bb31fSJohn Johansen } 472fe6bb31fSJohn Johansen 473fe6bb31fSJohn Johansen /** 474fe6bb31fSJohn Johansen * aa_policy_destroy - free the elements referenced by @policy 475fe6bb31fSJohn Johansen * @policy: policy that is to have its elements freed (NOT NULL) 476fe6bb31fSJohn Johansen */ 477fe6bb31fSJohn Johansen void aa_policy_destroy(struct aa_policy *policy) 478fe6bb31fSJohn Johansen { 4795fd1b95fSJohn Johansen AA_BUG(on_list_rcu(&policy->profiles)); 4805fd1b95fSJohn Johansen AA_BUG(on_list_rcu(&policy->list)); 481fe6bb31fSJohn Johansen 482fe6bb31fSJohn Johansen /* don't free name as its a subset of hname */ 483a1bd627bSJohn Johansen aa_put_str(policy->hname); 484fe6bb31fSJohn Johansen } 485