aboutsummaryrefslogtreecommitdiffstats
path: root/security/apparmor
diff options
context:
space:
mode:
Diffstat (limited to 'security/apparmor')
-rw-r--r--security/apparmor/Makefile27
-rw-r--r--security/apparmor/apparmorfs.c195
-rw-r--r--security/apparmor/audit.c7
-rw-r--r--security/apparmor/domain.c5
-rw-r--r--security/apparmor/file.c21
-rw-r--r--security/apparmor/include/apparmor.h15
-rw-r--r--security/apparmor/include/apparmorfs.h44
-rw-r--r--security/apparmor/include/audit.h9
-rw-r--r--security/apparmor/include/file.h2
-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/match.c80
-rw-r--r--security/apparmor/path.c56
-rw-r--r--security/apparmor/policy.c3
-rw-r--r--security/apparmor/policy_unpack.c31
-rw-r--r--security/apparmor/resource.c5
18 files changed, 419 insertions, 106 deletions
diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
index 2dafe50a2e25..806bd19af7f2 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 *capability_names[] = {" > $@ ;\ 18cmd_make-caps = echo "static const char *const 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,25 +28,38 @@ cmd_make-caps = echo "static const char *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 Thi is 31# RLIMIT defines to the order defined in asm-generic/resource.h This 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"
38quiet_cmd_make-rlim = GEN $@ 45quiet_cmd_make-rlim = GEN $@
39cmd_make-rlim = echo "static const char *rlim_names[] = {" > $@ ;\ 46cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \
47 > $@ ;\
40 sed $< >> $@ -r -n \ 48 sed $< >> $@ -r -n \
41 -e 's/^\# ?define[ \t]+(RLIMIT_([A-Z0-9_]+)).*/[\1] = "\L\2",/p';\ 49 -e 's/^\# ?define[ \t]+(RLIMIT_([A-Z0-9_]+)).*/[\1] = "\L\2",/p';\
42 echo "};" >> $@ ;\ 50 echo "};" >> $@ ;\
43 echo "static const int rlim_map[] = {" >> $@ ;\ 51 echo "static const int rlim_map[RLIM_NLIMITS] = {" >> $@ ;\
44 sed -r -n "s/^\# ?define[ \t]+(RLIMIT_[A-Z0-9_]+).*/\1,/p" $< >> $@ ;\ 52 sed -r -n "s/^\# ?define[ \t]+(RLIMIT_[A-Z0-9_]+).*/\1,/p" $< >> $@ ;\
45 echo "};" >> $@ 53 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/' >> $@
46 57
47$(obj)/capability.o : $(obj)/capability_names.h 58$(obj)/capability.o : $(obj)/capability_names.h
48$(obj)/resource.o : $(obj)/rlim_names.h 59$(obj)/resource.o : $(obj)/rlim_names.h
49$(obj)/capability_names.h : $(srctree)/include/linux/capability.h 60$(obj)/capability_names.h : $(srctree)/include/linux/capability.h \
61 $(src)/Makefile
50 $(call cmd,make-caps) 62 $(call cmd,make-caps)
51$(obj)/rlim_names.h : $(srctree)/include/asm-generic/resource.h 63$(obj)/rlim_names.h : $(srctree)/include/asm-generic/resource.h \
64 $(src)/Makefile
52 $(call cmd,make-rlim) 65 $(call cmd,make-rlim)
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index e39df6d43779..16c15ec6f670 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -18,12 +18,14 @@
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>
21 22
22#include "include/apparmor.h" 23#include "include/apparmor.h"
23#include "include/apparmorfs.h" 24#include "include/apparmorfs.h"
24#include "include/audit.h" 25#include "include/audit.h"
25#include "include/context.h" 26#include "include/context.h"
26#include "include/policy.h" 27#include "include/policy.h"
28#include "include/resource.h"
27 29
28/** 30/**
29 * aa_simple_write_to_buffer - common routine for getting policy from user 31 * aa_simple_write_to_buffer - common routine for getting policy from user
@@ -142,38 +144,166 @@ static const struct file_operations aa_fs_profile_remove = {
142 .llseek = default_llseek, 144 .llseek = default_llseek,
143}; 145};
144 146
145/** Base file system setup **/ 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;
146 153
147static struct dentry *aa_fs_dentry __initdata; 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}
148 171
149static void __init aafs_remove(const char *name) 172static int aa_fs_seq_open(struct inode *inode, struct file *file)
150{ 173{
151 struct dentry *dentry; 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 **/
186
187static struct aa_fs_entry aa_fs_entry_file[] = {
188 AA_FS_FILE_STRING("mask", "create read write exec append mmap_exec " \
189 "link lock"),
190 { }
191};
152 192
153 dentry = lookup_one_len(name, aa_fs_dentry, strlen(name)); 193static struct aa_fs_entry aa_fs_entry_domain[] = {
154 if (!IS_ERR(dentry)) { 194 AA_FS_FILE_BOOLEAN("change_hat", 1),
155 securityfs_remove(dentry); 195 AA_FS_FILE_BOOLEAN("change_hatv", 1),
156 dput(dentry); 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{
230 int error = 0;
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;
157 } 239 }
240 return error;
158} 241}
159 242
160/** 243/**
161 * aafs_create - create an entry in the apparmor filesystem 244 * aafs_create_dir - recursively create a directory entry in the securityfs
162 * @name: name of the entry (NOT NULL) 245 * @fs_dir: aa_fs_entry (and all child entries) to build (NOT NULL)
163 * @mask: file permission mask of the file 246 * @parent: the parent dentry in the securityfs
164 * @fops: file operations for the file (NOT NULL)
165 * 247 *
166 * Used aafs_remove to remove entries created with this fn. 248 * Use aafs_remove_dir to remove entries created with this fn.
167 */ 249 */
168static int __init aafs_create(const char *name, umode_t mask, 250static int __init aafs_create_dir(struct aa_fs_entry *fs_dir,
169 const struct file_operations *fops) 251 struct dentry *parent)
170{ 252{
171 struct dentry *dentry; 253 int error;
254 struct aa_fs_entry *fs_file;
172 255
173 dentry = securityfs_create_file(name, S_IFREG | mask, aa_fs_dentry, 256 fs_dir->dentry = securityfs_create_dir(fs_dir->name, parent);
174 NULL, fops); 257 if (IS_ERR(fs_dir->dentry)) {
258 error = PTR_ERR(fs_dir->dentry);
259 fs_dir->dentry = NULL;
260 goto failed;
261 }
175 262
176 return IS_ERR(dentry) ? PTR_ERR(dentry) : 0; 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 }
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}
290
291/**
292 * aafs_remove_dir - recursively drop a directory entry from the securityfs
293 * @fs_dir: aa_fs_entry (and all child entries) to detach (NOT NULL)
294 */
295static void __init aafs_remove_dir(struct aa_fs_entry *fs_dir)
296{
297 struct aa_fs_entry *fs_file;
298
299 for (fs_file = fs_dir->v.files; fs_file->name; ++fs_file) {
300 if (fs_file->v_type == AA_FS_TYPE_DIR)
301 aafs_remove_dir(fs_file);
302 else
303 aafs_remove_file(fs_file);
304 }
305
306 aafs_remove_file(fs_dir);
177} 307}
178 308
179/** 309/**
@@ -183,14 +313,7 @@ static int __init aafs_create(const char *name, umode_t mask,
183 */ 313 */
184void __init aa_destroy_aafs(void) 314void __init aa_destroy_aafs(void)
185{ 315{
186 if (aa_fs_dentry) { 316 aafs_remove_dir(&aa_fs_entry);
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 }
194} 317}
195 318
196/** 319/**
@@ -207,25 +330,13 @@ static int __init aa_create_aafs(void)
207 if (!apparmor_initialized) 330 if (!apparmor_initialized)
208 return 0; 331 return 0;
209 332
210 if (aa_fs_dentry) { 333 if (aa_fs_entry.dentry) {
211 AA_ERROR("%s: AppArmor securityfs already exists\n", __func__); 334 AA_ERROR("%s: AppArmor securityfs already exists\n", __func__);
212 return -EEXIST; 335 return -EEXIST;
213 } 336 }
214 337
215 aa_fs_dentry = securityfs_create_dir("apparmor", NULL); 338 /* Populate fs tree. */
216 if (IS_ERR(aa_fs_dentry)) { 339 error = aafs_create_dir(&aa_fs_entry, NULL);
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);
229 if (error) 340 if (error)
230 goto error; 341 goto error;
231 342
diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c
index f3fafedd798a..5ff67776a5ad 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 *op_table[] = { 22const char *const op_table[] = {
23 "null", 23 "null",
24 24
25 "sysctl", 25 "sysctl",
@@ -73,7 +73,7 @@ const char *op_table[] = {
73 "profile_remove" 73 "profile_remove"
74}; 74};
75 75
76const char *audit_mode_names[] = { 76const char *const audit_mode_names[] = {
77 "normal", 77 "normal",
78 "quiet_denied", 78 "quiet_denied",
79 "quiet", 79 "quiet",
@@ -81,7 +81,7 @@ const char *audit_mode_names[] = {
81 "all" 81 "all"
82}; 82};
83 83
84static char *aa_audit_type[] = { 84static const char *const aa_audit_type[] = {
85 "AUDIT", 85 "AUDIT",
86 "ALLOWED", 86 "ALLOWED",
87 "DENIED", 87 "DENIED",
@@ -89,6 +89,7 @@ static char *aa_audit_type[] = {
89 "STATUS", 89 "STATUS",
90 "ERROR", 90 "ERROR",
91 "KILLED" 91 "KILLED"
92 "AUTO"
92}; 93};
93 94
94/* 95/*
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index c1e18ba5bdc0..7c69599a69e1 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -372,13 +372,12 @@ 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_get_name(&bprm->file->f_path, profile->path_flags, &buffer, 375 error = aa_path_name(&bprm->file->f_path, profile->path_flags, &buffer,
376 &name); 376 &name, &info);
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";
382 name = bprm->filename; 381 name = bprm->filename;
383 goto audit; 382 goto audit;
384 } 383 }
diff --git a/security/apparmor/file.c b/security/apparmor/file.c
index 7312db741219..3022c0f4f0db 100644
--- a/security/apparmor/file.c
+++ b/security/apparmor/file.c
@@ -173,8 +173,6 @@ static u32 map_old_perms(u32 old)
173 if (old & 0x40) /* AA_EXEC_MMAP */ 173 if (old & 0x40) /* AA_EXEC_MMAP */
174 new |= AA_EXEC_MMAP; 174 new |= AA_EXEC_MMAP;
175 175
176 new |= AA_MAY_META_READ;
177
178 return new; 176 return new;
179} 177}
180 178
@@ -212,6 +210,7 @@ static struct file_perms compute_perms(struct aa_dfa *dfa, unsigned int state,
212 perms.quiet = map_old_perms(dfa_other_quiet(dfa, state)); 210 perms.quiet = map_old_perms(dfa_other_quiet(dfa, state));
213 perms.xindex = dfa_other_xindex(dfa, state); 211 perms.xindex = dfa_other_xindex(dfa, state);
214 } 212 }
213 perms.allow |= AA_MAY_META_READ;
215 214
216 /* change_profile wasn't determined by ownership in old mapping */ 215 /* change_profile wasn't determined by ownership in old mapping */
217 if (ACCEPT_TABLE(dfa)[state] & 0x80000000) 216 if (ACCEPT_TABLE(dfa)[state] & 0x80000000)
@@ -279,22 +278,16 @@ int aa_path_perm(int op, struct aa_profile *profile, struct path *path,
279 int error; 278 int error;
280 279
281 flags |= profile->path_flags | (S_ISDIR(cond->mode) ? PATH_IS_DIR : 0); 280 flags |= profile->path_flags | (S_ISDIR(cond->mode) ? PATH_IS_DIR : 0);
282 error = aa_get_name(path, flags, &buffer, &name); 281 error = aa_path_name(path, flags, &buffer, &name, &info);
283 if (error) { 282 if (error) {
284 if (error == -ENOENT && is_deleted(path->dentry)) { 283 if (error == -ENOENT && is_deleted(path->dentry)) {
285 /* Access to open files that are deleted are 284 /* Access to open files that are deleted are
286 * give a pass (implicit delegation) 285 * give a pass (implicit delegation)
287 */ 286 */
288 error = 0; 287 error = 0;
288 info = NULL;
289 perms.allow = request; 289 perms.allow = request;
290 } else if (error == -ENOENT) 290 }
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";
298 } else { 291 } else {
299 aa_str_perms(profile->file.dfa, profile->file.start, name, cond, 292 aa_str_perms(profile->file.dfa, profile->file.start, name, cond,
300 &perms); 293 &perms);
@@ -365,12 +358,14 @@ int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
365 lperms = nullperms; 358 lperms = nullperms;
366 359
367 /* buffer freed below, lname is pointer in buffer */ 360 /* buffer freed below, lname is pointer in buffer */
368 error = aa_get_name(&link, profile->path_flags, &buffer, &lname); 361 error = aa_path_name(&link, profile->path_flags, &buffer, &lname,
362 &info);
369 if (error) 363 if (error)
370 goto audit; 364 goto audit;
371 365
372 /* buffer2 freed below, tname is pointer in buffer2 */ 366 /* buffer2 freed below, tname is pointer in buffer2 */
373 error = aa_get_name(&target, profile->path_flags, &buffer2, &tname); 367 error = aa_path_name(&target, profile->path_flags, &buffer2, &tname,
368 &info);
374 if (error) 369 if (error)
375 goto audit; 370 goto audit;
376 371
diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h
index df3649560818..40aedd9f73ea 100644
--- a/security/apparmor/include/apparmor.h
+++ b/security/apparmor/include/apparmor.h
@@ -19,6 +19,19 @@
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
22/* Control parameters settable through module/boot flags */ 35/* Control parameters settable through module/boot flags */
23extern enum audit_mode aa_g_audit; 36extern enum audit_mode aa_g_audit;
24extern bool aa_g_audit_header; 37extern bool aa_g_audit_header;
@@ -81,7 +94,7 @@ static inline unsigned int aa_dfa_null_transition(struct aa_dfa *dfa,
81 unsigned int start) 94 unsigned int start)
82{ 95{
83 /* the null transition only needs the string's null terminator byte */ 96 /* the null transition only needs the string's null terminator byte */
84 return aa_dfa_match_len(dfa, start, "", 1); 97 return aa_dfa_next(dfa, start, 0);
85} 98}
86 99
87static inline bool mediated_filesystem(struct inode *inode) 100static inline bool mediated_filesystem(struct inode *inode)
diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h
index cb1e93a114d7..7ea4769fab3f 100644
--- a/security/apparmor/include/apparmorfs.h
+++ b/security/apparmor/include/apparmorfs.h
@@ -15,6 +15,50 @@
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
18extern void __init aa_destroy_aafs(void); 62extern void __init aa_destroy_aafs(void);
19 63
20#endif /* __AA_APPARMORFS_H */ 64#endif /* __AA_APPARMORFS_H */
diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
index 1951786d32e9..4ba78c203af1 100644
--- a/security/apparmor/include/audit.h
+++ b/security/apparmor/include/audit.h
@@ -25,11 +25,9 @@
25 25
26struct aa_profile; 26struct aa_profile;
27 27
28extern const char *audit_mode_names[]; 28extern const char *const 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
33enum audit_mode { 31enum audit_mode {
34 AUDIT_NORMAL, /* follow normal auditing of accesses */ 32 AUDIT_NORMAL, /* follow normal auditing of accesses */
35 AUDIT_QUIET_DENIED, /* quiet all denied access messages */ 33 AUDIT_QUIET_DENIED, /* quiet all denied access messages */
@@ -45,10 +43,11 @@ enum audit_type {
45 AUDIT_APPARMOR_HINT, 43 AUDIT_APPARMOR_HINT,
46 AUDIT_APPARMOR_STATUS, 44 AUDIT_APPARMOR_STATUS,
47 AUDIT_APPARMOR_ERROR, 45 AUDIT_APPARMOR_ERROR,
48 AUDIT_APPARMOR_KILL 46 AUDIT_APPARMOR_KILL,
47 AUDIT_APPARMOR_AUTO
49}; 48};
50 49
51extern const char *op_table[]; 50extern const char *const op_table[];
52enum aa_ops { 51enum aa_ops {
53 OP_NULL, 52 OP_NULL,
54 53
diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h
index ab8c6d87f758..f98fd4701d80 100644
--- a/security/apparmor/include/file.h
+++ b/security/apparmor/include/file.h
@@ -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 { 120 } else if (old_index) {
121 index |= AA_X_TABLE; 121 index |= AA_X_TABLE;
122 index |= old_index - 4; 122 index |= old_index - 4;
123 } 123 }
diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h
index a4a863997bd5..775843e7f984 100644
--- a/security/apparmor/include/match.h
+++ b/security/apparmor/include/match.h
@@ -116,6 +116,9 @@ 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
119void aa_dfa_free_kref(struct kref *kref); 122void aa_dfa_free_kref(struct kref *kref);
120 123
121/** 124/**
diff --git a/security/apparmor/include/path.h b/security/apparmor/include/path.h
index 27b327a7fae5..286ac75dc88b 100644
--- a/security/apparmor/include/path.h
+++ b/security/apparmor/include/path.h
@@ -26,6 +26,7 @@ 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_get_name(struct path *path, int flags, char **buffer, const char **name); 29int aa_path_name(struct path *path, int flags, char **buffer,
30 const char **name, const char **info);
30 31
31#endif /* __AA_PATH_H */ 32#endif /* __AA_PATH_H */
diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
index aeda5cf56904..bda4569fdd83 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 *profile_mode_names[]; 32extern const char *const 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,6 +129,17 @@ 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
132/* struct aa_profile - basic confinement data 143/* struct aa_profile - basic confinement data
133 * @base - base components of the profile (name, refcount, lists, lock ...) 144 * @base - base components of the profile (name, refcount, lists, lock ...)
134 * @parent: parent of profile 145 * @parent: parent of profile
@@ -143,6 +154,7 @@ struct aa_namespace {
143 * @flags: flags controlling profile behavior 154 * @flags: flags controlling profile behavior
144 * @path_flags: flags controlling path generation behavior 155 * @path_flags: flags controlling path generation behavior
145 * @size: the memory consumed by this profiles rules 156 * @size: the memory consumed by this profiles rules
157 * @policy: general match rules governing policy
146 * @file: The set of rules governing basic file access and domain transitions 158 * @file: The set of rules governing basic file access and domain transitions
147 * @caps: capabilities for the profile 159 * @caps: capabilities for the profile
148 * @rlimits: rlimits for the profile 160 * @rlimits: rlimits for the profile
@@ -179,6 +191,7 @@ struct aa_profile {
179 u32 path_flags; 191 u32 path_flags;
180 int size; 192 int size;
181 193
194 struct aa_policydb policy;
182 struct aa_file_rules file; 195 struct aa_file_rules file;
183 struct aa_caps caps; 196 struct aa_caps caps;
184 struct aa_rlimit rlimits; 197 struct aa_rlimit rlimits;
diff --git a/security/apparmor/include/resource.h b/security/apparmor/include/resource.h
index 02baec732bb5..d3f4cf027957 100644
--- a/security/apparmor/include/resource.h
+++ b/security/apparmor/include/resource.h
@@ -18,6 +18,8 @@
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
21struct aa_profile; 23struct aa_profile;
22 24
23/* struct aa_rlimit - rlimit settings for the profile 25/* struct aa_rlimit - rlimit settings for the profile
@@ -32,6 +34,8 @@ struct aa_rlimit {
32 struct rlimit limits[RLIM_NLIMITS]; 34 struct rlimit limits[RLIM_NLIMITS];
33}; 35};
34 36
37extern struct aa_fs_entry aa_fs_entry_rlimit[];
38
35int aa_map_resource(int resource); 39int aa_map_resource(int resource);
36int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *, 40int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *,
37 unsigned int resource, struct rlimit *new_rlim); 41 unsigned int resource, struct rlimit *new_rlim);
diff --git a/security/apparmor/match.c b/security/apparmor/match.c
index 94de6b4907c8..90971a8c3789 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_next_state - traverse @dfa to find state @str stops at 338 * aa_dfa_match - 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_next_state will match @str against the dfa and return the state it 343 * aa_dfa_match 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,5 +349,79 @@ 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 return aa_dfa_match_len(dfa, start, str, strlen(str)); 352 u16 *def = DEFAULT_TABLE(dfa);
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;
353} 427}
diff --git a/security/apparmor/path.c b/security/apparmor/path.c
index 9d070a7c3ffc..2daeea4f9266 100644
--- a/security/apparmor/path.c
+++ b/security/apparmor/path.c
@@ -83,31 +83,29 @@ static int d_namespace_path(struct path *path, char *buf, int buflen,
83 struct path root; 83 struct path root;
84 get_fs_root(current->fs, &root); 84 get_fs_root(current->fs, &root);
85 res = __d_path(path, &root, buf, buflen); 85 res = __d_path(path, &root, buf, buflen);
86 if (res && !IS_ERR(res)) {
87 /* everything's fine */
88 *name = res;
89 path_put(&root);
90 goto ok;
91 }
92 path_put(&root); 86 path_put(&root);
93 connected = 0; 87 } else {
88 res = d_absolute_path(path, buf, buflen);
89 if (!our_mnt(path->mnt))
90 connected = 0;
94 } 91 }
95 92
96 res = d_absolute_path(path, buf, buflen);
97
98 *name = res;
99 /* handle error conditions - and still allow a partial path to 93 /* handle error conditions - and still allow a partial path to
100 * be returned. 94 * be returned.
101 */ 95 */
102 if (IS_ERR(res)) { 96 if (!res || IS_ERR(res)) {
103 error = PTR_ERR(res);
104 *name = buf;
105 goto out;
106 }
107 if (!our_mnt(path->mnt))
108 connected = 0; 97 connected = 0;
98 res = dentry_path_raw(path->dentry, buf, buflen);
99 if (IS_ERR(res)) {
100 error = PTR_ERR(res);
101 *name = buf;
102 goto out;
103 };
104 } else if (!our_mnt(path->mnt))
105 connected = 0;
106
107 *name = res;
109 108
110ok:
111 /* Handle two cases: 109 /* Handle two cases:
112 * 1. A deleted dentry && profile is not allowing mediation of deleted 110 * 1. A deleted dentry && profile is not allowing mediation of deleted
113 * 2. On some filesystems, newly allocated dentries appear to the 111 * 2. On some filesystems, newly allocated dentries appear to the
@@ -138,7 +136,7 @@ ok:
138 /* disconnected path, don't return pathname starting 136 /* disconnected path, don't return pathname starting
139 * with '/' 137 * with '/'
140 */ 138 */
141 error = -ESTALE; 139 error = -EACCES;
142 if (*res == '/') 140 if (*res == '/')
143 *name = res + 1; 141 *name = res + 1;
144 } 142 }
@@ -159,7 +157,7 @@ out:
159 * Returns: %0 else error on failure 157 * Returns: %0 else error on failure
160 */ 158 */
161static int get_name_to_buffer(struct path *path, int flags, char *buffer, 159static int get_name_to_buffer(struct path *path, int flags, char *buffer,
162 int size, char **name) 160 int size, char **name, const char **info)
163{ 161{
164 int adjust = (flags & PATH_IS_DIR) ? 1 : 0; 162 int adjust = (flags & PATH_IS_DIR) ? 1 : 0;
165 int error = d_namespace_path(path, buffer, size - adjust, name, flags); 163 int error = d_namespace_path(path, buffer, size - adjust, name, flags);
@@ -171,15 +169,27 @@ static int get_name_to_buffer(struct path *path, int flags, char *buffer,
171 */ 169 */
172 strcpy(&buffer[size - 2], "/"); 170 strcpy(&buffer[size - 2], "/");
173 171
172 if (info && error) {
173 if (error == -ENOENT)
174 *info = "Failed name lookup - deleted entry";
175 else if (error == -ESTALE)
176 *info = "Failed name lookup - disconnected path";
177 else if (error == -ENAMETOOLONG)
178 *info = "Failed name lookup - name too long";
179 else
180 *info = "Failed name lookup";
181 }
182
174 return error; 183 return error;
175} 184}
176 185
177/** 186/**
178 * aa_get_name - compute the pathname of a file 187 * aa_path_name - compute the pathname of a file
179 * @path: path the file (NOT NULL) 188 * @path: path the file (NOT NULL)
180 * @flags: flags controlling path name generation 189 * @flags: flags controlling path name generation
181 * @buffer: buffer that aa_get_name() allocated (NOT NULL) 190 * @buffer: buffer that aa_get_name() allocated (NOT NULL)
182 * @name: Returns - the generated path name if !error (NOT NULL) 191 * @name: Returns - the generated path name if !error (NOT NULL)
192 * @info: Returns - information on why the path lookup failed (MAYBE NULL)
183 * 193 *
184 * @name is a pointer to the beginning of the pathname (which usually differs 194 * @name is a pointer to the beginning of the pathname (which usually differs
185 * from the beginning of the buffer), or NULL. If there is an error @name 195 * from the beginning of the buffer), or NULL. If there is an error @name
@@ -192,7 +202,8 @@ static int get_name_to_buffer(struct path *path, int flags, char *buffer,
192 * 202 *
193 * Returns: %0 else error code if could retrieve name 203 * Returns: %0 else error code if could retrieve name
194 */ 204 */
195int aa_get_name(struct path *path, int flags, char **buffer, const char **name) 205int aa_path_name(struct path *path, int flags, char **buffer, const char **name,
206 const char **info)
196{ 207{
197 char *buf, *str = NULL; 208 char *buf, *str = NULL;
198 int size = 256; 209 int size = 256;
@@ -206,7 +217,7 @@ int aa_get_name(struct path *path, int flags, char **buffer, const char **name)
206 if (!buf) 217 if (!buf)
207 return -ENOMEM; 218 return -ENOMEM;
208 219
209 error = get_name_to_buffer(path, flags, buf, size, &str); 220 error = get_name_to_buffer(path, flags, buf, size, &str, info);
210 if (error != -ENAMETOOLONG) 221 if (error != -ENAMETOOLONG)
211 break; 222 break;
212 223
@@ -214,6 +225,7 @@ int aa_get_name(struct path *path, int flags, char **buffer, const char **name)
214 size <<= 1; 225 size <<= 1;
215 if (size > aa_g_path_max) 226 if (size > aa_g_path_max)
216 return -ENAMETOOLONG; 227 return -ENAMETOOLONG;
228 *info = NULL;
217 } 229 }
218 *buffer = buf; 230 *buffer = buf;
219 *name = str; 231 *name = str;
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index 4f0eadee78b8..906414383022 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 *profile_mode_names[] = { 96const char *const profile_mode_names[] = {
97 "enforce", 97 "enforce",
98 "complain", 98 "complain",
99 "kill", 99 "kill",
@@ -749,6 +749,7 @@ static void free_profile(struct aa_profile *profile)
749 749
750 aa_free_sid(profile->sid); 750 aa_free_sid(profile->sid);
751 aa_put_dfa(profile->xmatch); 751 aa_put_dfa(profile->xmatch);
752 aa_put_dfa(profile->policy.dfa);
752 753
753 aa_put_profile(profile->replacedby); 754 aa_put_profile(profile->replacedby);
754 755
diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
index 741dd13e089b..25fd51edc8da 100644
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -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 (NOT NULL) 87 * @e: buffer position info
88 * @error: error code 88 * @error: error code
89 * 89 *
90 * Returns: %0 or error 90 * Returns: %0 or error
@@ -95,7 +95,8 @@ static int audit_iface(struct aa_profile *new, const char *name,
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 COMMON_AUDIT_DATA_INIT(&sa, NONE); 97 COMMON_AUDIT_DATA_INIT(&sa, NONE);
98 sa.aad.iface.pos = e->pos - e->start; 98 if (e)
99 sa.aad.iface.pos = e->pos - e->start;
99 sa.aad.iface.target = new; 100 sa.aad.iface.target = new;
100 sa.aad.name = name; 101 sa.aad.name = name;
101 sa.aad.info = info; 102 sa.aad.info = info;
@@ -468,7 +469,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
468{ 469{
469 struct aa_profile *profile = NULL; 470 struct aa_profile *profile = NULL;
470 const char *name = NULL; 471 const char *name = NULL;
471 int error = -EPROTO; 472 int i, error = -EPROTO;
472 kernel_cap_t tmpcap; 473 kernel_cap_t tmpcap;
473 u32 tmp; 474 u32 tmp;
474 475
@@ -554,11 +555,35 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
554 goto fail; 555 goto fail;
555 if (!unpack_u32(e, &(profile->caps.extended.cap[1]), NULL)) 556 if (!unpack_u32(e, &(profile->caps.extended.cap[1]), NULL))
556 goto fail; 557 goto fail;
558 if (!unpack_nameX(e, AA_STRUCTEND, NULL))
559 goto fail;
557 } 560 }
558 561
559 if (!unpack_rlimits(e, profile)) 562 if (!unpack_rlimits(e, profile))
560 goto fail; 563 goto fail;
561 564
565 if (unpack_nameX(e, AA_STRUCT, "policydb")) {
566 /* generic policy dfa - optional and may be NULL */
567 profile->policy.dfa = unpack_dfa(e);
568 if (IS_ERR(profile->policy.dfa)) {
569 error = PTR_ERR(profile->policy.dfa);
570 profile->policy.dfa = NULL;
571 goto fail;
572 }
573 if (!unpack_u32(e, &profile->policy.start[0], "start"))
574 /* default start state */
575 profile->policy.start[0] = DFA_START;
576 /* setup class index */
577 for (i = AA_CLASS_FILE; i <= AA_CLASS_LAST; i++) {
578 profile->policy.start[i] =
579 aa_dfa_next(profile->policy.dfa,
580 profile->policy.start[0],
581 i);
582 }
583 if (!unpack_nameX(e, AA_STRUCTEND, NULL))
584 goto fail;
585 }
586
562 /* get file rules */ 587 /* get file rules */
563 profile->file.dfa = unpack_dfa(e); 588 profile->file.dfa = unpack_dfa(e);
564 if (IS_ERR(profile->file.dfa)) { 589 if (IS_ERR(profile->file.dfa)) {
diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c
index a4136c10b1c6..72c25a4f2cfd 100644
--- a/security/apparmor/resource.c
+++ b/security/apparmor/resource.c
@@ -23,6 +23,11 @@
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
26/* audit callback for resource specific fields */ 31/* audit callback for resource specific fields */
27static void audit_cb(struct audit_buffer *ab, void *va) 32static void audit_cb(struct audit_buffer *ab, void *va)
28{ 33{