xref: /openbmc/linux/security/apparmor/lib.c (revision cdff264264254e0fabc8107a33f3bb75a95e981f)
1*cdff2642SJohn Johansen /*
2*cdff2642SJohn Johansen  * AppArmor security module
3*cdff2642SJohn Johansen  *
4*cdff2642SJohn Johansen  * This file contains basic common functions used in AppArmor
5*cdff2642SJohn Johansen  *
6*cdff2642SJohn Johansen  * Copyright (C) 1998-2008 Novell/SUSE
7*cdff2642SJohn Johansen  * Copyright 2009-2010 Canonical Ltd.
8*cdff2642SJohn Johansen  *
9*cdff2642SJohn Johansen  * This program is free software; you can redistribute it and/or
10*cdff2642SJohn Johansen  * modify it under the terms of the GNU General Public License as
11*cdff2642SJohn Johansen  * published by the Free Software Foundation, version 2 of the
12*cdff2642SJohn Johansen  * License.
13*cdff2642SJohn Johansen  */
14*cdff2642SJohn Johansen 
15*cdff2642SJohn Johansen #include <linux/slab.h>
16*cdff2642SJohn Johansen #include <linux/string.h>
17*cdff2642SJohn Johansen #include <linux/vmalloc.h>
18*cdff2642SJohn Johansen 
19*cdff2642SJohn Johansen #include "include/audit.h"
20*cdff2642SJohn Johansen 
21*cdff2642SJohn Johansen 
22*cdff2642SJohn Johansen /**
23*cdff2642SJohn Johansen  * aa_split_fqname - split a fqname into a profile and namespace name
24*cdff2642SJohn Johansen  * @fqname: a full qualified name in namespace profile format (NOT NULL)
25*cdff2642SJohn Johansen  * @ns_name: pointer to portion of the string containing the ns name (NOT NULL)
26*cdff2642SJohn Johansen  *
27*cdff2642SJohn Johansen  * Returns: profile name or NULL if one is not specified
28*cdff2642SJohn Johansen  *
29*cdff2642SJohn Johansen  * Split a namespace name from a profile name (see policy.c for naming
30*cdff2642SJohn Johansen  * description).  If a portion of the name is missing it returns NULL for
31*cdff2642SJohn Johansen  * that portion.
32*cdff2642SJohn Johansen  *
33*cdff2642SJohn Johansen  * NOTE: may modify the @fqname string.  The pointers returned point
34*cdff2642SJohn Johansen  *       into the @fqname string.
35*cdff2642SJohn Johansen  */
36*cdff2642SJohn Johansen char *aa_split_fqname(char *fqname, char **ns_name)
37*cdff2642SJohn Johansen {
38*cdff2642SJohn Johansen 	char *name = strim(fqname);
39*cdff2642SJohn Johansen 
40*cdff2642SJohn Johansen 	*ns_name = NULL;
41*cdff2642SJohn Johansen 	if (name[0] == ':') {
42*cdff2642SJohn Johansen 		char *split = strchr(&name[1], ':');
43*cdff2642SJohn Johansen 		if (split) {
44*cdff2642SJohn Johansen 			/* overwrite ':' with \0 */
45*cdff2642SJohn Johansen 			*split = 0;
46*cdff2642SJohn Johansen 			name = skip_spaces(split + 1);
47*cdff2642SJohn Johansen 		} else
48*cdff2642SJohn Johansen 			/* a ns name without a following profile is allowed */
49*cdff2642SJohn Johansen 			name = NULL;
50*cdff2642SJohn Johansen 		*ns_name = &name[1];
51*cdff2642SJohn Johansen 	}
52*cdff2642SJohn Johansen 	if (name && *name == 0)
53*cdff2642SJohn Johansen 		name = NULL;
54*cdff2642SJohn Johansen 
55*cdff2642SJohn Johansen 	return name;
56*cdff2642SJohn Johansen }
57*cdff2642SJohn Johansen 
58*cdff2642SJohn Johansen /**
59*cdff2642SJohn Johansen  * aa_info_message - log a none profile related status message
60*cdff2642SJohn Johansen  * @str: message to log
61*cdff2642SJohn Johansen  */
62*cdff2642SJohn Johansen void aa_info_message(const char *str)
63*cdff2642SJohn Johansen {
64*cdff2642SJohn Johansen 	if (audit_enabled) {
65*cdff2642SJohn Johansen 		struct common_audit_data sa;
66*cdff2642SJohn Johansen 		COMMON_AUDIT_DATA_INIT(&sa, NONE);
67*cdff2642SJohn Johansen 		sa.aad.info = str;
68*cdff2642SJohn Johansen 		aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL);
69*cdff2642SJohn Johansen 	}
70*cdff2642SJohn Johansen 	printk(KERN_INFO "AppArmor: %s\n", str);
71*cdff2642SJohn Johansen }
72*cdff2642SJohn Johansen 
73*cdff2642SJohn Johansen /**
74*cdff2642SJohn Johansen  * kvmalloc - do allocation preferring kmalloc but falling back to vmalloc
75*cdff2642SJohn Johansen  * @size: size of allocation
76*cdff2642SJohn Johansen  *
77*cdff2642SJohn Johansen  * Return: allocated buffer or NULL if failed
78*cdff2642SJohn Johansen  *
79*cdff2642SJohn Johansen  * It is possible that policy being loaded from the user is larger than
80*cdff2642SJohn Johansen  * what can be allocated by kmalloc, in those cases fall back to vmalloc.
81*cdff2642SJohn Johansen  */
82*cdff2642SJohn Johansen void *kvmalloc(size_t size)
83*cdff2642SJohn Johansen {
84*cdff2642SJohn Johansen 	void *buffer = NULL;
85*cdff2642SJohn Johansen 
86*cdff2642SJohn Johansen 	if (size == 0)
87*cdff2642SJohn Johansen 		return NULL;
88*cdff2642SJohn Johansen 
89*cdff2642SJohn Johansen 	/* do not attempt kmalloc if we need more than 16 pages at once */
90*cdff2642SJohn Johansen 	if (size <= (16*PAGE_SIZE))
91*cdff2642SJohn Johansen 		buffer = kmalloc(size, GFP_NOIO | __GFP_NOWARN);
92*cdff2642SJohn Johansen 	if (!buffer) {
93*cdff2642SJohn Johansen 		/* see kvfree for why size must be at least work_struct size
94*cdff2642SJohn Johansen 		 * when allocated via vmalloc
95*cdff2642SJohn Johansen 		 */
96*cdff2642SJohn Johansen 		if (size < sizeof(struct work_struct))
97*cdff2642SJohn Johansen 			size = sizeof(struct work_struct);
98*cdff2642SJohn Johansen 		buffer = vmalloc(size);
99*cdff2642SJohn Johansen 	}
100*cdff2642SJohn Johansen 	return buffer;
101*cdff2642SJohn Johansen }
102*cdff2642SJohn Johansen 
103*cdff2642SJohn Johansen /**
104*cdff2642SJohn Johansen  * do_vfree - workqueue routine for freeing vmalloced memory
105*cdff2642SJohn Johansen  * @work: data to be freed
106*cdff2642SJohn Johansen  *
107*cdff2642SJohn Johansen  * The work_struct is overlaid to the data being freed, as at the point
108*cdff2642SJohn Johansen  * the work is scheduled the data is no longer valid, be its freeing
109*cdff2642SJohn Johansen  * needs to be delayed until safe.
110*cdff2642SJohn Johansen  */
111*cdff2642SJohn Johansen static void do_vfree(struct work_struct *work)
112*cdff2642SJohn Johansen {
113*cdff2642SJohn Johansen 	vfree(work);
114*cdff2642SJohn Johansen }
115*cdff2642SJohn Johansen 
116*cdff2642SJohn Johansen /**
117*cdff2642SJohn Johansen  * kvfree - free an allocation do by kvmalloc
118*cdff2642SJohn Johansen  * @buffer: buffer to free (MAYBE_NULL)
119*cdff2642SJohn Johansen  *
120*cdff2642SJohn Johansen  * Free a buffer allocated by kvmalloc
121*cdff2642SJohn Johansen  */
122*cdff2642SJohn Johansen void kvfree(void *buffer)
123*cdff2642SJohn Johansen {
124*cdff2642SJohn Johansen 	if (is_vmalloc_addr(buffer)) {
125*cdff2642SJohn Johansen 		/* Data is no longer valid so just use the allocated space
126*cdff2642SJohn Johansen 		 * as the work_struct
127*cdff2642SJohn Johansen 		 */
128*cdff2642SJohn Johansen 		struct work_struct *work = (struct work_struct *) buffer;
129*cdff2642SJohn Johansen 		INIT_WORK(work, do_vfree);
130*cdff2642SJohn Johansen 		schedule_work(work);
131*cdff2642SJohn Johansen 	} else
132*cdff2642SJohn Johansen 		kfree(buffer);
133*cdff2642SJohn Johansen }
134