aboutsummaryrefslogtreecommitdiffstats
path: root/security/apparmor
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /security/apparmor
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'security/apparmor')
-rw-r--r--security/apparmor/Makefile27
-rw-r--r--security/apparmor/apparmorfs.c197
-rw-r--r--security/apparmor/audit.c62
-rw-r--r--security/apparmor/capability.c10
-rw-r--r--security/apparmor/domain.c47
-rw-r--r--security/apparmor/file.c89
-rw-r--r--security/apparmor/include/apparmor.h25
-rw-r--r--security/apparmor/include/apparmorfs.h44
-rw-r--r--security/apparmor/include/audit.h38
-rw-r--r--security/apparmor/include/file.h6
-rw-r--r--security/apparmor/include/match.h3
-rw-r--r--security/apparmor/include/path.h3
-rw-r--r--security/apparmor/include/policy.h15
-rw-r--r--security/apparmor/include/resource.h4
-rw-r--r--security/apparmor/ipc.c13
-rw-r--r--security/apparmor/lib.c7
-rw-r--r--security/apparmor/lsm.c68
-rw-r--r--security/apparmor/match.c80
-rw-r--r--security/apparmor/path.c59
-rw-r--r--security/apparmor/policy.c45
-rw-r--r--security/apparmor/policy_unpack.c63
-rw-r--r--security/apparmor/procattr.c1
-rw-r--r--security/apparmor/resource.c19
23 files changed, 251 insertions, 674 deletions
diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
index 5706b74c857..2dafe50a2e2 100644
--- a/security/apparmor/Makefile
+++ b/security/apparmor/Makefile
@@ -15,7 +15,7 @@ clean-files := capability_names.h rlim_names.h
15# to 15# to
16# [1] = "dac_override", 16# [1] = "dac_override",
17quiet_cmd_make-caps = GEN $@ 17quiet_cmd_make-caps = GEN $@
18cmd_make-caps = echo "static const char *const capability_names[] = {" > $@ ;\ 18cmd_make-caps = echo "static const char *capability_names[] = {" > $@ ;\
19 sed $< >>$@ -r -n -e '/CAP_FS_MASK/d' \ 19 sed $< >>$@ -r -n -e '/CAP_FS_MASK/d' \
20 -e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/[\2] = "\L\1",/p';\ 20 -e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/[\2] = "\L\1",/p';\
21 echo "};" >> $@ 21 echo "};" >> $@
@@ -28,38 +28,25 @@ cmd_make-caps = echo "static const char *const capability_names[] = {" > $@ ;\
28# [RLIMIT_STACK] = "stack", 28# [RLIMIT_STACK] = "stack",
29# 29#
30# and build a second integer table (with the second sed cmd), that maps 30# and build a second integer table (with the second sed cmd), that maps
31# RLIMIT defines to the order defined in asm-generic/resource.h This is 31# RLIMIT defines to the order defined in asm-generic/resource.h Thi is
32# required by policy load to map policy ordering of RLIMITs to internal 32# required by policy load to map policy ordering of RLIMITs to internal
33# ordering for architectures that redefine an RLIMIT. 33# ordering for architectures that redefine an RLIMIT.
34# Transforms lines from 34# Transforms lines from
35# #define RLIMIT_STACK 3 /* max stack size */ 35# #define RLIMIT_STACK 3 /* max stack size */
36# to 36# to
37# RLIMIT_STACK, 37# RLIMIT_STACK,
38#
39# and build the securityfs entries for the mapping.
40# Transforms lines from
41# #define RLIMIT_FSIZE 1 /* Maximum filesize */
42# #define RLIMIT_STACK 3 /* max stack size */
43# to
44# #define AA_FS_RLIMIT_MASK "fsize stack"
45quiet_cmd_make-rlim = GEN $@ 38quiet_cmd_make-rlim = GEN $@
46cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \ 39cmd_make-rlim = echo "static const char *rlim_names[] = {" > $@ ;\
47 > $@ ;\
48 sed $< >> $@ -r -n \ 40 sed $< >> $@ -r -n \
49 -e 's/^\# ?define[ \t]+(RLIMIT_([A-Z0-9_]+)).*/[\1] = "\L\2",/p';\ 41 -e 's/^\# ?define[ \t]+(RLIMIT_([A-Z0-9_]+)).*/[\1] = "\L\2",/p';\
50 echo "};" >> $@ ;\ 42 echo "};" >> $@ ;\
51 echo "static const int rlim_map[RLIM_NLIMITS] = {" >> $@ ;\ 43 echo "static const int rlim_map[] = {" >> $@ ;\
52 sed -r -n "s/^\# ?define[ \t]+(RLIMIT_[A-Z0-9_]+).*/\1,/p" $< >> $@ ;\ 44 sed -r -n "s/^\# ?define[ \t]+(RLIMIT_[A-Z0-9_]+).*/\1,/p" $< >> $@ ;\
53 echo "};" >> $@ ; \ 45 echo "};" >> $@
54 echo -n '\#define AA_FS_RLIMIT_MASK "' >> $@ ;\
55 sed -r -n 's/^\# ?define[ \t]+RLIMIT_([A-Z0-9_]+).*/\L\1/p' $< | \
56 tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
57 46
58$(obj)/capability.o : $(obj)/capability_names.h 47$(obj)/capability.o : $(obj)/capability_names.h
59$(obj)/resource.o : $(obj)/rlim_names.h 48$(obj)/resource.o : $(obj)/rlim_names.h
60$(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \ 49$(obj)/capability_names.h : $(srctree)/include/linux/capability.h
61 $(src)/Makefile
62 $(call cmd,make-caps) 50 $(call cmd,make-caps)
63$(obj)/rlim_names.h : $(srctree)/include/uapi/asm-generic/resource.h \ 51$(obj)/rlim_names.h : $(srctree)/include/asm-generic/resource.h
64 $(src)/Makefile
65 $(call cmd,make-rlim) 52 $(call cmd,make-rlim)
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 16c15ec6f67..0848292982a 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -18,14 +18,12 @@
18#include <linux/seq_file.h> 18#include <linux/seq_file.h>
19#include <linux/uaccess.h> 19#include <linux/uaccess.h>
20#include <linux/namei.h> 20#include <linux/namei.h>
21#include <linux/capability.h>
22 21
23#include "include/apparmor.h" 22#include "include/apparmor.h"
24#include "include/apparmorfs.h" 23#include "include/apparmorfs.h"
25#include "include/audit.h" 24#include "include/audit.h"
26#include "include/context.h" 25#include "include/context.h"
27#include "include/policy.h" 26#include "include/policy.h"
28#include "include/resource.h"
29 27
30/** 28/**
31 * aa_simple_write_to_buffer - common routine for getting policy from user 29 * aa_simple_write_to_buffer - common routine for getting policy from user
@@ -144,166 +142,38 @@ static const struct file_operations aa_fs_profile_remove = {
144 .llseek = default_llseek, 142 .llseek = default_llseek,
145}; 143};
146 144
147static int aa_fs_seq_show(struct seq_file *seq, void *v)
148{
149 struct aa_fs_entry *fs_file = seq->private;
150
151 if (!fs_file)
152 return 0;
153
154 switch (fs_file->v_type) {
155 case AA_FS_TYPE_BOOLEAN:
156 seq_printf(seq, "%s\n", fs_file->v.boolean ? "yes" : "no");
157 break;
158 case AA_FS_TYPE_STRING:
159 seq_printf(seq, "%s\n", fs_file->v.string);
160 break;
161 case AA_FS_TYPE_U64:
162 seq_printf(seq, "%#08lx\n", fs_file->v.u64);
163 break;
164 default:
165 /* Ignore unpritable entry types. */
166 break;
167 }
168
169 return 0;
170}
171
172static int aa_fs_seq_open(struct inode *inode, struct file *file)
173{
174 return single_open(file, aa_fs_seq_show, inode->i_private);
175}
176
177const struct file_operations aa_fs_seq_file_ops = {
178 .owner = THIS_MODULE,
179 .open = aa_fs_seq_open,
180 .read = seq_read,
181 .llseek = seq_lseek,
182 .release = single_release,
183};
184
185/** Base file system setup **/ 145/** Base file system setup **/
186 146
187static struct aa_fs_entry aa_fs_entry_file[] = { 147static struct dentry *aa_fs_dentry __initdata;
188 AA_FS_FILE_STRING("mask", "create read write exec append mmap_exec " \
189 "link lock"),
190 { }
191};
192 148
193static struct aa_fs_entry aa_fs_entry_domain[] = { 149static void __init aafs_remove(const char *name)
194 AA_FS_FILE_BOOLEAN("change_hat", 1),
195 AA_FS_FILE_BOOLEAN("change_hatv", 1),
196 AA_FS_FILE_BOOLEAN("change_onexec", 1),
197 AA_FS_FILE_BOOLEAN("change_profile", 1),
198 { }
199};
200
201static struct aa_fs_entry aa_fs_entry_features[] = {
202 AA_FS_DIR("domain", aa_fs_entry_domain),
203 AA_FS_DIR("file", aa_fs_entry_file),
204 AA_FS_FILE_U64("capability", VFS_CAP_FLAGS_MASK),
205 AA_FS_DIR("rlimit", aa_fs_entry_rlimit),
206 { }
207};
208
209static struct aa_fs_entry aa_fs_entry_apparmor[] = {
210 AA_FS_FILE_FOPS(".load", 0640, &aa_fs_profile_load),
211 AA_FS_FILE_FOPS(".replace", 0640, &aa_fs_profile_replace),
212 AA_FS_FILE_FOPS(".remove", 0640, &aa_fs_profile_remove),
213 AA_FS_DIR("features", aa_fs_entry_features),
214 { }
215};
216
217static struct aa_fs_entry aa_fs_entry =
218 AA_FS_DIR("apparmor", aa_fs_entry_apparmor);
219
220/**
221 * aafs_create_file - create a file entry in the apparmor securityfs
222 * @fs_file: aa_fs_entry to build an entry for (NOT NULL)
223 * @parent: the parent dentry in the securityfs
224 *
225 * Use aafs_remove_file to remove entries created with this fn.
226 */
227static int __init aafs_create_file(struct aa_fs_entry *fs_file,
228 struct dentry *parent)
229{ 150{
230 int error = 0; 151 struct dentry *dentry;
231
232 fs_file->dentry = securityfs_create_file(fs_file->name,
233 S_IFREG | fs_file->mode,
234 parent, fs_file,
235 fs_file->file_ops);
236 if (IS_ERR(fs_file->dentry)) {
237 error = PTR_ERR(fs_file->dentry);
238 fs_file->dentry = NULL;
239 }
240 return error;
241}
242 152
243/** 153 dentry = lookup_one_len(name, aa_fs_dentry, strlen(name));
244 * aafs_create_dir - recursively create a directory entry in the securityfs 154 if (!IS_ERR(dentry)) {
245 * @fs_dir: aa_fs_entry (and all child entries) to build (NOT NULL) 155 securityfs_remove(dentry);
246 * @parent: the parent dentry in the securityfs 156 dput(dentry);
247 *
248 * Use aafs_remove_dir to remove entries created with this fn.
249 */
250static int __init aafs_create_dir(struct aa_fs_entry *fs_dir,
251 struct dentry *parent)
252{
253 int error;
254 struct aa_fs_entry *fs_file;
255
256 fs_dir->dentry = securityfs_create_dir(fs_dir->name, parent);
257 if (IS_ERR(fs_dir->dentry)) {
258 error = PTR_ERR(fs_dir->dentry);
259 fs_dir->dentry = NULL;
260 goto failed;
261 }
262
263 for (fs_file = fs_dir->v.files; fs_file->name; ++fs_file) {
264 if (fs_file->v_type == AA_FS_TYPE_DIR)
265 error = aafs_create_dir(fs_file, fs_dir->dentry);
266 else
267 error = aafs_create_file(fs_file, fs_dir->dentry);
268 if (error)
269 goto failed;
270 } 157 }
271
272 return 0;
273
274failed:
275 return error;
276}
277
278/**
279 * aafs_remove_file - drop a single file entry in the apparmor securityfs
280 * @fs_file: aa_fs_entry to detach from the securityfs (NOT NULL)
281 */
282static void __init aafs_remove_file(struct aa_fs_entry *fs_file)
283{
284 if (!fs_file->dentry)
285 return;
286
287 securityfs_remove(fs_file->dentry);
288 fs_file->dentry = NULL;
289} 158}
290 159
291/** 160/**
292 * aafs_remove_dir - recursively drop a directory entry from the securityfs 161 * aafs_create - create an entry in the apparmor filesystem
293 * @fs_dir: aa_fs_entry (and all child entries) to detach (NOT NULL) 162 * @name: name of the entry (NOT NULL)
163 * @mask: file permission mask of the file
164 * @fops: file operations for the file (NOT NULL)
165 *
166 * Used aafs_remove to remove entries created with this fn.
294 */ 167 */
295static void __init aafs_remove_dir(struct aa_fs_entry *fs_dir) 168static int __init aafs_create(const char *name, int mask,
169 const struct file_operations *fops)
296{ 170{
297 struct aa_fs_entry *fs_file; 171 struct dentry *dentry;
298 172
299 for (fs_file = fs_dir->v.files; fs_file->name; ++fs_file) { 173 dentry = securityfs_create_file(name, S_IFREG | mask, aa_fs_dentry,
300 if (fs_file->v_type == AA_FS_TYPE_DIR) 174 NULL, fops);
301 aafs_remove_dir(fs_file);
302 else
303 aafs_remove_file(fs_file);
304 }
305 175
306 aafs_remove_file(fs_dir); 176 return IS_ERR(dentry) ? PTR_ERR(dentry) : 0;
307} 177}
308 178
309/** 179/**
@@ -313,7 +183,14 @@ static void __init aafs_remove_dir(struct aa_fs_entry *fs_dir)
313 */ 183 */
314void __init aa_destroy_aafs(void) 184void __init aa_destroy_aafs(void)
315{ 185{
316 aafs_remove_dir(&aa_fs_entry); 186 if (aa_fs_dentry) {
187 aafs_remove(".remove");
188 aafs_remove(".replace");
189 aafs_remove(".load");
190
191 securityfs_remove(aa_fs_dentry);
192 aa_fs_dentry = NULL;
193 }
317} 194}
318 195
319/** 196/**
@@ -323,20 +200,32 @@ void __init aa_destroy_aafs(void)
323 * 200 *
324 * Returns: error on failure 201 * Returns: error on failure
325 */ 202 */
326static int __init aa_create_aafs(void) 203int __init aa_create_aafs(void)
327{ 204{
328 int error; 205 int error;
329 206
330 if (!apparmor_initialized) 207 if (!apparmor_initialized)
331 return 0; 208 return 0;
332 209
333 if (aa_fs_entry.dentry) { 210 if (aa_fs_dentry) {
334 AA_ERROR("%s: AppArmor securityfs already exists\n", __func__); 211 AA_ERROR("%s: AppArmor securityfs already exists\n", __func__);
335 return -EEXIST; 212 return -EEXIST;
336 } 213 }
337 214
338 /* Populate fs tree. */ 215 aa_fs_dentry = securityfs_create_dir("apparmor", NULL);
339 error = aafs_create_dir(&aa_fs_entry, NULL); 216 if (IS_ERR(aa_fs_dentry)) {
217 error = PTR_ERR(aa_fs_dentry);
218 aa_fs_dentry = NULL;
219 goto error;
220 }
221
222 error = aafs_create(".load", 0640, &aa_fs_profile_load);
223 if (error)
224 goto error;
225 error = aafs_create(".replace", 0640, &aa_fs_profile_replace);
226 if (error)
227 goto error;
228 error = aafs_create(".remove", 0640, &aa_fs_profile_remove);
340 if (error) 229 if (error)
341 goto error; 230 goto error;
342 231
diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c
index 3ae28db5a64..96502b22b26 100644
--- a/security/apparmor/audit.c
+++ b/security/apparmor/audit.c
@@ -19,7 +19,7 @@
19#include "include/audit.h" 19#include "include/audit.h"
20#include "include/policy.h" 20#include "include/policy.h"
21 21
22const char *const op_table[] = { 22const char *op_table[] = {
23 "null", 23 "null",
24 24
25 "sysctl", 25 "sysctl",
@@ -73,7 +73,7 @@ const char *const op_table[] = {
73 "profile_remove" 73 "profile_remove"
74}; 74};
75 75
76const char *const audit_mode_names[] = { 76const char *audit_mode_names[] = {
77 "normal", 77 "normal",
78 "quiet_denied", 78 "quiet_denied",
79 "quiet", 79 "quiet",
@@ -81,7 +81,7 @@ const char *const audit_mode_names[] = {
81 "all" 81 "all"
82}; 82};
83 83
84static const char *const aa_audit_type[] = { 84static char *aa_audit_type[] = {
85 "AUDIT", 85 "AUDIT",
86 "ALLOWED", 86 "ALLOWED",
87 "DENIED", 87 "DENIED",
@@ -89,7 +89,6 @@ static const char *const aa_audit_type[] = {
89 "STATUS", 89 "STATUS",
90 "ERROR", 90 "ERROR",
91 "KILLED" 91 "KILLED"
92 "AUTO"
93}; 92};
94 93
95/* 94/*
@@ -111,30 +110,30 @@ static const char *const aa_audit_type[] = {
111static void audit_pre(struct audit_buffer *ab, void *ca) 110static void audit_pre(struct audit_buffer *ab, void *ca)
112{ 111{
113 struct common_audit_data *sa = ca; 112 struct common_audit_data *sa = ca;
114 struct task_struct *tsk = sa->aad->tsk ? sa->aad->tsk : current; 113 struct task_struct *tsk = sa->tsk ? sa->tsk : current;
115 114
116 if (aa_g_audit_header) { 115 if (aa_g_audit_header) {
117 audit_log_format(ab, "apparmor="); 116 audit_log_format(ab, "apparmor=");
118 audit_log_string(ab, aa_audit_type[sa->aad->type]); 117 audit_log_string(ab, aa_audit_type[sa->aad.type]);
119 } 118 }
120 119
121 if (sa->aad->op) { 120 if (sa->aad.op) {
122 audit_log_format(ab, " operation="); 121 audit_log_format(ab, " operation=");
123 audit_log_string(ab, op_table[sa->aad->op]); 122 audit_log_string(ab, op_table[sa->aad.op]);
124 } 123 }
125 124
126 if (sa->aad->info) { 125 if (sa->aad.info) {
127 audit_log_format(ab, " info="); 126 audit_log_format(ab, " info=");
128 audit_log_string(ab, sa->aad->info); 127 audit_log_string(ab, sa->aad.info);
129 if (sa->aad->error) 128 if (sa->aad.error)
130 audit_log_format(ab, " error=%d", sa->aad->error); 129 audit_log_format(ab, " error=%d", sa->aad.error);
131 } 130 }
132 131
133 if (sa->aad->profile) { 132 if (sa->aad.profile) {
134 struct aa_profile *profile = sa->aad->profile; 133 struct aa_profile *profile = sa->aad.profile;
135 pid_t pid; 134 pid_t pid;
136 rcu_read_lock(); 135 rcu_read_lock();
137 pid = rcu_dereference(tsk->real_parent)->pid; 136 pid = tsk->real_parent->pid;
138 rcu_read_unlock(); 137 rcu_read_unlock();
139 audit_log_format(ab, " parent=%d", pid); 138 audit_log_format(ab, " parent=%d", pid);
140 if (profile->ns != root_ns) { 139 if (profile->ns != root_ns) {
@@ -145,16 +144,10 @@ static void audit_pre(struct audit_buffer *ab, void *ca)
145 audit_log_untrustedstring(ab, profile->base.hname); 144 audit_log_untrustedstring(ab, profile->base.hname);
146 } 145 }
147 146
148 if (sa->aad->name) { 147 if (sa->aad.name) {
149 audit_log_format(ab, " name="); 148 audit_log_format(ab, " name=");
150 audit_log_untrustedstring(ab, sa->aad->name); 149 audit_log_untrustedstring(ab, sa->aad.name);
151 } 150 }
152
153 if (sa->aad->tsk) {
154 audit_log_format(ab, " pid=%d comm=", tsk->pid);
155 audit_log_untrustedstring(ab, tsk->comm);
156 }
157
158} 151}
159 152
160/** 153/**
@@ -165,8 +158,10 @@ static void audit_pre(struct audit_buffer *ab, void *ca)
165void aa_audit_msg(int type, struct common_audit_data *sa, 158void aa_audit_msg(int type, struct common_audit_data *sa,
166 void (*cb) (struct audit_buffer *, void *)) 159 void (*cb) (struct audit_buffer *, void *))
167{ 160{
168 sa->aad->type = type; 161 sa->aad.type = type;
169 common_lsm_audit(sa, audit_pre, cb); 162 sa->lsm_pre_audit = audit_pre;
163 sa->lsm_post_audit = cb;
164 common_lsm_audit(sa);
170} 165}
171 166
172/** 167/**
@@ -188,7 +183,7 @@ int aa_audit(int type, struct aa_profile *profile, gfp_t gfp,
188 BUG_ON(!profile); 183 BUG_ON(!profile);
189 184
190 if (type == AUDIT_APPARMOR_AUTO) { 185 if (type == AUDIT_APPARMOR_AUTO) {
191 if (likely(!sa->aad->error)) { 186 if (likely(!sa->aad.error)) {
192 if (AUDIT_MODE(profile) != AUDIT_ALL) 187 if (AUDIT_MODE(profile) != AUDIT_ALL)
193 return 0; 188 return 0;
194 type = AUDIT_APPARMOR_AUDIT; 189 type = AUDIT_APPARMOR_AUDIT;
@@ -200,22 +195,21 @@ int aa_audit(int type, struct aa_profile *profile, gfp_t gfp,
200 if (AUDIT_MODE(profile) == AUDIT_QUIET || 195 if (AUDIT_MODE(profile) == AUDIT_QUIET ||
201 (type == AUDIT_APPARMOR_DENIED && 196 (type == AUDIT_APPARMOR_DENIED &&
202 AUDIT_MODE(profile) == AUDIT_QUIET)) 197 AUDIT_MODE(profile) == AUDIT_QUIET))
203 return sa->aad->error; 198 return sa->aad.error;
204 199
205 if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED) 200 if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED)
206 type = AUDIT_APPARMOR_KILL; 201 type = AUDIT_APPARMOR_KILL;
207 202
208 if (!unconfined(profile)) 203 if (!unconfined(profile))
209 sa->aad->profile = profile; 204 sa->aad.profile = profile;
210 205
211 aa_audit_msg(type, sa, cb); 206 aa_audit_msg(type, sa, cb);
212 207
213 if (sa->aad->type == AUDIT_APPARMOR_KILL) 208 if (sa->aad.type == AUDIT_APPARMOR_KILL)
214 (void)send_sig_info(SIGKILL, NULL, 209 (void)send_sig_info(SIGKILL, NULL, sa->tsk ? sa->tsk : current);
215 sa->aad->tsk ? sa->aad->tsk : current);
216 210
217 if (sa->aad->type == AUDIT_APPARMOR_ALLOWED) 211 if (sa->aad.type == AUDIT_APPARMOR_ALLOWED)
218 return complain_error(sa->aad->error); 212 return complain_error(sa->aad.error);
219 213
220 return sa->aad->error; 214 return sa->aad.error;
221} 215}
diff --git a/security/apparmor/capability.c b/security/apparmor/capability.c
index 887a5e94894..9982c48def4 100644
--- a/security/apparmor/capability.c
+++ b/security/apparmor/capability.c
@@ -64,13 +64,11 @@ static int audit_caps(struct aa_profile *profile, struct task_struct *task,
64 struct audit_cache *ent; 64 struct audit_cache *ent;
65 int type = AUDIT_APPARMOR_AUTO; 65 int type = AUDIT_APPARMOR_AUTO;
66 struct common_audit_data sa; 66 struct common_audit_data sa;
67 struct apparmor_audit_data aad = {0,}; 67 COMMON_AUDIT_DATA_INIT(&sa, CAP);
68 sa.type = LSM_AUDIT_DATA_CAP; 68 sa.tsk = task;
69 sa.aad = &aad;
70 sa.u.cap = cap; 69 sa.u.cap = cap;
71 sa.aad->tsk = task; 70 sa.aad.op = OP_CAPABLE;
72 sa.aad->op = OP_CAPABLE; 71 sa.aad.error = error;
73 sa.aad->error = error;
74 72
75 if (likely(!error)) { 73 if (likely(!error)) {
76 /* test if auditing is being forced */ 74 /* test if auditing is being forced */
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index 60f0c76a27d..c1e18ba5bdc 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -372,12 +372,13 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
372 state = profile->file.start; 372 state = profile->file.start;
373 373
374 /* buffer freed below, name is pointer into buffer */ 374 /* buffer freed below, name is pointer into buffer */
375 error = aa_path_name(&bprm->file->f_path, profile->path_flags, &buffer, 375 error = aa_get_name(&bprm->file->f_path, profile->path_flags, &buffer,
376 &name, &info); 376 &name);
377 if (error) { 377 if (error) {
378 if (profile->flags & 378 if (profile->flags &
379 (PFLAG_IX_ON_NAME_ERROR | PFLAG_UNCONFINED)) 379 (PFLAG_IX_ON_NAME_ERROR | PFLAG_UNCONFINED))
380 error = 0; 380 error = 0;
381 info = "Exec failed name resolution";
381 name = bprm->filename; 382 name = bprm->filename;
382 goto audit; 383 goto audit;
383 } 384 }
@@ -394,11 +395,6 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
394 new_profile = find_attach(ns, &ns->base.profiles, name); 395 new_profile = find_attach(ns, &ns->base.profiles, name);
395 if (!new_profile) 396 if (!new_profile)
396 goto cleanup; 397 goto cleanup;
397 /*
398 * NOTE: Domain transitions from unconfined are allowed
399 * even when no_new_privs is set because this aways results
400 * in a further reduction of permissions.
401 */
402 goto apply; 398 goto apply;
403 } 399 }
404 400
@@ -415,8 +411,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
415 * exec\0change_profile 411 * exec\0change_profile
416 */ 412 */
417 state = aa_dfa_null_transition(profile->file.dfa, state); 413 state = aa_dfa_null_transition(profile->file.dfa, state);
418 cp = change_profile_perms(profile, cxt->onexec->ns, 414 cp = change_profile_perms(profile, cxt->onexec->ns, name,
419 cxt->onexec->base.name,
420 AA_MAY_ONEXEC, state); 415 AA_MAY_ONEXEC, state);
421 416
422 if (!(cp.allow & AA_MAY_ONEXEC)) 417 if (!(cp.allow & AA_MAY_ONEXEC))
@@ -460,16 +455,6 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
460 /* fail exec */ 455 /* fail exec */
461 error = -EACCES; 456 error = -EACCES;
462 457
463 /*
464 * Policy has specified a domain transition, if no_new_privs then
465 * fail the exec.
466 */
467 if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) {
468 aa_put_profile(new_profile);
469 error = -EPERM;
470 goto cleanup;
471 }
472
473 if (!new_profile) 458 if (!new_profile)
474 goto audit; 459 goto audit;
475 460
@@ -624,14 +609,6 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest)
624 const char *target = NULL, *info = NULL; 609 const char *target = NULL, *info = NULL;
625 int error = 0; 610 int error = 0;
626 611
627 /*
628 * Fail explicitly requested domain transitions if no_new_privs.
629 * There is no exception for unconfined as change_hat is not
630 * available.
631 */
632 if (current->no_new_privs)
633 return -EPERM;
634
635 /* released below */ 612 /* released below */
636 cred = get_current_cred(); 613 cred = get_current_cred();
637 cxt = cred->security; 614 cxt = cred->security;
@@ -721,7 +698,7 @@ audit:
721 if (!permtest) 698 if (!permtest)
722 error = aa_audit_file(profile, &perms, GFP_KERNEL, 699 error = aa_audit_file(profile, &perms, GFP_KERNEL,
723 OP_CHANGE_HAT, AA_MAY_CHANGEHAT, NULL, 700 OP_CHANGE_HAT, AA_MAY_CHANGEHAT, NULL,
724 target, GLOBAL_ROOT_UID, info, error); 701 target, 0, info, error);
725 702
726out: 703out:
727 aa_put_profile(hat); 704 aa_put_profile(hat);
@@ -773,18 +750,6 @@ int aa_change_profile(const char *ns_name, const char *hname, bool onexec,
773 cxt = cred->security; 750 cxt = cred->security;
774 profile = aa_cred_profile(cred); 751 profile = aa_cred_profile(cred);
775 752
776 /*
777 * Fail explicitly requested domain transitions if no_new_privs
778 * and not unconfined.
779 * Domain transitions from unconfined are allowed even when
780 * no_new_privs is set because this aways results in a reduction
781 * of permissions.
782 */
783 if (current->no_new_privs && !unconfined(profile)) {
784 put_cred(cred);
785 return -EPERM;
786 }
787
788 if (ns_name) { 753 if (ns_name) {
789 /* released below */ 754 /* released below */
790 ns = aa_find_namespace(profile->ns, ns_name); 755 ns = aa_find_namespace(profile->ns, ns_name);
@@ -848,7 +813,7 @@ int aa_change_profile(const char *ns_name, const char *hname, bool onexec,
848audit: 813audit:
849 if (!permtest) 814 if (!permtest)
850 error = aa_audit_file(profile, &perms, GFP_KERNEL, op, request, 815 error = aa_audit_file(profile, &perms, GFP_KERNEL, op, request,
851 name, hname, GLOBAL_ROOT_UID, info, error); 816 name, hname, 0, info, error);
852 817
853 aa_put_namespace(ns); 818 aa_put_namespace(ns);
854 aa_put_profile(target); 819 aa_put_profile(target);
diff --git a/security/apparmor/file.c b/security/apparmor/file.c
index cd21ec5b90a..7312db74121 100644
--- a/security/apparmor/file.c
+++ b/security/apparmor/file.c
@@ -65,26 +65,24 @@ static void audit_file_mask(struct audit_buffer *ab, u32 mask)
65static void file_audit_cb(struct audit_buffer *ab, void *va) 65static void file_audit_cb(struct audit_buffer *ab, void *va)
66{ 66{
67 struct common_audit_data *sa = va; 67 struct common_audit_data *sa = va;
68 kuid_t fsuid = current_fsuid(); 68 uid_t fsuid = current_fsuid();
69 69
70 if (sa->aad->fs.request & AA_AUDIT_FILE_MASK) { 70 if (sa->aad.fs.request & AA_AUDIT_FILE_MASK) {
71 audit_log_format(ab, " requested_mask="); 71 audit_log_format(ab, " requested_mask=");
72 audit_file_mask(ab, sa->aad->fs.request); 72 audit_file_mask(ab, sa->aad.fs.request);
73 } 73 }
74 if (sa->aad->fs.denied & AA_AUDIT_FILE_MASK) { 74 if (sa->aad.fs.denied & AA_AUDIT_FILE_MASK) {
75 audit_log_format(ab, " denied_mask="); 75 audit_log_format(ab, " denied_mask=");
76 audit_file_mask(ab, sa->aad->fs.denied); 76 audit_file_mask(ab, sa->aad.fs.denied);
77 } 77 }
78 if (sa->aad->fs.request & AA_AUDIT_FILE_MASK) { 78 if (sa->aad.fs.request & AA_AUDIT_FILE_MASK) {
79 audit_log_format(ab, " fsuid=%d", 79 audit_log_format(ab, " fsuid=%d", fsuid);
80 from_kuid(&init_user_ns, fsuid)); 80 audit_log_format(ab, " ouid=%d", sa->aad.fs.ouid);
81 audit_log_format(ab, " ouid=%d",
82 from_kuid(&init_user_ns, sa->aad->fs.ouid));
83 } 81 }
84 82
85 if (sa->aad->fs.target) { 83 if (sa->aad.fs.target) {
86 audit_log_format(ab, " target="); 84 audit_log_format(ab, " target=");
87 audit_log_untrustedstring(ab, sa->aad->fs.target); 85 audit_log_untrustedstring(ab, sa->aad.fs.target);
88 } 86 }
89} 87}
90 88
@@ -105,51 +103,49 @@ static void file_audit_cb(struct audit_buffer *ab, void *va)
105 */ 103 */
106int aa_audit_file(struct aa_profile *profile, struct file_perms *perms, 104int aa_audit_file(struct aa_profile *profile, struct file_perms *perms,
107 gfp_t gfp, int op, u32 request, const char *name, 105 gfp_t gfp, int op, u32 request, const char *name,
108 const char *target, kuid_t ouid, const char *info, int error) 106 const char *target, uid_t ouid, const char *info, int error)
109{ 107{
110 int type = AUDIT_APPARMOR_AUTO; 108 int type = AUDIT_APPARMOR_AUTO;
111 struct common_audit_data sa; 109 struct common_audit_data sa;
112 struct apparmor_audit_data aad = {0,}; 110 COMMON_AUDIT_DATA_INIT(&sa, NONE);
113 sa.type = LSM_AUDIT_DATA_NONE; 111 sa.aad.op = op,
114 sa.aad = &aad; 112 sa.aad.fs.request = request;
115 aad.op = op, 113 sa.aad.name = name;
116 aad.fs.request = request; 114 sa.aad.fs.target = target;
117 aad.name = name; 115 sa.aad.fs.ouid = ouid;
118 aad.fs.target = target; 116 sa.aad.info = info;
119 aad.fs.ouid = ouid; 117 sa.aad.error = error;
120 aad.info = info; 118
121 aad.error = error; 119 if (likely(!sa.aad.error)) {
122
123 if (likely(!sa.aad->error)) {
124 u32 mask = perms->audit; 120 u32 mask = perms->audit;
125 121
126 if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL)) 122 if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL))
127 mask = 0xffff; 123 mask = 0xffff;
128 124
129 /* mask off perms that are not being force audited */ 125 /* mask off perms that are not being force audited */
130 sa.aad->fs.request &= mask; 126 sa.aad.fs.request &= mask;
131 127
132 if (likely(!sa.aad->fs.request)) 128 if (likely(!sa.aad.fs.request))
133 return 0; 129 return 0;
134 type = AUDIT_APPARMOR_AUDIT; 130 type = AUDIT_APPARMOR_AUDIT;
135 } else { 131 } else {
136 /* only report permissions that were denied */ 132 /* only report permissions that were denied */
137 sa.aad->fs.request = sa.aad->fs.request & ~perms->allow; 133 sa.aad.fs.request = sa.aad.fs.request & ~perms->allow;
138 134
139 if (sa.aad->fs.request & perms->kill) 135 if (sa.aad.fs.request & perms->kill)
140 type = AUDIT_APPARMOR_KILL; 136 type = AUDIT_APPARMOR_KILL;
141 137
142 /* quiet known rejects, assumes quiet and kill do not overlap */ 138 /* quiet known rejects, assumes quiet and kill do not overlap */
143 if ((sa.aad->fs.request & perms->quiet) && 139 if ((sa.aad.fs.request & perms->quiet) &&
144 AUDIT_MODE(profile) != AUDIT_NOQUIET && 140 AUDIT_MODE(profile) != AUDIT_NOQUIET &&
145 AUDIT_MODE(profile) != AUDIT_ALL) 141 AUDIT_MODE(profile) != AUDIT_ALL)
146 sa.aad->fs.request &= ~perms->quiet; 142 sa.aad.fs.request &= ~perms->quiet;
147 143
148 if (!sa.aad->fs.request) 144 if (!sa.aad.fs.request)
149 return COMPLAIN_MODE(profile) ? 0 : sa.aad->error; 145 return COMPLAIN_MODE(profile) ? 0 : sa.aad.error;
150 } 146 }
151 147
152 sa.aad->fs.denied = sa.aad->fs.request & ~perms->allow; 148 sa.aad.fs.denied = sa.aad.fs.request & ~perms->allow;
153 return aa_audit(type, profile, gfp, &sa, file_audit_cb); 149 return aa_audit(type, profile, gfp, &sa, file_audit_cb);
154} 150}
155 151
@@ -177,6 +173,8 @@ static u32 map_old_perms(u32 old)
177 if (old & 0x40) /* AA_EXEC_MMAP */ 173 if (old & 0x40) /* AA_EXEC_MMAP */
178 new |= AA_EXEC_MMAP; 174 new |= AA_EXEC_MMAP;
179 175
176 new |= AA_MAY_META_READ;
177
180 return new; 178 return new;
181} 179}
182 180
@@ -203,7 +201,7 @@ static struct file_perms compute_perms(struct aa_dfa *dfa, unsigned int state,
203 */ 201 */
204 perms.kill = 0; 202 perms.kill = 0;
205 203
206 if (uid_eq(current_fsuid(), cond->uid)) { 204 if (current_fsuid() == cond->uid) {
207 perms.allow = map_old_perms(dfa_user_allow(dfa, state)); 205 perms.allow = map_old_perms(dfa_user_allow(dfa, state));
208 perms.audit = map_old_perms(dfa_user_audit(dfa, state)); 206 perms.audit = map_old_perms(dfa_user_audit(dfa, state));
209 perms.quiet = map_old_perms(dfa_user_quiet(dfa, state)); 207 perms.quiet = map_old_perms(dfa_user_quiet(dfa, state));
@@ -214,13 +212,10 @@ static struct file_perms compute_perms(struct aa_dfa *dfa, unsigned int state,
214 perms.quiet = map_old_perms(dfa_other_quiet(dfa, state)); 212 perms.quiet = map_old_perms(dfa_other_quiet(dfa, state));
215 perms.xindex = dfa_other_xindex(dfa, state); 213 perms.xindex = dfa_other_xindex(dfa, state);
216 } 214 }
217 perms.allow |= AA_MAY_META_READ;
218 215
219 /* change_profile wasn't determined by ownership in old mapping */ 216 /* change_profile wasn't determined by ownership in old mapping */
220 if (ACCEPT_TABLE(dfa)[state] & 0x80000000) 217 if (ACCEPT_TABLE(dfa)[state] & 0x80000000)
221 perms.allow |= AA_MAY_CHANGE_PROFILE; 218 perms.allow |= AA_MAY_CHANGE_PROFILE;
222 if (ACCEPT_TABLE(dfa)[state] & 0x40000000)
223 perms.allow |= AA_MAY_ONEXEC;
224 219
225 return perms; 220 return perms;
226} 221}
@@ -284,16 +279,22 @@ int aa_path_perm(int op, struct aa_profile *profile, struct path *path,
284 int error; 279 int error;
285 280
286 flags |= profile->path_flags | (S_ISDIR(cond->mode) ? PATH_IS_DIR : 0); 281 flags |= profile->path_flags | (S_ISDIR(cond->mode) ? PATH_IS_DIR : 0);
287 error = aa_path_name(path, flags, &buffer, &name, &info); 282 error = aa_get_name(path, flags, &buffer, &name);
288 if (error) { 283 if (error) {
289 if (error == -ENOENT && is_deleted(path->dentry)) { 284 if (error == -ENOENT && is_deleted(path->dentry)) {
290 /* Access to open files that are deleted are 285 /* Access to open files that are deleted are
291 * give a pass (implicit delegation) 286 * give a pass (implicit delegation)
292 */ 287 */
293 error = 0; 288 error = 0;
294 info = NULL;
295 perms.allow = request; 289 perms.allow = request;
296 } 290 } else if (error == -ENOENT)
291 info = "Failed name lookup - deleted entry";
292 else if (error == -ESTALE)
293 info = "Failed name lookup - disconnected path";
294 else if (error == -ENAMETOOLONG)
295 info = "Failed name lookup - name too long";
296 else
297 info = "Failed name lookup";
297 } else { 298 } else {
298 aa_str_perms(profile->file.dfa, profile->file.start, name, cond, 299 aa_str_perms(profile->file.dfa, profile->file.start, name, cond,
299 &perms); 300 &perms);
@@ -364,14 +365,12 @@ int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
364 lperms = nullperms; 365 lperms = nullperms;
365 366
366 /* buffer freed below, lname is pointer in buffer */ 367 /* buffer freed below, lname is pointer in buffer */
367 error = aa_path_name(&link, profile->path_flags, &buffer, &lname, 368 error = aa_get_name(&link, profile->path_flags, &buffer, &lname);
368 &info);
369 if (error) 369 if (error)
370 goto audit; 370 goto audit;
371 371
372 /* buffer2 freed below, tname is pointer in buffer2 */ 372 /* buffer2 freed below, tname is pointer in buffer2 */
373 error = aa_path_name(&target, profile->path_flags, &buffer2, &tname, 373 error = aa_get_name(&target, profile->path_flags, &buffer2, &tname);
374 &info);
375 if (error) 374 if (error)
376 goto audit; 375 goto audit;
377 376
diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h
index 40aedd9f73e..38ccaea0820 100644
--- a/security/apparmor/include/apparmor.h
+++ b/security/apparmor/include/apparmor.h
@@ -19,26 +19,13 @@
19 19
20#include "match.h" 20#include "match.h"
21 21
22/*
23 * Class of mediation types in the AppArmor policy db
24 */
25#define AA_CLASS_ENTRY 0
26#define AA_CLASS_UNKNOWN 1
27#define AA_CLASS_FILE 2
28#define AA_CLASS_CAP 3
29#define AA_CLASS_NET 4
30#define AA_CLASS_RLIMITS 5
31#define AA_CLASS_DOMAIN 6
32
33#define AA_CLASS_LAST AA_CLASS_DOMAIN
34
35/* Control parameters settable through module/boot flags */ 22/* Control parameters settable through module/boot flags */
36extern enum audit_mode aa_g_audit; 23extern enum audit_mode aa_g_audit;
37extern bool aa_g_audit_header; 24extern int aa_g_audit_header;
38extern bool aa_g_debug; 25extern int aa_g_debug;
39extern bool aa_g_lock_policy; 26extern int aa_g_lock_policy;
40extern bool aa_g_logsyscall; 27extern int aa_g_logsyscall;
41extern bool aa_g_paranoid_load; 28extern int aa_g_paranoid_load;
42extern unsigned int aa_g_path_max; 29extern unsigned int aa_g_path_max;
43 30
44/* 31/*
@@ -94,7 +81,7 @@ static inline unsigned int aa_dfa_null_transition(struct aa_dfa *dfa,
94 unsigned int start) 81 unsigned int start)
95{ 82{
96 /* the null transition only needs the string's null terminator byte */ 83 /* the null transition only needs the string's null terminator byte */
97 return aa_dfa_next(dfa, start, 0); 84 return aa_dfa_match_len(dfa, start, "", 1);
98} 85}
99 86
100static inline bool mediated_filesystem(struct inode *inode) 87static inline bool mediated_filesystem(struct inode *inode)
diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h
index 7ea4769fab3..cb1e93a114d 100644
--- a/security/apparmor/include/apparmorfs.h
+++ b/security/apparmor/include/apparmorfs.h
@@ -15,50 +15,6 @@
15#ifndef __AA_APPARMORFS_H 15#ifndef __AA_APPARMORFS_H
16#define __AA_APPARMORFS_H 16#define __AA_APPARMORFS_H
17 17
18enum aa_fs_type {
19 AA_FS_TYPE_BOOLEAN,
20 AA_FS_TYPE_STRING,
21 AA_FS_TYPE_U64,
22 AA_FS_TYPE_FOPS,
23 AA_FS_TYPE_DIR,
24};
25
26struct aa_fs_entry;
27
28struct aa_fs_entry {
29 const char *name;
30 struct dentry *dentry;
31 umode_t mode;
32 enum aa_fs_type v_type;
33 union {
34 bool boolean;
35 char *string;
36 unsigned long u64;
37 struct aa_fs_entry *files;
38 } v;
39 const struct file_operations *file_ops;
40};
41
42extern const struct file_operations aa_fs_seq_file_ops;
43
44#define AA_FS_FILE_BOOLEAN(_name, _value) \
45 { .name = (_name), .mode = 0444, \
46 .v_type = AA_FS_TYPE_BOOLEAN, .v.boolean = (_value), \
47 .file_ops = &aa_fs_seq_file_ops }
48#define AA_FS_FILE_STRING(_name, _value) \
49 { .name = (_name), .mode = 0444, \
50 .v_type = AA_FS_TYPE_STRING, .v.string = (_value), \
51 .file_ops = &aa_fs_seq_file_ops }
52#define AA_FS_FILE_U64(_name, _value) \
53 { .name = (_name), .mode = 0444, \
54 .v_type = AA_FS_TYPE_U64, .v.u64 = (_value), \
55 .file_ops = &aa_fs_seq_file_ops }
56#define AA_FS_FILE_FOPS(_name, _mode, _fops) \
57 { .name = (_name), .v_type = AA_FS_TYPE_FOPS, \
58 .mode = (_mode), .file_ops = (_fops) }
59#define AA_FS_DIR(_name, _value) \
60 { .name = (_name), .v_type = AA_FS_TYPE_DIR, .v.files = (_value) }
61
62extern void __init aa_destroy_aafs(void); 18extern void __init aa_destroy_aafs(void);
63 19
64#endif /* __AA_APPARMORFS_H */ 20#endif /* __AA_APPARMORFS_H */
diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
index 69d8cae634e..1951786d32e 100644
--- a/security/apparmor/include/audit.h
+++ b/security/apparmor/include/audit.h
@@ -25,9 +25,11 @@
25 25
26struct aa_profile; 26struct aa_profile;
27 27
28extern const char *const audit_mode_names[]; 28extern const char *audit_mode_names[];
29#define AUDIT_MAX_INDEX 5 29#define AUDIT_MAX_INDEX 5
30 30
31#define AUDIT_APPARMOR_AUTO 0 /* auto choose audit message type */
32
31enum audit_mode { 33enum audit_mode {
32 AUDIT_NORMAL, /* follow normal auditing of accesses */ 34 AUDIT_NORMAL, /* follow normal auditing of accesses */
33 AUDIT_QUIET_DENIED, /* quiet all denied access messages */ 35 AUDIT_QUIET_DENIED, /* quiet all denied access messages */
@@ -43,11 +45,10 @@ enum audit_type {
43 AUDIT_APPARMOR_HINT, 45 AUDIT_APPARMOR_HINT,
44 AUDIT_APPARMOR_STATUS, 46 AUDIT_APPARMOR_STATUS,
45 AUDIT_APPARMOR_ERROR, 47 AUDIT_APPARMOR_ERROR,
46 AUDIT_APPARMOR_KILL, 48 AUDIT_APPARMOR_KILL
47 AUDIT_APPARMOR_AUTO
48}; 49};
49 50
50extern const char *const op_table[]; 51extern const char *op_table[];
51enum aa_ops { 52enum aa_ops {
52 OP_NULL, 53 OP_NULL,
53 54
@@ -103,34 +104,7 @@ enum aa_ops {
103}; 104};
104 105
105 106
106struct apparmor_audit_data { 107/* define a short hand for apparmor_audit_data portion of common_audit_data */
107 int error;
108 int op;
109 int type;
110 void *profile;
111 const char *name;
112 const char *info;
113 struct task_struct *tsk;
114 union {
115 void *target;
116 struct {
117 long pos;
118 void *target;
119 } iface;
120 struct {
121 int rlim;
122 unsigned long max;
123 } rlim;
124 struct {
125 const char *target;
126 u32 request;
127 u32 denied;
128 kuid_t ouid;
129 } fs;
130 };
131};
132
133/* define a short hand for apparmor_audit_data structure */
134#define aad apparmor_audit_data 108#define aad apparmor_audit_data
135 109
136void aa_audit_msg(int type, struct common_audit_data *sa, 110void aa_audit_msg(int type, struct common_audit_data *sa,
diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h
index 967b2deda37..ab8c6d87f75 100644
--- a/security/apparmor/include/file.h
+++ b/security/apparmor/include/file.h
@@ -71,7 +71,7 @@ struct path;
71 71
72/* need to make conditional which ones are being set */ 72/* need to make conditional which ones are being set */
73struct path_cond { 73struct path_cond {
74 kuid_t uid; 74 uid_t uid;
75 umode_t mode; 75 umode_t mode;
76}; 76};
77 77
@@ -117,7 +117,7 @@ static inline u16 dfa_map_xindex(u16 mask)
117 index |= AA_X_NAME; 117 index |= AA_X_NAME;
118 } else if (old_index == 3) { 118 } else if (old_index == 3) {
119 index |= AA_X_NAME | AA_X_CHILD; 119 index |= AA_X_NAME | AA_X_CHILD;
120 } else if (old_index) { 120 } else {
121 index |= AA_X_TABLE; 121 index |= AA_X_TABLE;
122 index |= old_index - 4; 122 index |= old_index - 4;
123 } 123 }
@@ -146,7 +146,7 @@ static inline u16 dfa_map_xindex(u16 mask)
146 146
147int aa_audit_file(struct aa_profile *profile, struct file_perms *perms, 147int aa_audit_file(struct aa_profile *profile, struct file_perms *perms,
148 gfp_t gfp, int op, u32 request, const char *name, 148 gfp_t gfp, int op, u32 request, const char *name,
149 const char *target, kuid_t ouid, const char *info, int error); 149 const char *target, uid_t ouid, const char *info, int error);
150 150
151/** 151/**
152 * struct aa_file_rules - components used for file rule permissions 152 * struct aa_file_rules - components used for file rule permissions
diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h
index 775843e7f98..a4a863997bd 100644
--- a/security/apparmor/include/match.h
+++ b/security/apparmor/include/match.h
@@ -116,9 +116,6 @@ unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
116 const char *str, int len); 116 const char *str, int len);
117unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start, 117unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start,
118 const char *str); 118 const char *str);
119unsigned int aa_dfa_next(struct aa_dfa *dfa, unsigned int state,
120 const char c);
121
122void aa_dfa_free_kref(struct kref *kref); 119void aa_dfa_free_kref(struct kref *kref);
123 120
124/** 121/**
diff --git a/security/apparmor/include/path.h b/security/apparmor/include/path.h
index 286ac75dc88..27b327a7fae 100644
--- a/security/apparmor/include/path.h
+++ b/security/apparmor/include/path.h
@@ -26,7 +26,6 @@ enum path_flags {
26 PATH_MEDIATE_DELETED = 0x10000, /* mediate deleted paths */ 26 PATH_MEDIATE_DELETED = 0x10000, /* mediate deleted paths */
27}; 27};
28 28
29int aa_path_name(struct path *path, int flags, char **buffer, 29int aa_get_name(struct path *path, int flags, char **buffer, const char **name);
30 const char **name, const char **info);
31 30
32#endif /* __AA_PATH_H */ 31#endif /* __AA_PATH_H */
diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
index bda4569fdd8..aeda5cf5690 100644
--- a/security/apparmor/include/policy.h
+++ b/security/apparmor/include/policy.h
@@ -29,7 +29,7 @@
29#include "file.h" 29#include "file.h"
30#include "resource.h" 30#include "resource.h"
31 31
32extern const char *const profile_mode_names[]; 32extern const char *profile_mode_names[];
33#define APPARMOR_NAMES_MAX_INDEX 3 33#define APPARMOR_NAMES_MAX_INDEX 3
34 34
35#define COMPLAIN_MODE(_profile) \ 35#define COMPLAIN_MODE(_profile) \
@@ -129,17 +129,6 @@ struct aa_namespace {
129 struct list_head sub_ns; 129 struct list_head sub_ns;
130}; 130};
131 131
132/* struct aa_policydb - match engine for a policy
133 * dfa: dfa pattern match
134 * start: set of start states for the different classes of data
135 */
136struct aa_policydb {
137 /* Generic policy DFA specific rule types will be subsections of it */
138 struct aa_dfa *dfa;
139 unsigned int start[AA_CLASS_LAST + 1];
140
141};
142
143/* struct aa_profile - basic confinement data 132/* struct aa_profile - basic confinement data
144 * @base - base components of the profile (name, refcount, lists, lock ...) 133 * @base - base components of the profile (name, refcount, lists, lock ...)
145 * @parent: parent of profile 134 * @parent: parent of profile
@@ -154,7 +143,6 @@ struct aa_policydb {
154 * @flags: flags controlling profile behavior 143 * @flags: flags controlling profile behavior
155 * @path_flags: flags controlling path generation behavior 144 * @path_flags: flags controlling path generation behavior
156 * @size: the memory consumed by this profiles rules 145 * @size: the memory consumed by this profiles rules
157 * @policy: general match rules governing policy
158 * @file: The set of rules governing basic file access and domain transitions 146 * @file: The set of rules governing basic file access and domain transitions
159 * @caps: capabilities for the profile 147 * @caps: capabilities for the profile
160 * @rlimits: rlimits for the profile 148 * @rlimits: rlimits for the profile
@@ -191,7 +179,6 @@ struct aa_profile {
191 u32 path_flags; 179 u32 path_flags;
192 int size; 180 int size;
193 181
194 struct aa_policydb policy;
195 struct aa_file_rules file; 182 struct aa_file_rules file;
196 struct aa_caps caps; 183 struct aa_caps caps;
197 struct aa_rlimit rlimits; 184 struct aa_rlimit rlimits;
diff --git a/security/apparmor/include/resource.h b/security/apparmor/include/resource.h
index d3f4cf02795..02baec732bb 100644
--- a/security/apparmor/include/resource.h
+++ b/security/apparmor/include/resource.h
@@ -18,8 +18,6 @@
18#include <linux/resource.h> 18#include <linux/resource.h>
19#include <linux/sched.h> 19#include <linux/sched.h>
20 20
21#include "apparmorfs.h"
22
23struct aa_profile; 21struct aa_profile;
24 22
25/* struct aa_rlimit - rlimit settings for the profile 23/* struct aa_rlimit - rlimit settings for the profile
@@ -34,8 +32,6 @@ struct aa_rlimit {
34 struct rlimit limits[RLIM_NLIMITS]; 32 struct rlimit limits[RLIM_NLIMITS];
35}; 33};
36 34
37extern struct aa_fs_entry aa_fs_entry_rlimit[];
38
39int aa_map_resource(int resource); 35int aa_map_resource(int resource);
40int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *, 36int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *,
41 unsigned int resource, struct rlimit *new_rlim); 37 unsigned int resource, struct rlimit *new_rlim);
diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c
index cf1071b1423..649fad88869 100644
--- a/security/apparmor/ipc.c
+++ b/security/apparmor/ipc.c
@@ -19,14 +19,13 @@
19#include "include/capability.h" 19#include "include/capability.h"
20#include "include/context.h" 20#include "include/context.h"
21#include "include/policy.h" 21#include "include/policy.h"
22#include "include/ipc.h"
23 22
24/* call back to audit ptrace fields */ 23/* call back to audit ptrace fields */
25static void audit_cb(struct audit_buffer *ab, void *va) 24static void audit_cb(struct audit_buffer *ab, void *va)
26{ 25{
27 struct common_audit_data *sa = va; 26 struct common_audit_data *sa = va;
28 audit_log_format(ab, " target="); 27 audit_log_format(ab, " target=");
29 audit_log_untrustedstring(ab, sa->aad->target); 28 audit_log_untrustedstring(ab, sa->aad.target);
30} 29}
31 30
32/** 31/**
@@ -41,12 +40,10 @@ static int aa_audit_ptrace(struct aa_profile *profile,
41 struct aa_profile *target, int error) 40 struct aa_profile *target, int error)
42{ 41{
43 struct common_audit_data sa; 42 struct common_audit_data sa;
44 struct apparmor_audit_data aad = {0,}; 43 COMMON_AUDIT_DATA_INIT(&sa, NONE);
45 sa.type = LSM_AUDIT_DATA_NONE; 44 sa.aad.op = OP_PTRACE;
46 sa.aad = &aad; 45 sa.aad.target = target;
47 aad.op = OP_PTRACE; 46 sa.aad.error = error;
48 aad.target = target;
49 aad.error = error;
50 47
51 return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_ATOMIC, &sa, 48 return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_ATOMIC, &sa,
52 audit_cb); 49 audit_cb);
diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c
index 7430298116d..b82e383beb7 100644
--- a/security/apparmor/lib.c
+++ b/security/apparmor/lib.c
@@ -18,7 +18,6 @@
18#include <linux/vmalloc.h> 18#include <linux/vmalloc.h>
19 19
20#include "include/audit.h" 20#include "include/audit.h"
21#include "include/apparmor.h"
22 21
23 22
24/** 23/**
@@ -65,10 +64,8 @@ void aa_info_message(const char *str)
65{ 64{
66 if (audit_enabled) { 65 if (audit_enabled) {
67 struct common_audit_data sa; 66 struct common_audit_data sa;
68 struct apparmor_audit_data aad = {0,}; 67 COMMON_AUDIT_DATA_INIT(&sa, NONE);
69 sa.type = LSM_AUDIT_DATA_NONE; 68 sa.aad.info = str;
70 sa.aad = &aad;
71 aad.info = str;
72 aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL); 69 aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL);
73 } 70 }
74 printk(KERN_INFO "AppArmor: %s\n", str); 71 printk(KERN_INFO "AppArmor: %s\n", str);
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 8c2a7f6b35e..37832026e58 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -136,16 +136,16 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective,
136 return 0; 136 return 0;
137} 137}
138 138
139static int apparmor_capable(const struct cred *cred, struct user_namespace *ns, 139static int apparmor_capable(struct task_struct *task, const struct cred *cred,
140 int cap, int audit) 140 struct user_namespace *ns, int cap, int audit)
141{ 141{
142 struct aa_profile *profile; 142 struct aa_profile *profile;
143 /* cap_capable returns 0 on success, else -EPERM */ 143 /* cap_capable returns 0 on success, else -EPERM */
144 int error = cap_capable(cred, ns, cap, audit); 144 int error = cap_capable(task, cred, ns, cap, audit);
145 if (!error) { 145 if (!error) {
146 profile = aa_cred_profile(cred); 146 profile = aa_cred_profile(cred);
147 if (!unconfined(profile)) 147 if (!unconfined(profile))
148 error = aa_capable(current, profile, cap, audit); 148 error = aa_capable(task, profile, cap, audit);
149 } 149 }
150 return error; 150 return error;
151} 151}
@@ -262,7 +262,7 @@ static int apparmor_path_unlink(struct path *dir, struct dentry *dentry)
262} 262}
263 263
264static int apparmor_path_mkdir(struct path *dir, struct dentry *dentry, 264static int apparmor_path_mkdir(struct path *dir, struct dentry *dentry,
265 umode_t mode) 265 int mode)
266{ 266{
267 return common_perm_create(OP_MKDIR, dir, dentry, AA_MAY_CREATE, 267 return common_perm_create(OP_MKDIR, dir, dentry, AA_MAY_CREATE,
268 S_IFDIR); 268 S_IFDIR);
@@ -274,7 +274,7 @@ static int apparmor_path_rmdir(struct path *dir, struct dentry *dentry)
274} 274}
275 275
276static int apparmor_path_mknod(struct path *dir, struct dentry *dentry, 276static int apparmor_path_mknod(struct path *dir, struct dentry *dentry,
277 umode_t mode, unsigned int dev) 277 int mode, unsigned int dev)
278{ 278{
279 return common_perm_create(OP_MKNOD, dir, dentry, AA_MAY_CREATE, mode); 279 return common_perm_create(OP_MKNOD, dir, dentry, AA_MAY_CREATE, mode);
280} 280}
@@ -344,15 +344,16 @@ static int apparmor_path_rename(struct path *old_dir, struct dentry *old_dentry,
344 return error; 344 return error;
345} 345}
346 346
347static int apparmor_path_chmod(struct path *path, umode_t mode) 347static int apparmor_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
348 mode_t mode)
348{ 349{
349 if (!mediated_filesystem(path->dentry->d_inode)) 350 if (!mediated_filesystem(dentry->d_inode))
350 return 0; 351 return 0;
351 352
352 return common_perm_mnt_dentry(OP_CHMOD, path->mnt, path->dentry, AA_MAY_CHMOD); 353 return common_perm_mnt_dentry(OP_CHMOD, mnt, dentry, AA_MAY_CHMOD);
353} 354}
354 355
355static int apparmor_path_chown(struct path *path, kuid_t uid, kgid_t gid) 356static int apparmor_path_chown(struct path *path, uid_t uid, gid_t gid)
356{ 357{
357 struct path_cond cond = { path->dentry->d_inode->i_uid, 358 struct path_cond cond = { path->dentry->d_inode->i_uid,
358 path->dentry->d_inode->i_mode 359 path->dentry->d_inode->i_mode
@@ -373,7 +374,7 @@ static int apparmor_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
373 AA_MAY_META_READ); 374 AA_MAY_META_READ);
374} 375}
375 376
376static int apparmor_file_open(struct file *file, const struct cred *cred) 377static int apparmor_dentry_open(struct file *file, const struct cred *cred)
377{ 378{
378 struct aa_file_cxt *fcxt = file->f_security; 379 struct aa_file_cxt *fcxt = file->f_security;
379 struct aa_profile *profile; 380 struct aa_profile *profile;
@@ -490,9 +491,17 @@ static int common_mmap(int op, struct file *file, unsigned long prot,
490 return common_file_perm(op, file, mask); 491 return common_file_perm(op, file, mask);
491} 492}
492 493
493static int apparmor_mmap_file(struct file *file, unsigned long reqprot, 494static int apparmor_file_mmap(struct file *file, unsigned long reqprot,
494 unsigned long prot, unsigned long flags) 495 unsigned long prot, unsigned long flags,
496 unsigned long addr, unsigned long addr_only)
495{ 497{
498 int rc = 0;
499
500 /* do DAC check */
501 rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only);
502 if (rc || addr_only)
503 return rc;
504
496 return common_mmap(OP_FMMAP, file, prot, flags); 505 return common_mmap(OP_FMMAP, file, prot, flags);
497} 506}
498 507
@@ -580,12 +589,10 @@ static int apparmor_setprocattr(struct task_struct *task, char *name,
580 error = aa_setprocattr_permipc(args); 589 error = aa_setprocattr_permipc(args);
581 } else { 590 } else {
582 struct common_audit_data sa; 591 struct common_audit_data sa;
583 struct apparmor_audit_data aad = {0,}; 592 COMMON_AUDIT_DATA_INIT(&sa, NONE);
584 sa.type = LSM_AUDIT_DATA_NONE; 593 sa.aad.op = OP_SETPROCATTR;
585 sa.aad = &aad; 594 sa.aad.info = name;
586 aad.op = OP_SETPROCATTR; 595 sa.aad.error = -EINVAL;
587 aad.info = name;
588 aad.error = -EINVAL;
589 return aa_audit(AUDIT_APPARMOR_DENIED, 596 return aa_audit(AUDIT_APPARMOR_DENIED,
590 __aa_current_profile(), GFP_KERNEL, 597 __aa_current_profile(), GFP_KERNEL,
591 &sa, NULL); 598 &sa, NULL);
@@ -632,14 +639,13 @@ static struct security_operations apparmor_ops = {
632 .path_chmod = apparmor_path_chmod, 639 .path_chmod = apparmor_path_chmod,
633 .path_chown = apparmor_path_chown, 640 .path_chown = apparmor_path_chown,
634 .path_truncate = apparmor_path_truncate, 641 .path_truncate = apparmor_path_truncate,
642 .dentry_open = apparmor_dentry_open,
635 .inode_getattr = apparmor_inode_getattr, 643 .inode_getattr = apparmor_inode_getattr,
636 644
637 .file_open = apparmor_file_open,
638 .file_permission = apparmor_file_permission, 645 .file_permission = apparmor_file_permission,
639 .file_alloc_security = apparmor_file_alloc_security, 646 .file_alloc_security = apparmor_file_alloc_security,
640 .file_free_security = apparmor_file_free_security, 647 .file_free_security = apparmor_file_free_security,
641 .mmap_file = apparmor_mmap_file, 648 .file_mmap = apparmor_file_mmap,
642 .mmap_addr = cap_mmap_addr,
643 .file_mprotect = apparmor_file_mprotect, 649 .file_mprotect = apparmor_file_mprotect,
644 .file_lock = apparmor_file_lock, 650 .file_lock = apparmor_file_lock,
645 651
@@ -665,7 +671,7 @@ static struct security_operations apparmor_ops = {
665 671
666static int param_set_aabool(const char *val, const struct kernel_param *kp); 672static int param_set_aabool(const char *val, const struct kernel_param *kp);
667static int param_get_aabool(char *buffer, const struct kernel_param *kp); 673static int param_get_aabool(char *buffer, const struct kernel_param *kp);
668#define param_check_aabool param_check_bool 674#define param_check_aabool(name, p) __param_check(name, p, int)
669static struct kernel_param_ops param_ops_aabool = { 675static struct kernel_param_ops param_ops_aabool = {
670 .set = param_set_aabool, 676 .set = param_set_aabool,
671 .get = param_get_aabool 677 .get = param_get_aabool
@@ -673,7 +679,7 @@ static struct kernel_param_ops param_ops_aabool = {
673 679
674static int param_set_aauint(const char *val, const struct kernel_param *kp); 680static int param_set_aauint(const char *val, const struct kernel_param *kp);
675static int param_get_aauint(char *buffer, const struct kernel_param *kp); 681static int param_get_aauint(char *buffer, const struct kernel_param *kp);
676#define param_check_aauint param_check_uint 682#define param_check_aauint(name, p) __param_check(name, p, int)
677static struct kernel_param_ops param_ops_aauint = { 683static struct kernel_param_ops param_ops_aauint = {
678 .set = param_set_aauint, 684 .set = param_set_aauint,
679 .get = param_get_aauint 685 .get = param_get_aauint
@@ -681,7 +687,7 @@ static struct kernel_param_ops param_ops_aauint = {
681 687
682static int param_set_aalockpolicy(const char *val, const struct kernel_param *kp); 688static int param_set_aalockpolicy(const char *val, const struct kernel_param *kp);
683static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp); 689static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp);
684#define param_check_aalockpolicy param_check_bool 690#define param_check_aalockpolicy(name, p) __param_check(name, p, int)
685static struct kernel_param_ops param_ops_aalockpolicy = { 691static struct kernel_param_ops param_ops_aalockpolicy = {
686 .set = param_set_aalockpolicy, 692 .set = param_set_aalockpolicy,
687 .get = param_get_aalockpolicy 693 .get = param_get_aalockpolicy
@@ -703,7 +709,7 @@ module_param_call(mode, param_set_mode, param_get_mode,
703 &aa_g_profile_mode, S_IRUSR | S_IWUSR); 709 &aa_g_profile_mode, S_IRUSR | S_IWUSR);
704 710
705/* Debug mode */ 711/* Debug mode */
706bool aa_g_debug; 712int aa_g_debug;
707module_param_named(debug, aa_g_debug, aabool, S_IRUSR | S_IWUSR); 713module_param_named(debug, aa_g_debug, aabool, S_IRUSR | S_IWUSR);
708 714
709/* Audit mode */ 715/* Audit mode */
@@ -714,7 +720,7 @@ module_param_call(audit, param_set_audit, param_get_audit,
714/* Determines if audit header is included in audited messages. This 720/* Determines if audit header is included in audited messages. This
715 * provides more context if the audit daemon is not running 721 * provides more context if the audit daemon is not running
716 */ 722 */
717bool aa_g_audit_header = 1; 723int aa_g_audit_header = 1;
718module_param_named(audit_header, aa_g_audit_header, aabool, 724module_param_named(audit_header, aa_g_audit_header, aabool,
719 S_IRUSR | S_IWUSR); 725 S_IRUSR | S_IWUSR);
720 726
@@ -722,12 +728,12 @@ module_param_named(audit_header, aa_g_audit_header, aabool,
722 * TODO: add in at boot loading of policy, which is the only way to 728 * TODO: add in at boot loading of policy, which is the only way to
723 * load policy, if lock_policy is set 729 * load policy, if lock_policy is set
724 */ 730 */
725bool aa_g_lock_policy; 731int aa_g_lock_policy;
726module_param_named(lock_policy, aa_g_lock_policy, aalockpolicy, 732module_param_named(lock_policy, aa_g_lock_policy, aalockpolicy,
727 S_IRUSR | S_IWUSR); 733 S_IRUSR | S_IWUSR);
728 734
729/* Syscall logging mode */ 735/* Syscall logging mode */
730bool aa_g_logsyscall; 736int aa_g_logsyscall;
731module_param_named(logsyscall, aa_g_logsyscall, aabool, S_IRUSR | S_IWUSR); 737module_param_named(logsyscall, aa_g_logsyscall, aabool, S_IRUSR | S_IWUSR);
732 738
733/* Maximum pathname length before accesses will start getting rejected */ 739/* Maximum pathname length before accesses will start getting rejected */
@@ -737,12 +743,12 @@ module_param_named(path_max, aa_g_path_max, aauint, S_IRUSR | S_IWUSR);
737/* Determines how paranoid loading of policy is and how much verification 743/* Determines how paranoid loading of policy is and how much verification
738 * on the loaded policy is done. 744 * on the loaded policy is done.
739 */ 745 */
740bool aa_g_paranoid_load = 1; 746int aa_g_paranoid_load = 1;
741module_param_named(paranoid_load, aa_g_paranoid_load, aabool, 747module_param_named(paranoid_load, aa_g_paranoid_load, aabool,
742 S_IRUSR | S_IWUSR); 748 S_IRUSR | S_IWUSR);
743 749
744/* Boot time disable flag */ 750/* Boot time disable flag */
745static bool apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE; 751static unsigned int apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
746module_param_named(enabled, apparmor_enabled, aabool, S_IRUSR); 752module_param_named(enabled, apparmor_enabled, aabool, S_IRUSR);
747 753
748static int __init apparmor_enabled_setup(char *str) 754static int __init apparmor_enabled_setup(char *str)
diff --git a/security/apparmor/match.c b/security/apparmor/match.c
index 90971a8c378..94de6b4907c 100644
--- a/security/apparmor/match.c
+++ b/security/apparmor/match.c
@@ -335,12 +335,12 @@ unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
335} 335}
336 336
337/** 337/**
338 * aa_dfa_match - traverse @dfa to find state @str stops at 338 * aa_dfa_next_state - traverse @dfa to find state @str stops at
339 * @dfa: the dfa to match @str against (NOT NULL) 339 * @dfa: the dfa to match @str against (NOT NULL)
340 * @start: the state of the dfa to start matching in 340 * @start: the state of the dfa to start matching in
341 * @str: the null terminated string of bytes to match against the dfa (NOT NULL) 341 * @str: the null terminated string of bytes to match against the dfa (NOT NULL)
342 * 342 *
343 * aa_dfa_match will match @str against the dfa and return the state it 343 * aa_dfa_next_state will match @str against the dfa and return the state it
344 * finished matching in. The final state can be used to look up the accepting 344 * finished matching in. The final state can be used to look up the accepting
345 * label, or as the start state of a continuing match. 345 * label, or as the start state of a continuing match.
346 * 346 *
@@ -349,79 +349,5 @@ unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
349unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start, 349unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start,
350 const char *str) 350 const char *str)
351{ 351{
352 u16 *def = DEFAULT_TABLE(dfa); 352 return aa_dfa_match_len(dfa, start, str, strlen(str));
353 u32 *base = BASE_TABLE(dfa);
354 u16 *next = NEXT_TABLE(dfa);
355 u16 *check = CHECK_TABLE(dfa);
356 unsigned int state = start, pos;
357
358 if (state == 0)
359 return 0;
360
361 /* current state is <state>, matching character *str */
362 if (dfa->tables[YYTD_ID_EC]) {
363 /* Equivalence class table defined */
364 u8 *equiv = EQUIV_TABLE(dfa);
365 /* default is direct to next state */
366 while (*str) {
367 pos = base[state] + equiv[(u8) *str++];
368 if (check[pos] == state)
369 state = next[pos];
370 else
371 state = def[state];
372 }
373 } else {
374 /* default is direct to next state */
375 while (*str) {
376 pos = base[state] + (u8) *str++;
377 if (check[pos] == state)
378 state = next[pos];
379 else
380 state = def[state];
381 }
382 }
383
384 return state;
385}
386
387/**
388 * aa_dfa_next - step one character to the next state in the dfa
389 * @dfa: the dfa to tranverse (NOT NULL)
390 * @state: the state to start in
391 * @c: the input character to transition on
392 *
393 * aa_dfa_match will step through the dfa by one input character @c
394 *
395 * Returns: state reach after input @c
396 */
397unsigned int aa_dfa_next(struct aa_dfa *dfa, unsigned int state,
398 const char c)
399{
400 u16 *def = DEFAULT_TABLE(dfa);
401 u32 *base = BASE_TABLE(dfa);
402 u16 *next = NEXT_TABLE(dfa);
403 u16 *check = CHECK_TABLE(dfa);
404 unsigned int pos;
405
406 /* current state is <state>, matching character *str */
407 if (dfa->tables[YYTD_ID_EC]) {
408 /* Equivalence class table defined */
409 u8 *equiv = EQUIV_TABLE(dfa);
410 /* default is direct to next state */
411
412 pos = base[state] + equiv[(u8) c];
413 if (check[pos] == state)
414 state = next[pos];
415 else
416 state = def[state];
417 } else {
418 /* default is direct to next state */
419 pos = base[state] + (u8) c;
420 if (check[pos] == state)
421 state = next[pos];
422 else
423 state = def[state];
424 }
425
426 return state;
427} 353}
diff --git a/security/apparmor/path.c b/security/apparmor/path.c
index e91ffee8016..b566eba4a65 100644
--- a/security/apparmor/path.c
+++ b/security/apparmor/path.c
@@ -13,6 +13,7 @@
13 */ 13 */
14 14
15#include <linux/magic.h> 15#include <linux/magic.h>
16#include <linux/mnt_namespace.h>
16#include <linux/mount.h> 17#include <linux/mount.h>
17#include <linux/namei.h> 18#include <linux/namei.h>
18#include <linux/nsproxy.h> 19#include <linux/nsproxy.h>
@@ -83,31 +84,31 @@ static int d_namespace_path(struct path *path, char *buf, int buflen,
83 struct path root; 84 struct path root;
84 get_fs_root(current->fs, &root); 85 get_fs_root(current->fs, &root);
85 res = __d_path(path, &root, buf, buflen); 86 res = __d_path(path, &root, buf, buflen);
87 if (res && !IS_ERR(res)) {
88 /* everything's fine */
89 *name = res;
90 path_put(&root);
91 goto ok;
92 }
86 path_put(&root); 93 path_put(&root);
87 } else { 94 connected = 0;
88 res = d_absolute_path(path, buf, buflen);
89 if (!our_mnt(path->mnt))
90 connected = 0;
91 } 95 }
92 96
97 res = d_absolute_path(path, buf, buflen);
98
99 *name = res;
93 /* handle error conditions - and still allow a partial path to 100 /* handle error conditions - and still allow a partial path to
94 * be returned. 101 * be returned.
95 */ 102 */
96 if (!res || IS_ERR(res)) { 103 if (IS_ERR(res)) {
97 if (PTR_ERR(res) == -ENAMETOOLONG) 104 error = PTR_ERR(res);
98 return -ENAMETOOLONG; 105 *name = buf;
99 connected = 0; 106 goto out;
100 res = dentry_path_raw(path->dentry, buf, buflen); 107 }
101 if (IS_ERR(res)) { 108 if (!our_mnt(path->mnt))
102 error = PTR_ERR(res);
103 *name = buf;
104 goto out;
105 };
106 } else if (!our_mnt(path->mnt))
107 connected = 0; 109 connected = 0;
108 110
109 *name = res; 111ok:
110
111 /* Handle two cases: 112 /* Handle two cases:
112 * 1. A deleted dentry && profile is not allowing mediation of deleted 113 * 1. A deleted dentry && profile is not allowing mediation of deleted
113 * 2. On some filesystems, newly allocated dentries appear to the 114 * 2. On some filesystems, newly allocated dentries appear to the
@@ -138,7 +139,7 @@ static int d_namespace_path(struct path *path, char *buf, int buflen,
138 /* disconnected path, don't return pathname starting 139 /* disconnected path, don't return pathname starting
139 * with '/' 140 * with '/'
140 */ 141 */
141 error = -EACCES; 142 error = -ESTALE;
142 if (*res == '/') 143 if (*res == '/')
143 *name = res + 1; 144 *name = res + 1;
144 } 145 }
@@ -159,7 +160,7 @@ out:
159 * Returns: %0 else error on failure 160 * Returns: %0 else error on failure
160 */ 161 */
161static int get_name_to_buffer(struct path *path, int flags, char *buffer, 162static int get_name_to_buffer(struct path *path, int flags, char *buffer,
162 int size, char **name, const char **info) 163 int size, char **name)
163{ 164{
164 int adjust = (flags & PATH_IS_DIR) ? 1 : 0; 165 int adjust = (flags & PATH_IS_DIR) ? 1 : 0;
165 int error = d_namespace_path(path, buffer, size - adjust, name, flags); 166 int error = d_namespace_path(path, buffer, size - adjust, name, flags);
@@ -171,27 +172,15 @@ static int get_name_to_buffer(struct path *path, int flags, char *buffer,
171 */ 172 */
172 strcpy(&buffer[size - 2], "/"); 173 strcpy(&buffer[size - 2], "/");
173 174
174 if (info && error) {
175 if (error == -ENOENT)
176 *info = "Failed name lookup - deleted entry";
177 else if (error == -ESTALE)
178 *info = "Failed name lookup - disconnected path";
179 else if (error == -ENAMETOOLONG)
180 *info = "Failed name lookup - name too long";
181 else
182 *info = "Failed name lookup";
183 }
184
185 return error; 175 return error;
186} 176}
187 177
188/** 178/**
189 * aa_path_name - compute the pathname of a file 179 * aa_get_name - compute the pathname of a file
190 * @path: path the file (NOT NULL) 180 * @path: path the file (NOT NULL)
191 * @flags: flags controlling path name generation 181 * @flags: flags controlling path name generation
192 * @buffer: buffer that aa_get_name() allocated (NOT NULL) 182 * @buffer: buffer that aa_get_name() allocated (NOT NULL)
193 * @name: Returns - the generated path name if !error (NOT NULL) 183 * @name: Returns - the generated path name if !error (NOT NULL)
194 * @info: Returns - information on why the path lookup failed (MAYBE NULL)
195 * 184 *
196 * @name is a pointer to the beginning of the pathname (which usually differs 185 * @name is a pointer to the beginning of the pathname (which usually differs
197 * from the beginning of the buffer), or NULL. If there is an error @name 186 * from the beginning of the buffer), or NULL. If there is an error @name
@@ -204,8 +193,7 @@ static int get_name_to_buffer(struct path *path, int flags, char *buffer,
204 * 193 *
205 * Returns: %0 else error code if could retrieve name 194 * Returns: %0 else error code if could retrieve name
206 */ 195 */
207int aa_path_name(struct path *path, int flags, char **buffer, const char **name, 196int aa_get_name(struct path *path, int flags, char **buffer, const char **name)
208 const char **info)
209{ 197{
210 char *buf, *str = NULL; 198 char *buf, *str = NULL;
211 int size = 256; 199 int size = 256;
@@ -219,7 +207,7 @@ int aa_path_name(struct path *path, int flags, char **buffer, const char **name,
219 if (!buf) 207 if (!buf)
220 return -ENOMEM; 208 return -ENOMEM;
221 209
222 error = get_name_to_buffer(path, flags, buf, size, &str, info); 210 error = get_name_to_buffer(path, flags, buf, size, &str);
223 if (error != -ENAMETOOLONG) 211 if (error != -ENAMETOOLONG)
224 break; 212 break;
225 213
@@ -227,7 +215,6 @@ int aa_path_name(struct path *path, int flags, char **buffer, const char **name,
227 size <<= 1; 215 size <<= 1;
228 if (size > aa_g_path_max) 216 if (size > aa_g_path_max)
229 return -ENAMETOOLONG; 217 return -ENAMETOOLONG;
230 *info = NULL;
231 } 218 }
232 *buffer = buf; 219 *buffer = buf;
233 *name = str; 220 *name = str;
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index 813200384d9..4f0eadee78b 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -93,7 +93,7 @@
93/* root profile namespace */ 93/* root profile namespace */
94struct aa_namespace *root_ns; 94struct aa_namespace *root_ns;
95 95
96const char *const profile_mode_names[] = { 96const char *profile_mode_names[] = {
97 "enforce", 97 "enforce",
98 "complain", 98 "complain",
99 "kill", 99 "kill",
@@ -724,8 +724,6 @@ fail:
724 */ 724 */
725static void free_profile(struct aa_profile *profile) 725static void free_profile(struct aa_profile *profile)
726{ 726{
727 struct aa_profile *p;
728
729 AA_DEBUG("%s(%p)\n", __func__, profile); 727 AA_DEBUG("%s(%p)\n", __func__, profile);
730 728
731 if (!profile) 729 if (!profile)
@@ -751,29 +749,8 @@ static void free_profile(struct aa_profile *profile)
751 749
752 aa_free_sid(profile->sid); 750 aa_free_sid(profile->sid);
753 aa_put_dfa(profile->xmatch); 751 aa_put_dfa(profile->xmatch);
754 aa_put_dfa(profile->policy.dfa); 752
755 753 aa_put_profile(profile->replacedby);
756 /* put the profile reference for replacedby, but not via
757 * put_profile(kref_put).
758 * replacedby can form a long chain that can result in cascading
759 * frees that blows the stack because kref_put makes a nested fn
760 * call (it looks like recursion, with free_profile calling
761 * free_profile) for each profile in the chain lp#1056078.
762 */
763 for (p = profile->replacedby; p; ) {
764 if (atomic_dec_and_test(&p->base.count.refcount)) {
765 /* no more refs on p, grab its replacedby */
766 struct aa_profile *next = p->replacedby;
767 /* break the chain */
768 p->replacedby = NULL;
769 /* now free p, chain is broken */
770 free_profile(p);
771
772 /* follow up with next profile in the chain */
773 p = next;
774 } else
775 break;
776 }
777 754
778 kzfree(profile); 755 kzfree(profile);
779} 756}
@@ -925,10 +902,6 @@ struct aa_profile *aa_lookup_profile(struct aa_namespace *ns, const char *hname)
925 profile = aa_get_profile(__lookup_profile(&ns->base, hname)); 902 profile = aa_get_profile(__lookup_profile(&ns->base, hname));
926 read_unlock(&ns->lock); 903 read_unlock(&ns->lock);
927 904
928 /* the unconfined profile is not in the regular profile list */
929 if (!profile && strcmp(hname, "unconfined") == 0)
930 profile = aa_get_profile(ns->unconfined);
931
932 /* refcount released by caller */ 905 /* refcount released by caller */
933 return profile; 906 return profile;
934} 907}
@@ -990,13 +963,11 @@ static int audit_policy(int op, gfp_t gfp, const char *name, const char *info,
990 int error) 963 int error)
991{ 964{
992 struct common_audit_data sa; 965 struct common_audit_data sa;
993 struct apparmor_audit_data aad = {0,}; 966 COMMON_AUDIT_DATA_INIT(&sa, NONE);
994 sa.type = LSM_AUDIT_DATA_NONE; 967 sa.aad.op = op;
995 sa.aad = &aad; 968 sa.aad.name = name;
996 aad.op = op; 969 sa.aad.info = info;
997 aad.name = name; 970 sa.aad.error = error;
998 aad.info = info;
999 aad.error = error;
1000 971
1001 return aa_audit(AUDIT_APPARMOR_STATUS, __aa_current_profile(), gfp, 972 return aa_audit(AUDIT_APPARMOR_STATUS, __aa_current_profile(), gfp,
1002 &sa, NULL); 973 &sa, NULL);
diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
index 329b1fd3074..d6d9a57b565 100644
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -70,13 +70,13 @@ struct aa_ext {
70static void audit_cb(struct audit_buffer *ab, void *va) 70static void audit_cb(struct audit_buffer *ab, void *va)
71{ 71{
72 struct common_audit_data *sa = va; 72 struct common_audit_data *sa = va;
73 if (sa->aad->iface.target) { 73 if (sa->aad.iface.target) {
74 struct aa_profile *name = sa->aad->iface.target; 74 struct aa_profile *name = sa->aad.iface.target;
75 audit_log_format(ab, " name="); 75 audit_log_format(ab, " name=");
76 audit_log_untrustedstring(ab, name->base.hname); 76 audit_log_untrustedstring(ab, name->base.hname);
77 } 77 }
78 if (sa->aad->iface.pos) 78 if (sa->aad.iface.pos)
79 audit_log_format(ab, " offset=%ld", sa->aad->iface.pos); 79 audit_log_format(ab, " offset=%ld", sa->aad.iface.pos);
80} 80}
81 81
82/** 82/**
@@ -84,7 +84,7 @@ static void audit_cb(struct audit_buffer *ab, void *va)
84 * @new: profile if it has been allocated (MAYBE NULL) 84 * @new: profile if it has been allocated (MAYBE NULL)
85 * @name: name of the profile being manipulated (MAYBE NULL) 85 * @name: name of the profile being manipulated (MAYBE NULL)
86 * @info: any extra info about the failure (MAYBE NULL) 86 * @info: any extra info about the failure (MAYBE NULL)
87 * @e: buffer position info 87 * @e: buffer position info (NOT NULL)
88 * @error: error code 88 * @error: error code
89 * 89 *
90 * Returns: %0 or error 90 * Returns: %0 or error
@@ -94,15 +94,12 @@ static int audit_iface(struct aa_profile *new, const char *name,
94{ 94{
95 struct aa_profile *profile = __aa_current_profile(); 95 struct aa_profile *profile = __aa_current_profile();
96 struct common_audit_data sa; 96 struct common_audit_data sa;
97 struct apparmor_audit_data aad = {0,}; 97 COMMON_AUDIT_DATA_INIT(&sa, NONE);
98 sa.type = LSM_AUDIT_DATA_NONE; 98 sa.aad.iface.pos = e->pos - e->start;
99 sa.aad = &aad; 99 sa.aad.iface.target = new;
100 if (e) 100 sa.aad.name = name;
101 aad.iface.pos = e->pos - e->start; 101 sa.aad.info = info;
102 aad.iface.target = new; 102 sa.aad.error = error;
103 aad.name = name;
104 aad.info = info;
105 aad.error = error;
106 103
107 return aa_audit(AUDIT_APPARMOR_STATUS, profile, GFP_KERNEL, &sa, 104 return aa_audit(AUDIT_APPARMOR_STATUS, profile, GFP_KERNEL, &sa,
108 audit_cb); 105 audit_cb);
@@ -384,11 +381,11 @@ static bool unpack_trans_table(struct aa_ext *e, struct aa_profile *profile)
384 profile->file.trans.size = size; 381 profile->file.trans.size = size;
385 for (i = 0; i < size; i++) { 382 for (i = 0; i < size; i++) {
386 char *str; 383 char *str;
387 int c, j, size2 = unpack_strdup(e, &str, NULL); 384 int c, j, size = unpack_strdup(e, &str, NULL);
388 /* unpack_strdup verifies that the last character is 385 /* unpack_strdup verifies that the last character is
389 * null termination byte. 386 * null termination byte.
390 */ 387 */
391 if (!size2) 388 if (!size)
392 goto fail; 389 goto fail;
393 profile->file.trans.table[i] = str; 390 profile->file.trans.table[i] = str;
394 /* verify that name doesn't start with space */ 391 /* verify that name doesn't start with space */
@@ -396,7 +393,7 @@ static bool unpack_trans_table(struct aa_ext *e, struct aa_profile *profile)
396 goto fail; 393 goto fail;
397 394
398 /* count internal # of internal \0 */ 395 /* count internal # of internal \0 */
399 for (c = j = 0; j < size2 - 2; j++) { 396 for (c = j = 0; j < size - 2; j++) {
400 if (!str[j]) 397 if (!str[j])
401 c++; 398 c++;
402 } 399 }
@@ -443,11 +440,11 @@ static bool unpack_rlimits(struct aa_ext *e, struct aa_profile *profile)
443 if (size > RLIM_NLIMITS) 440 if (size > RLIM_NLIMITS)
444 goto fail; 441 goto fail;
445 for (i = 0; i < size; i++) { 442 for (i = 0; i < size; i++) {
446 u64 tmp2 = 0; 443 u64 tmp = 0;
447 int a = aa_map_resource(i); 444 int a = aa_map_resource(i);
448 if (!unpack_u64(e, &tmp2, NULL)) 445 if (!unpack_u64(e, &tmp, NULL))
449 goto fail; 446 goto fail;
450 profile->rlimits.limits[a].rlim_max = tmp2; 447 profile->rlimits.limits[a].rlim_max = tmp;
451 } 448 }
452 if (!unpack_nameX(e, AA_ARRAYEND, NULL)) 449 if (!unpack_nameX(e, AA_ARRAYEND, NULL))
453 goto fail; 450 goto fail;
@@ -471,7 +468,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
471{ 468{
472 struct aa_profile *profile = NULL; 469 struct aa_profile *profile = NULL;
473 const char *name = NULL; 470 const char *name = NULL;
474 int i, error = -EPROTO; 471 int error = -EPROTO;
475 kernel_cap_t tmpcap; 472 kernel_cap_t tmpcap;
476 u32 tmp; 473 u32 tmp;
477 474
@@ -557,35 +554,11 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
557 goto fail; 554 goto fail;
558 if (!unpack_u32(e, &(profile->caps.extended.cap[1]), NULL)) 555 if (!unpack_u32(e, &(profile->caps.extended.cap[1]), NULL))
559 goto fail; 556 goto fail;
560 if (!unpack_nameX(e, AA_STRUCTEND, NULL))
561 goto fail;
562 } 557 }
563 558
564 if (!unpack_rlimits(e, profile)) 559 if (!unpack_rlimits(e, profile))
565 goto fail; 560 goto fail;
566 561
567 if (unpack_nameX(e, AA_STRUCT, "policydb")) {
568 /* generic policy dfa - optional and may be NULL */
569 profile->policy.dfa = unpack_dfa(e);
570 if (IS_ERR(profile->policy.dfa)) {
571 error = PTR_ERR(profile->policy.dfa);
572 profile->policy.dfa = NULL;
573 goto fail;
574 }
575 if (!unpack_u32(e, &profile->policy.start[0], "start"))
576 /* default start state */
577 profile->policy.start[0] = DFA_START;
578 /* setup class index */
579 for (i = AA_CLASS_FILE; i <= AA_CLASS_LAST; i++) {
580 profile->policy.start[i] =
581 aa_dfa_next(profile->policy.dfa,
582 profile->policy.start[0],
583 i);
584 }
585 if (!unpack_nameX(e, AA_STRUCTEND, NULL))
586 goto fail;
587 }
588
589 /* get file rules */ 562 /* get file rules */
590 profile->file.dfa = unpack_dfa(e); 563 profile->file.dfa = unpack_dfa(e);
591 if (IS_ERR(profile->file.dfa)) { 564 if (IS_ERR(profile->file.dfa)) {
diff --git a/security/apparmor/procattr.c b/security/apparmor/procattr.c
index 1b41c542d37..04a2cf8d1b6 100644
--- a/security/apparmor/procattr.c
+++ b/security/apparmor/procattr.c
@@ -16,7 +16,6 @@
16#include "include/context.h" 16#include "include/context.h"
17#include "include/policy.h" 17#include "include/policy.h"
18#include "include/domain.h" 18#include "include/domain.h"
19#include "include/procattr.h"
20 19
21 20
22/** 21/**
diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c
index e1f3d7ef2c5..a4136c10b1c 100644
--- a/security/apparmor/resource.c
+++ b/security/apparmor/resource.c
@@ -23,18 +23,13 @@
23 */ 23 */
24#include "rlim_names.h" 24#include "rlim_names.h"
25 25
26struct aa_fs_entry aa_fs_entry_rlimit[] = {
27 AA_FS_FILE_STRING("mask", AA_FS_RLIMIT_MASK),
28 { }
29};
30
31/* audit callback for resource specific fields */ 26/* audit callback for resource specific fields */
32static void audit_cb(struct audit_buffer *ab, void *va) 27static void audit_cb(struct audit_buffer *ab, void *va)
33{ 28{
34 struct common_audit_data *sa = va; 29 struct common_audit_data *sa = va;
35 30
36 audit_log_format(ab, " rlimit=%s value=%lu", 31 audit_log_format(ab, " rlimit=%s value=%lu",
37 rlim_names[sa->aad->rlim.rlim], sa->aad->rlim.max); 32 rlim_names[sa->aad.rlim.rlim], sa->aad.rlim.max);
38} 33}
39 34
40/** 35/**
@@ -50,14 +45,12 @@ static int audit_resource(struct aa_profile *profile, unsigned int resource,
50 unsigned long value, int error) 45 unsigned long value, int error)
51{ 46{
52 struct common_audit_data sa; 47 struct common_audit_data sa;
53 struct apparmor_audit_data aad = {0,};
54 48
55 sa.type = LSM_AUDIT_DATA_NONE; 49 COMMON_AUDIT_DATA_INIT(&sa, NONE);
56 sa.aad = &aad; 50 sa.aad.op = OP_SETRLIMIT,
57 aad.op = OP_SETRLIMIT, 51 sa.aad.rlim.rlim = resource;
58 aad.rlim.rlim = resource; 52 sa.aad.rlim.max = value;
59 aad.rlim.max = value; 53 sa.aad.error = error;
60 aad.error = error;
61 return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_KERNEL, &sa, 54 return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_KERNEL, &sa,
62 audit_cb); 55 audit_cb);
63} 56}