blob: 90d4631ddafeb1f369805b0015791af282c3c95f [file] [log] [blame]
John Johansencdff2642010-07-29 14:47:57 -07001/*
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
John Johansen3b0aaf52017-01-16 00:42:23 -080015#include <linux/ctype.h>
Alexey Dobriyanb7f080c2011-06-16 11:01:34 +000016#include <linux/mm.h>
John Johansencdff2642010-07-29 14:47:57 -070017#include <linux/slab.h>
18#include <linux/string.h>
19#include <linux/vmalloc.h>
20
21#include "include/audit.h"
James Morris32c3df62011-08-29 11:15:25 +100022#include "include/apparmor.h"
John Johansen12557dc2017-01-16 00:42:13 -080023#include "include/lib.h"
John Johansenfc7e0b22017-05-26 01:57:09 -070024#include "include/perms.h"
John Johansenfe6bb312017-01-16 00:42:14 -080025#include "include/policy.h"
John Johansencdff2642010-07-29 14:47:57 -070026
27/**
28 * aa_split_fqname - split a fqname into a profile and namespace name
29 * @fqname: a full qualified name in namespace profile format (NOT NULL)
30 * @ns_name: pointer to portion of the string containing the ns name (NOT NULL)
31 *
32 * Returns: profile name or NULL if one is not specified
33 *
34 * Split a namespace name from a profile name (see policy.c for naming
35 * description). If a portion of the name is missing it returns NULL for
36 * that portion.
37 *
38 * NOTE: may modify the @fqname string. The pointers returned point
39 * into the @fqname string.
40 */
41char *aa_split_fqname(char *fqname, char **ns_name)
42{
43 char *name = strim(fqname);
44
45 *ns_name = NULL;
46 if (name[0] == ':') {
47 char *split = strchr(&name[1], ':');
John Johansen04ccd532010-08-27 18:33:28 -070048 *ns_name = skip_spaces(&name[1]);
John Johansencdff2642010-07-29 14:47:57 -070049 if (split) {
50 /* overwrite ':' with \0 */
John Johansen2654bfb2013-02-27 03:45:05 -080051 *split++ = 0;
52 if (strncmp(split, "//", 2) == 0)
53 split += 2;
54 name = skip_spaces(split);
John Johansencdff2642010-07-29 14:47:57 -070055 } else
56 /* a ns name without a following profile is allowed */
57 name = NULL;
John Johansencdff2642010-07-29 14:47:57 -070058 }
59 if (name && *name == 0)
60 name = NULL;
61
62 return name;
63}
64
65/**
John Johansen3b0aaf52017-01-16 00:42:23 -080066 * skipn_spaces - Removes leading whitespace from @str.
67 * @str: The string to be stripped.
68 *
69 * Returns a pointer to the first non-whitespace character in @str.
70 * if all whitespace will return NULL
71 */
72
John Johansenb91deb92017-05-22 02:47:22 -070073const char *skipn_spaces(const char *str, size_t n)
John Johansen3b0aaf52017-01-16 00:42:23 -080074{
75 for (; n && isspace(*str); --n)
76 ++str;
77 if (n)
78 return (char *)str;
79 return NULL;
80}
81
82const char *aa_splitn_fqname(const char *fqname, size_t n, const char **ns_name,
83 size_t *ns_len)
84{
85 const char *end = fqname + n;
86 const char *name = skipn_spaces(fqname, n);
87
88 if (!name)
89 return NULL;
90 *ns_name = NULL;
91 *ns_len = 0;
92 if (name[0] == ':') {
93 char *split = strnchr(&name[1], end - &name[1], ':');
94 *ns_name = skipn_spaces(&name[1], end - &name[1]);
95 if (!*ns_name)
96 return NULL;
97 if (split) {
98 *ns_len = split - *ns_name;
99 if (*ns_len == 0)
100 *ns_name = NULL;
101 split++;
102 if (end - split > 1 && strncmp(split, "//", 2) == 0)
103 split += 2;
104 name = skipn_spaces(split, end - split);
105 } else {
106 /* a ns name without a following profile is allowed */
107 name = NULL;
108 *ns_len = end - *ns_name;
109 }
110 }
111 if (name && *name == 0)
112 name = NULL;
113
114 return name;
115}
116
117/**
John Johansencdff2642010-07-29 14:47:57 -0700118 * aa_info_message - log a none profile related status message
119 * @str: message to log
120 */
121void aa_info_message(const char *str)
122{
123 if (audit_enabled) {
John Johansenef88a7a2017-01-16 00:43:02 -0800124 DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, NULL);
125
126 aad(&sa)->info = str;
John Johansencdff2642010-07-29 14:47:57 -0700127 aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL);
128 }
129 printk(KERN_INFO "AppArmor: %s\n", str);
130}
131
John Johansene53cfe62017-05-26 15:07:22 -0700132const char aa_file_perm_chrs[] = "xwracd km l ";
133const char *aa_file_perm_names[] = {
134 "exec",
135 "write",
136 "read",
137 "append",
138
139 "create",
140 "delete",
141 "open",
142 "rename",
143
144 "setattr",
145 "getattr",
146 "setcred",
147 "getcred",
148
149 "chmod",
150 "chown",
151 "chgrp",
152 "lock",
153
154 "mmap",
155 "mprot",
156 "link",
157 "snapshot",
158
159 "unknown",
160 "unknown",
161 "unknown",
162 "unknown",
163
164 "unknown",
165 "unknown",
166 "unknown",
167 "unknown",
168
169 "stack",
170 "change_onexec",
171 "change_profile",
172 "change_hat",
173};
174
175/**
176 * aa_perm_mask_to_str - convert a perm mask to its short string
177 * @str: character buffer to store string in (at least 10 characters)
178 * @mask: permission mask to convert
179 */
180void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask)
181{
182 unsigned int i, perm = 1;
183
184 for (i = 0; i < 32; perm <<= 1, i++) {
185 if (mask & perm)
186 *str++ = chrs[i];
187 }
188 *str = '\0';
189}
190
John Johansencdff2642010-07-29 14:47:57 -0700191/**
John Johansenfe6bb312017-01-16 00:42:14 -0800192 * aa_policy_init - initialize a policy structure
193 * @policy: policy to initialize (NOT NULL)
194 * @prefix: prefix name if any is required. (MAYBE NULL)
195 * @name: name of the policy, init will make a copy of it (NOT NULL)
196 *
197 * Note: this fn creates a copy of strings passed in
198 *
199 * Returns: true if policy init successful
200 */
201bool aa_policy_init(struct aa_policy *policy, const char *prefix,
John Johansend102d892017-01-16 00:42:31 -0800202 const char *name, gfp_t gfp)
John Johansenfe6bb312017-01-16 00:42:14 -0800203{
204 /* freed by policy_free */
205 if (prefix) {
206 policy->hname = kmalloc(strlen(prefix) + strlen(name) + 3,
John Johansend102d892017-01-16 00:42:31 -0800207 gfp);
John Johansenfe6bb312017-01-16 00:42:14 -0800208 if (policy->hname)
John Johansenbbe4a7c2017-01-16 00:42:30 -0800209 sprintf((char *)policy->hname, "%s//%s", prefix, name);
John Johansenfe6bb312017-01-16 00:42:14 -0800210 } else
John Johansend102d892017-01-16 00:42:31 -0800211 policy->hname = kstrdup(name, gfp);
John Johansenfe6bb312017-01-16 00:42:14 -0800212 if (!policy->hname)
kbuild test robotb9c42ac2017-04-06 06:55:19 -0700213 return false;
John Johansenfe6bb312017-01-16 00:42:14 -0800214 /* base.name is a substring of fqname */
John Johansend102d892017-01-16 00:42:31 -0800215 policy->name = basename(policy->hname);
John Johansenfe6bb312017-01-16 00:42:14 -0800216 INIT_LIST_HEAD(&policy->list);
217 INIT_LIST_HEAD(&policy->profiles);
218
kbuild test robotb9c42ac2017-04-06 06:55:19 -0700219 return true;
John Johansenfe6bb312017-01-16 00:42:14 -0800220}
221
222/**
223 * aa_policy_destroy - free the elements referenced by @policy
224 * @policy: policy that is to have its elements freed (NOT NULL)
225 */
226void aa_policy_destroy(struct aa_policy *policy)
227{
John Johansen5fd1b952017-01-16 00:42:32 -0800228 AA_BUG(on_list_rcu(&policy->profiles));
229 AA_BUG(on_list_rcu(&policy->list));
John Johansenfe6bb312017-01-16 00:42:14 -0800230
231 /* don't free name as its a subset of hname */
232 kzfree(policy->hname);
233}