1cdff2642SJohn Johansen /* 2cdff2642SJohn Johansen * AppArmor security module 3cdff2642SJohn Johansen * 4cdff2642SJohn Johansen * This file contains basic common functions used in AppArmor 5cdff2642SJohn Johansen * 6cdff2642SJohn Johansen * Copyright (C) 1998-2008 Novell/SUSE 7cdff2642SJohn Johansen * Copyright 2009-2010 Canonical Ltd. 8cdff2642SJohn Johansen * 9cdff2642SJohn Johansen * This program is free software; you can redistribute it and/or 10cdff2642SJohn Johansen * modify it under the terms of the GNU General Public License as 11cdff2642SJohn Johansen * published by the Free Software Foundation, version 2 of the 12cdff2642SJohn Johansen * License. 13cdff2642SJohn Johansen */ 14cdff2642SJohn Johansen 153b0aaf58SJohn Johansen #include <linux/ctype.h> 16b7f080cfSAlexey Dobriyan #include <linux/mm.h> 17cdff2642SJohn Johansen #include <linux/slab.h> 18cdff2642SJohn Johansen #include <linux/string.h> 19cdff2642SJohn Johansen #include <linux/vmalloc.h> 20cdff2642SJohn Johansen 21cdff2642SJohn Johansen #include "include/audit.h" 2232c3df63SJames Morris #include "include/apparmor.h" 2312557dcbSJohn Johansen #include "include/lib.h" 24fc7e0b26SJohn Johansen #include "include/perms.h" 25fe6bb31fSJohn Johansen #include "include/policy.h" 26cdff2642SJohn Johansen 27cdff2642SJohn Johansen /** 28cdff2642SJohn Johansen * aa_split_fqname - split a fqname into a profile and namespace name 29cdff2642SJohn Johansen * @fqname: a full qualified name in namespace profile format (NOT NULL) 30cdff2642SJohn Johansen * @ns_name: pointer to portion of the string containing the ns name (NOT NULL) 31cdff2642SJohn Johansen * 32cdff2642SJohn Johansen * Returns: profile name or NULL if one is not specified 33cdff2642SJohn Johansen * 34cdff2642SJohn Johansen * Split a namespace name from a profile name (see policy.c for naming 35cdff2642SJohn Johansen * description). If a portion of the name is missing it returns NULL for 36cdff2642SJohn Johansen * that portion. 37cdff2642SJohn Johansen * 38cdff2642SJohn Johansen * NOTE: may modify the @fqname string. The pointers returned point 39cdff2642SJohn Johansen * into the @fqname string. 40cdff2642SJohn Johansen */ 41cdff2642SJohn Johansen char *aa_split_fqname(char *fqname, char **ns_name) 42cdff2642SJohn Johansen { 43cdff2642SJohn Johansen char *name = strim(fqname); 44cdff2642SJohn Johansen 45cdff2642SJohn Johansen *ns_name = NULL; 46cdff2642SJohn Johansen if (name[0] == ':') { 47cdff2642SJohn Johansen char *split = strchr(&name[1], ':'); 4804ccd53fSJohn Johansen *ns_name = skip_spaces(&name[1]); 49cdff2642SJohn Johansen if (split) { 50cdff2642SJohn Johansen /* overwrite ':' with \0 */ 512654bfbcSJohn Johansen *split++ = 0; 522654bfbcSJohn Johansen if (strncmp(split, "//", 2) == 0) 532654bfbcSJohn Johansen split += 2; 542654bfbcSJohn Johansen name = skip_spaces(split); 55cdff2642SJohn Johansen } else 56cdff2642SJohn Johansen /* a ns name without a following profile is allowed */ 57cdff2642SJohn Johansen name = NULL; 58cdff2642SJohn Johansen } 59cdff2642SJohn Johansen if (name && *name == 0) 60cdff2642SJohn Johansen name = NULL; 61cdff2642SJohn Johansen 62cdff2642SJohn Johansen return name; 63cdff2642SJohn Johansen } 64cdff2642SJohn Johansen 65cdff2642SJohn Johansen /** 663b0aaf58SJohn Johansen * skipn_spaces - Removes leading whitespace from @str. 673b0aaf58SJohn Johansen * @str: The string to be stripped. 683b0aaf58SJohn Johansen * 693b0aaf58SJohn Johansen * Returns a pointer to the first non-whitespace character in @str. 703b0aaf58SJohn Johansen * if all whitespace will return NULL 713b0aaf58SJohn Johansen */ 723b0aaf58SJohn Johansen 73b91deb9dSJohn Johansen const char *skipn_spaces(const char *str, size_t n) 743b0aaf58SJohn Johansen { 753b0aaf58SJohn Johansen for (; n && isspace(*str); --n) 763b0aaf58SJohn Johansen ++str; 773b0aaf58SJohn Johansen if (n) 783b0aaf58SJohn Johansen return (char *)str; 793b0aaf58SJohn Johansen return NULL; 803b0aaf58SJohn Johansen } 813b0aaf58SJohn Johansen 823b0aaf58SJohn Johansen const char *aa_splitn_fqname(const char *fqname, size_t n, const char **ns_name, 833b0aaf58SJohn Johansen size_t *ns_len) 843b0aaf58SJohn Johansen { 853b0aaf58SJohn Johansen const char *end = fqname + n; 863b0aaf58SJohn Johansen const char *name = skipn_spaces(fqname, n); 873b0aaf58SJohn Johansen 883b0aaf58SJohn Johansen if (!name) 893b0aaf58SJohn Johansen return NULL; 903b0aaf58SJohn Johansen *ns_name = NULL; 913b0aaf58SJohn Johansen *ns_len = 0; 923b0aaf58SJohn Johansen if (name[0] == ':') { 933b0aaf58SJohn Johansen char *split = strnchr(&name[1], end - &name[1], ':'); 943b0aaf58SJohn Johansen *ns_name = skipn_spaces(&name[1], end - &name[1]); 953b0aaf58SJohn Johansen if (!*ns_name) 963b0aaf58SJohn Johansen return NULL; 973b0aaf58SJohn Johansen if (split) { 983b0aaf58SJohn Johansen *ns_len = split - *ns_name; 993b0aaf58SJohn Johansen if (*ns_len == 0) 1003b0aaf58SJohn Johansen *ns_name = NULL; 1013b0aaf58SJohn Johansen split++; 1023b0aaf58SJohn Johansen if (end - split > 1 && strncmp(split, "//", 2) == 0) 1033b0aaf58SJohn Johansen split += 2; 1043b0aaf58SJohn Johansen name = skipn_spaces(split, end - split); 1053b0aaf58SJohn Johansen } else { 1063b0aaf58SJohn Johansen /* a ns name without a following profile is allowed */ 1073b0aaf58SJohn Johansen name = NULL; 1083b0aaf58SJohn Johansen *ns_len = end - *ns_name; 1093b0aaf58SJohn Johansen } 1103b0aaf58SJohn Johansen } 1113b0aaf58SJohn Johansen if (name && *name == 0) 1123b0aaf58SJohn Johansen name = NULL; 1133b0aaf58SJohn Johansen 1143b0aaf58SJohn Johansen return name; 1153b0aaf58SJohn Johansen } 1163b0aaf58SJohn Johansen 1173b0aaf58SJohn Johansen /** 118cdff2642SJohn Johansen * aa_info_message - log a none profile related status message 119cdff2642SJohn Johansen * @str: message to log 120cdff2642SJohn Johansen */ 121cdff2642SJohn Johansen void aa_info_message(const char *str) 122cdff2642SJohn Johansen { 123cdff2642SJohn Johansen if (audit_enabled) { 124ef88a7acSJohn Johansen DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, NULL); 125ef88a7acSJohn Johansen 126ef88a7acSJohn Johansen aad(&sa)->info = str; 127cdff2642SJohn Johansen aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL); 128cdff2642SJohn Johansen } 129cdff2642SJohn Johansen printk(KERN_INFO "AppArmor: %s\n", str); 130cdff2642SJohn Johansen } 131cdff2642SJohn Johansen 132*e53cfe6cSJohn Johansen const char aa_file_perm_chrs[] = "xwracd km l "; 133*e53cfe6cSJohn Johansen const char *aa_file_perm_names[] = { 134*e53cfe6cSJohn Johansen "exec", 135*e53cfe6cSJohn Johansen "write", 136*e53cfe6cSJohn Johansen "read", 137*e53cfe6cSJohn Johansen "append", 138*e53cfe6cSJohn Johansen 139*e53cfe6cSJohn Johansen "create", 140*e53cfe6cSJohn Johansen "delete", 141*e53cfe6cSJohn Johansen "open", 142*e53cfe6cSJohn Johansen "rename", 143*e53cfe6cSJohn Johansen 144*e53cfe6cSJohn Johansen "setattr", 145*e53cfe6cSJohn Johansen "getattr", 146*e53cfe6cSJohn Johansen "setcred", 147*e53cfe6cSJohn Johansen "getcred", 148*e53cfe6cSJohn Johansen 149*e53cfe6cSJohn Johansen "chmod", 150*e53cfe6cSJohn Johansen "chown", 151*e53cfe6cSJohn Johansen "chgrp", 152*e53cfe6cSJohn Johansen "lock", 153*e53cfe6cSJohn Johansen 154*e53cfe6cSJohn Johansen "mmap", 155*e53cfe6cSJohn Johansen "mprot", 156*e53cfe6cSJohn Johansen "link", 157*e53cfe6cSJohn Johansen "snapshot", 158*e53cfe6cSJohn Johansen 159*e53cfe6cSJohn Johansen "unknown", 160*e53cfe6cSJohn Johansen "unknown", 161*e53cfe6cSJohn Johansen "unknown", 162*e53cfe6cSJohn Johansen "unknown", 163*e53cfe6cSJohn Johansen 164*e53cfe6cSJohn Johansen "unknown", 165*e53cfe6cSJohn Johansen "unknown", 166*e53cfe6cSJohn Johansen "unknown", 167*e53cfe6cSJohn Johansen "unknown", 168*e53cfe6cSJohn Johansen 169*e53cfe6cSJohn Johansen "stack", 170*e53cfe6cSJohn Johansen "change_onexec", 171*e53cfe6cSJohn Johansen "change_profile", 172*e53cfe6cSJohn Johansen "change_hat", 173*e53cfe6cSJohn Johansen }; 174*e53cfe6cSJohn Johansen 175*e53cfe6cSJohn Johansen /** 176*e53cfe6cSJohn Johansen * aa_perm_mask_to_str - convert a perm mask to its short string 177*e53cfe6cSJohn Johansen * @str: character buffer to store string in (at least 10 characters) 178*e53cfe6cSJohn Johansen * @mask: permission mask to convert 179*e53cfe6cSJohn Johansen */ 180*e53cfe6cSJohn Johansen void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask) 181*e53cfe6cSJohn Johansen { 182*e53cfe6cSJohn Johansen unsigned int i, perm = 1; 183*e53cfe6cSJohn Johansen 184*e53cfe6cSJohn Johansen for (i = 0; i < 32; perm <<= 1, i++) { 185*e53cfe6cSJohn Johansen if (mask & perm) 186*e53cfe6cSJohn Johansen *str++ = chrs[i]; 187*e53cfe6cSJohn Johansen } 188*e53cfe6cSJohn Johansen *str = '\0'; 189*e53cfe6cSJohn Johansen } 190*e53cfe6cSJohn Johansen 191cdff2642SJohn Johansen /** 192fe6bb31fSJohn Johansen * aa_policy_init - initialize a policy structure 193fe6bb31fSJohn Johansen * @policy: policy to initialize (NOT NULL) 194fe6bb31fSJohn Johansen * @prefix: prefix name if any is required. (MAYBE NULL) 195fe6bb31fSJohn Johansen * @name: name of the policy, init will make a copy of it (NOT NULL) 196fe6bb31fSJohn Johansen * 197fe6bb31fSJohn Johansen * Note: this fn creates a copy of strings passed in 198fe6bb31fSJohn Johansen * 199fe6bb31fSJohn Johansen * Returns: true if policy init successful 200fe6bb31fSJohn Johansen */ 201fe6bb31fSJohn Johansen bool aa_policy_init(struct aa_policy *policy, const char *prefix, 202d102d895SJohn Johansen const char *name, gfp_t gfp) 203fe6bb31fSJohn Johansen { 204fe6bb31fSJohn Johansen /* freed by policy_free */ 205fe6bb31fSJohn Johansen if (prefix) { 206fe6bb31fSJohn Johansen policy->hname = kmalloc(strlen(prefix) + strlen(name) + 3, 207d102d895SJohn Johansen gfp); 208fe6bb31fSJohn Johansen if (policy->hname) 209bbe4a7c8SJohn Johansen sprintf((char *)policy->hname, "%s//%s", prefix, name); 210fe6bb31fSJohn Johansen } else 211d102d895SJohn Johansen policy->hname = kstrdup(name, gfp); 212fe6bb31fSJohn Johansen if (!policy->hname) 213b9c42ac7Skbuild test robot return false; 214fe6bb31fSJohn Johansen /* base.name is a substring of fqname */ 215d102d895SJohn Johansen policy->name = basename(policy->hname); 216fe6bb31fSJohn Johansen INIT_LIST_HEAD(&policy->list); 217fe6bb31fSJohn Johansen INIT_LIST_HEAD(&policy->profiles); 218fe6bb31fSJohn Johansen 219b9c42ac7Skbuild test robot return true; 220fe6bb31fSJohn Johansen } 221fe6bb31fSJohn Johansen 222fe6bb31fSJohn Johansen /** 223fe6bb31fSJohn Johansen * aa_policy_destroy - free the elements referenced by @policy 224fe6bb31fSJohn Johansen * @policy: policy that is to have its elements freed (NOT NULL) 225fe6bb31fSJohn Johansen */ 226fe6bb31fSJohn Johansen void aa_policy_destroy(struct aa_policy *policy) 227fe6bb31fSJohn Johansen { 2285fd1b95fSJohn Johansen AA_BUG(on_list_rcu(&policy->profiles)); 2295fd1b95fSJohn Johansen AA_BUG(on_list_rcu(&policy->list)); 230fe6bb31fSJohn Johansen 231fe6bb31fSJohn Johansen /* don't free name as its a subset of hname */ 232fe6bb31fSJohn Johansen kzfree(policy->hname); 233fe6bb31fSJohn Johansen } 234