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