Linux Audio

Check our new training course

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