latest version of the patches, updated off of 2.6.25 dev

This commit is contained in:
John Johansen 2008-04-19 23:08:39 +00:00
parent 8c5f77c4bd
commit d4856f9680
8 changed files with 385 additions and 221 deletions

View file

@ -7,12 +7,12 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
security/apparmor/lsm.c | 879 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 879 insertions(+)
security/apparmor/lsm.c | 889 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 889 insertions(+)
--- /dev/null
+++ b/security/apparmor/lsm.c
@@ -0,0 +1,879 @@
@@ -0,0 +1,889 @@
+/*
+ * Copyright (C) 1998-2007 Novell/SUSE
+ *
@ -645,6 +645,16 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ unsigned long prot, unsigned long flags,
+ unsigned long addr, unsigned long addr_only)
+{
+ if ((addr < mmap_min_addr) && !capable(CAP_SYS_RAWIO)) {
+ struct aa_profile *profile = aa_get_profile(current);
+ if (profile)
+ /* future control check here */
+ return -EACCES;
+ else
+ return -EACCES;
+ aa_put_profile(profile);
+ }
+
+ return aa_mmap(file, "file_mmap", prot, flags);
+}
+

View file

@ -7,12 +7,12 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
security/apparmor/main.c | 1421 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 1421 insertions(+)
security/apparmor/main.c | 1479 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 1479 insertions(+)
--- /dev/null
+++ b/security/apparmor/main.c
@@ -0,0 +1,1421 @@
@@ -0,0 +1,1479 @@
+/*
+ * Copyright (C) 2002-2007 Novell/SUSE
+ *
@ -84,6 +84,8 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+static void aa_audit_file_sub_mask(struct audit_buffer *ab, char *buffer,
+ int mask)
+{
+ const char unsafex[] = "upcn";
+ const char safex[] = "UPCN";
+ char *m = buffer;
+
+ if (mask & AA_EXEC_MMAP)
@ -95,37 +97,18 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ else if (mask & MAY_APPEND)
+ *m++ = 'a';
+ if (mask & MAY_EXEC) {
+ if (mask & AA_EXEC_UNSAFE) {
+ switch(mask & AA_EXEC_MODIFIERS) {
+ case AA_EXEC_UNCONFINED:
+ *m++ = 'u';
+ break;
+ case AA_EXEC_PIX:
+ *m++ = 'p';
+ /* fall through */
+ case AA_EXEC_INHERIT:
+ *m++ = 'i';
+ break;
+ case AA_EXEC_PROFILE:
+ *m++ = 'p';
+ break;
+ }
+ } else {
+ switch(mask & AA_EXEC_MODIFIERS) {
+ case AA_EXEC_UNCONFINED:
+ *m++ = 'U';
+ break;
+ case AA_EXEC_PIX:
+ *m++ = 'P';
+ /* fall through */
+ case AA_EXEC_INHERIT:
+ *m++ = 'I';
+ break;
+ case AA_EXEC_PROFILE:
+ *m++ = 'P';
+ break;
+ }
+ int index = AA_EXEC_INDEX(mask);
+ /* all indexes > 4 are also named transitions */
+ if (index > 4)
+ index = 4;
+ if (index > 0) {
+ if (mask & AA_EXEC_UNSAFE)
+ *m++ = unsafex[index - 1];
+ else
+ *m++ = safex[index - 1];
+ }
+ if (mask & AA_EXEC_INHERIT)
+ *m++ = 'i';
+ *m++ = 'x';
+ }
+ if (mask & AA_MAY_LINK)
@ -369,7 +352,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ int *request_mask, int *audit_mask)
+{
+ unsigned int state;
+ int l_mode, t_mode, denied_mask = 0;
+ int l_mode, t_mode, l_x, t_x, denied_mask = 0;
+ int link_mask = AA_MAY_LINK << target_mode;
+
+ *request_mask = link_mask;
@ -393,7 +376,8 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ return denied_mask;
+ }
+
+ /* Do link perm subset test
+ /* Do link perm subset test requiring permission on link are a
+ * subset of the permissions on target.
+ * If a subset test is required a permission subset test of the
+ * perms for the link are done against the user::other of the
+ * target's 'r', 'w', 'x', 'a', 'k', and 'm' permissions.
@ -405,6 +389,9 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+
+ t_mode = aa_match(profile->file_rules, target, NULL);
+
+ l_x = l_mode & (ALL_AA_EXEC_TYPE | AA_EXEC_BITS);
+ t_x = t_mode & (ALL_AA_EXEC_TYPE | AA_EXEC_BITS);
+
+ /* For actual subset test ignore valid-profile-transition flags,
+ * and link bits
+ */
@ -414,12 +401,20 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ *request_mask = l_mode | link_mask;
+
+ if (l_mode) {
+ int x = l_x | (t_x & ALL_AA_EXEC_UNSAFE);
+ denied_mask |= l_mode & ~t_mode;
+ if ((l_mode & AA_EXEC_BITS) &&
+ (l_mode & ALL_AA_EXEC_TYPE) !=
+ (t_mode & ALL_AA_EXEC_TYPE))
+ denied_mask = (denied_mask & ~ALL_AA_EXEC_TYPE) |
+ (l_mode & (ALL_AA_EXEC_TYPE | AA_EXEC_BITS));
+ /* mask off x modes not used by link */
+
+ /* handle exec subset
+ * - link safe exec issubset of unsafe exec
+ * - no link x perm is subset of target having x perm
+ */
+ if ((l_mode & AA_USER_EXEC) &&
+ (x & AA_USER_EXEC_TYPE) != (t_x & AA_USER_EXEC_TYPE))
+ denied_mask = AA_USER_EXEC | (l_x & AA_USER_EXEC_TYPE);
+ if ((l_mode & AA_OTHER_EXEC) &&
+ (x & AA_OTHER_EXEC_TYPE) != (t_x & AA_OTHER_EXEC_TYPE))
+ denied_mask = AA_OTHER_EXEC | (l_x & AA_OTHER_EXEC_TYPE);
+ }
+
+ return denied_mask;
@ -484,6 +479,13 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ }
+}
+
+static char *new_compound_name(const char *n1, const char *n2)
+{
+ char *name = kmalloc(strlen(n1) + strlen(n2) + 3, GFP_KERNEL);
+ if (name)
+ sprintf(name, "%s//%s", n1, n2);
+ return name;
+}
+static inline void aa_put_name_buffer(char *buffer)
+{
+ kfree(buffer);
@ -840,16 +842,37 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+}
+
+static struct aa_profile *
+aa_register_find(struct aa_profile *profile, const char *name, int mandatory,
+ int complain, struct aa_audit *sa)
+aa_register_find(struct aa_profile *profile, const char* ns_name,
+ const char *name, int mandatory, int complain,
+ struct aa_audit *sa)
+{
+ struct aa_namespace *ns;
+ struct aa_profile *new_profile;
+ int ns_ref = 0;
+
+ if (profile)
+ ns = profile->ns;
+ else
+ ns = default_namespace;
+
+ if (ns_name) {
+ /* locate the profile namespace */
+ ns = aa_find_namespace(ns_name);
+ if (!ns) {
+ if (mandatory) {
+ sa->info = "profile namespace not found";
+ sa->denied_mask = sa->request_mask;
+ sa->error_code = -ENOENT;
+ return ERR_PTR(-ENOENT);
+ } else {
+ return NULL;
+ }
+ }
+ ns_ref++;
+ }
+
+ /* Locate new profile */
+ if (profile)
+ new_profile = aa_find_profile(profile->ns, name);
+ else
+ new_profile = aa_find_profile(default_namespace, name);
+ new_profile = aa_find_profile(ns, name);
+
+ if (new_profile) {
+ AA_DEBUG("%s: setting profile %s\n",
@ -863,16 +886,82 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ aa_dup_profile(profile->ns->null_complain_profile);
+ } else {
+ sa->error_code = -EACCES;
+ return ERR_PTR(aa_audit_file(profile, sa));
+ if (ns_ref)
+ aa_put_namespace(ns);
+ return ERR_PTR(-EACCES);
+ }
+ } else {
+ /* Only way we can get into this code is if task
+ * is unconfined, or pix.
+ * is unconfined, pix, nix.
+ */
+ AA_DEBUG("%s: No profile found for exec image '%s'\n",
+ __FUNCTION__,
+ name);
+ }
+ if (ns_ref)
+ aa_put_namespace(ns);
+ return new_profile;
+}
+
+static struct aa_profile *
+aa_x_to_profile(struct aa_profile *profile, const char *filename, int xmode,
+ struct aa_audit *sa, char **child)
+{
+ struct aa_profile *new_profile = NULL;
+ int ix = xmode & AA_EXEC_INHERIT;
+ int complain = PROFILE_COMPLAIN(profile);
+ int index;
+
+ *child = NULL;
+ switch (xmode & AA_EXEC_MODIFIERS) {
+ case 0:
+ /* only valid with ix flag */
+ ix = 1;
+ break;
+ case AA_EXEC_UNCONFINED:
+ /* only valid without ix flag */
+ ix = 0;
+ break;
+ case AA_EXEC_PROFILE:
+ new_profile = aa_register_find(profile, NULL, filename, !ix,
+ complain, sa);
+ break;
+ case AA_EXEC_CHILD:
+ *child = new_compound_name(profile->name, filename);
+ sa->name2 = *child;
+ if (!*child) {
+ sa->info = "Failed name resolution - exec failed";
+ sa->error_code = -ENOMEM;
+ new_profile = ERR_PTR(-ENOMEM);
+ } else {
+ new_profile = aa_register_find(profile, NULL, *child,
+ !ix, complain, sa);
+ }
+ break;
+ default:
+ /* all other indexes are named transitions */
+ index = AA_EXEC_INDEX(xmode);
+ if (index - 4 > profile->exec_table_size) {
+ sa->info = "invalid named transition - exec failed";
+ sa->error_code = -EACCES;
+ new_profile = ERR_PTR(-EACCES);
+ } else {
+ char *ns_name = NULL;
+ char *name = profile->exec_table[index - 4];
+ if (*name == ':') {
+ ns_name = name + 1;
+ name = ns_name + strlen(ns_name) + 1;
+ }
+ sa->name2 = name;
+ sa->name3 = ns_name;
+ new_profile =
+ aa_register_find(profile, ns_name, name,
+ !ix, complain, sa);
+ }
+ }
+ if (IS_ERR(new_profile))
+ /* all these failures must be audited - no quieting */
+ return ERR_PTR(aa_audit_reject(profile, sa));
+ return new_profile;
+}
+
@ -886,7 +975,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+int aa_register(struct linux_binprm *bprm)
+{
+ const char *filename;
+ char *buffer = NULL;
+ char *buffer = NULL, *child = NULL;
+ struct file *filp = bprm->file;
+ struct aa_profile *profile, *old_profile, *new_profile = NULL;
+ int exec_mode, complain = 0, shift;
@ -907,7 +996,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ if (profile) {
+ sa.info = "Failed name resolution - exec failed";
+ sa.error_code = PTR_ERR(filename);
+ aa_audit_reject(profile, &sa);
+ aa_audit_file(profile, &sa);
+ return sa.error_code;
+ } else
+ return 0;
@ -926,46 +1015,16 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ exec_mode = aa_match(profile->file_rules, filename,
+ &sa.audit_mask);
+
+
+ if (exec_mode & sa.request_mask) {
+ switch ((exec_mode >> shift) & AA_EXEC_MODIFIERS) {
+ case AA_EXEC_INHERIT:
+ AA_DEBUG("%s: INHERIT %s\n",
+ __FUNCTION__,
+ filename);
+ /* nothing to be done here */
+ int xm = exec_mode >> shift;
+ new_profile = aa_x_to_profile(profile, filename,
+ xm, &sa, &child);
+
+ if (!new_profile && (xm & AA_EXEC_INHERIT))
+ /* (p|c|n|)ix - don't change profile */
+ goto cleanup;
+
+ case AA_EXEC_UNCONFINED:
+ AA_DEBUG("%s: UNCONFINED %s\n",
+ __FUNCTION__,
+ filename);
+
+ /* detach current profile */
+ new_profile = NULL;
+ break;
+
+ case AA_EXEC_PROFILE:
+ AA_DEBUG("%s: PROFILE %s\n",
+ __FUNCTION__,
+ filename);
+ new_profile = aa_register_find(profile,
+ filename,
+ 1, complain,
+ &sa);
+ break;
+ case AA_EXEC_PIX:
+ AA_DEBUG("%s: PROFILE %s\n",
+ __FUNCTION__,
+ filename);
+ new_profile = aa_register_find(profile,
+ filename,
+ 0, complain,
+ &sa);
+ if (!new_profile)
+ /* inherit - nothing to be done here */
+ goto cleanup;
+ break;
+ }
+ /* error case caught below */
+
+ } else if (sa.request_mask & AUDIT_QUIET_MASK(sa.audit_mask)) {
+ /* quiet failed exit */
@ -985,7 +1044,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ }
+ } else {
+ /* Unconfined task, load profile if it exists */
+ new_profile = aa_register_find(NULL, filename, 0, 0, &sa);
+ new_profile = aa_register_find(NULL, NULL, filename, 0, 0, &sa);
+ if (new_profile == NULL)
+ goto cleanup;
+ }
@ -1039,6 +1098,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ }
+
+cleanup:
+ aa_put_name_buffer(child);
+ aa_put_name_buffer(buffer);
+ if (IS_ERR(new_profile))
+ return PTR_ERR(new_profile);
@ -1180,7 +1240,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+int aa_change_profile(const char *ns_name, const char *name)
+{
+ struct aa_task_context *cxt;
+ struct aa_profile *profile;
+ struct aa_profile *profile = NULL;
+ struct aa_namespace *ns = NULL;
+ struct aa_audit sa;
+ unsigned int state;
@ -1196,23 +1256,23 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+repeat:
+ task_lock(current);
+ cxt = aa_task_context(current);
+ if (!cxt) {
+ task_unlock(current);
+ return -EPERM;
+ }
+ profile = aa_dup_profile(cxt->profile);
+ if (cxt)
+ profile = aa_dup_profile(cxt->profile);
+ task_unlock(current);
+
+ if (ns_name)
+ ns = aa_find_namespace(ns_name);
+ else
+ else if (profile)
+ ns = aa_get_namespace(profile->ns);
+ else
+ ns = aa_get_namespace(default_namespace);
+
+ if (!ns) {
+ aa_put_profile(profile);
+ return -ENOENT;
+ }
+
+ if (PROFILE_COMPLAIN(profile) ||
+ if (!profile || PROFILE_COMPLAIN(profile) ||
+ (ns == profile->ns &&
+ (aa_match(profile->file_rules, name, NULL) & AA_CHANGE_PROFILE)))
+ error = do_change_profile(profile, ns, name, 0, 0, &sa);
@ -1287,16 +1347,14 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ else
+ profile_name = profile->name;
+
+ name = kmalloc(strlen(hat_name) + 3 + strlen(profile_name),
+ GFP_KERNEL);
+ name = new_compound_name(profile_name, hat_name);
+ if (!name) {
+ error = -ENOMEM;
+ goto out;
+ }
+ sprintf(name, "%s//%s", profile_name, hat_name);
+ error = do_change_profile(profile, profile->ns, name, cookie,
+ 0, &sa);
+ kfree(name);
+ aa_put_name_buffer(name);
+ } else if (previous_profile)
+ error = do_change_profile(profile, profile->ns,
+ previous_profile->name, cookie, 1,

View file

@ -13,13 +13,13 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
security/apparmor/Kconfig | 42 ++++
security/apparmor/Makefile | 13 +
security/apparmor/apparmor.h | 358 +++++++++++++++++++++++++++++++++++++++++
security/apparmor/apparmorfs.c | 280 ++++++++++++++++++++++++++++++++
security/apparmor/inline.h | 250 ++++++++++++++++++++++++++++
security/apparmor/apparmor.h | 367 +++++++++++++++++++++++++++++++++++++++++
security/apparmor/apparmorfs.c | 280 +++++++++++++++++++++++++++++++
security/apparmor/inline.h | 250 +++++++++++++++++++++++++++
security/apparmor/list.c | 156 +++++++++++++++++
security/apparmor/locking.txt | 68 +++++++
security/apparmor/procattr.c | 195 ++++++++++++++++++++++
8 files changed, 1362 insertions(+)
security/apparmor/procattr.c | 195 +++++++++++++++++++++
8 files changed, 1371 insertions(+)
--- /dev/null
+++ b/security/apparmor/Kconfig
@ -84,7 +84,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ $(call cmd,make-caps)
--- /dev/null
+++ b/security/apparmor/apparmor.h
@@ -0,0 +1,358 @@
@@ -0,0 +1,367 @@
+/*
+ * Copyright (C) 1998-2007 Novell/SUSE
+ *
@ -113,30 +113,31 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+#define AA_EXEC_MMAP 0x0040
+#define AA_MAY_MOUNT 0x0080 /* no direct audit mapping */
+#define AA_EXEC_UNSAFE 0x0100
+#define AA_EXEC_MOD_0 0x0200
+#define AA_EXEC_MOD_1 0x0400
+#define AA_EXEC_MOD_2 0x0800
+#define AA_EXEC_MOD_3 0x1000
+#define AA_EXEC_MOD_4 0x2000
+#define AA_EXEC_INHERIT 0x0200
+#define AA_EXEC_MOD_0 0x0400
+#define AA_EXEC_MOD_1 0x0800
+#define AA_EXEC_MOD_2 0x1000
+#define AA_EXEC_MOD_3 0x2000
+
+#define AA_BASE_PERMS (MAY_READ | MAY_WRITE | MAY_EXEC | \
+ MAY_APPEND | AA_MAY_LINK | \
+ AA_MAY_LOCK | AA_EXEC_MMAP | \
+ AA_MAY_MOUNT | AA_EXEC_UNSAFE | \
+ AA_EXEC_MOD_0 | AA_EXEC_MOD_1 | \
+ AA_EXEC_MOD_2 | AA_EXEC_MOD_3 | \
+ AA_EXEC_MOD_4)
+ AA_EXEC_INHERIT | AA_EXEC_MOD_0 | \
+ AA_EXEC_MOD_1 | AA_EXEC_MOD_2 | \
+ AA_EXEC_MOD_3)
+
+#define AA_EXEC_MODIFIERS (AA_EXEC_MOD_0 | AA_EXEC_MOD_1 | \
+ AA_EXEC_MOD_2 | AA_EXEC_MOD_3 | \
+ AA_EXEC_MOD_4)
+ AA_EXEC_MOD_2 | AA_EXEC_MOD_3)
+
+#define AA_EXEC_TYPE (AA_EXEC_UNSAFE | AA_EXEC_MODIFIERS)
+#define AA_EXEC_TYPE (AA_EXEC_UNSAFE | AA_EXEC_INHERIT | \
+ AA_EXEC_MODIFIERS)
+
+#define AA_EXEC_UNCONFINED AA_EXEC_MOD_0
+#define AA_EXEC_INHERIT AA_EXEC_MOD_1
+#define AA_EXEC_PROFILE (AA_EXEC_MOD_0 | AA_EXEC_MOD_1)
+#define AA_EXEC_PIX AA_EXEC_MOD_2
+#define AA_EXEC_PROFILE AA_EXEC_MOD_1
+#define AA_EXEC_CHILD (AA_EXEC_MOD_0 | AA_EXEC_MOD_1)
+/* remaining exec modes are index into profile name table */
+#define AA_EXEC_INDEX(mode) ((mode & AA_EXEC_MODIFIERS) >> 10)
+
+#define AA_USER_SHIFT 0
+#define AA_OTHER_SHIFT 14
@ -157,20 +158,26 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+
+#define AA_EXEC_BITS (AA_USER_EXEC | AA_OTHER_EXEC)
+
+#define ALL_AA_EXEC_UNSAFE ((AA_EXEC_UNSAFE << AA_USER_SHIFT) | \
+ (AA_EXEC_UNSAFE << AA_OTHER_SHIFT))
+
+#define ALL_AA_EXEC_TYPE (AA_USER_EXEC_TYPE | AA_OTHER_EXEC_TYPE)
+
+/* overloaded permissions for link pairs */
+#define AA_LINK_SUBSET_TEST 0x0020
+
+#define AA_USER_PTRACE 0x10000000
+#define AA_OTHER_PTRACE 0x20000000
+#define AA_PTRACE_PERMS (AA_USER_PTRACE | AA_OTHER_PTRACE)
+
+/* shared permissions that are not duplicated in user::other */
+#define AA_AUDIT_FIELD 0x10000000
+#define AA_CHANGE_HAT 0x20000000
+#define AA_CHANGE_PROFILE 0x40000000
+#define AA_CHANGE_HAT 0x40000000
+#define AA_CHANGE_PROFILE 0x80000000
+
+#define AA_SHARED_PERMS (AA_CHANGE_HAT | AA_CHANGE_PROFILE | \
+ AA_AUDIT_FIELD)
+#define AA_SHARED_PERMS (AA_CHANGE_HAT | AA_CHANGE_PROFILE)
+
+#define AA_VALID_PERM_MASK (AA_FILE_PERMS | AA_SHARED_PERMS)
+#define AA_VALID_PERM_MASK (AA_FILE_PERMS | AA_PTRACE_PERMS | \
+ AA_SHARED_PERMS)
+
+/* audit bits for the second accept field */
+#define AUDIT_FILE_MASK 0x1fc07f
@ -270,6 +277,8 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ struct list_head list;
+ struct aa_namespace *ns;
+
+ int exec_table_size;
+ char **exec_table;
+ struct aa_dfa *file_rules;
+ struct {
+ int complain;

View file

@ -8,10 +8,10 @@ Signed-off-by: John Johansen <jjohansen@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
security/apparmor/match.c | 364 +++++++++++++++
security/apparmor/match.c | 364 ++++++++++++++
security/apparmor/match.h | 87 +++
security/apparmor/module_interface.c | 815 +++++++++++++++++++++++++++++++++++
3 files changed, 1266 insertions(+)
security/apparmor/module_interface.c | 874 +++++++++++++++++++++++++++++++++++
3 files changed, 1325 insertions(+)
--- /dev/null
+++ b/security/apparmor/match.c
@ -472,7 +472,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+#endif /* __MATCH_H */
--- /dev/null
+++ b/security/apparmor/module_interface.c
@@ -0,0 +1,815 @@
@@ -0,0 +1,874 @@
+/*
+ * Copyright (C) 1998-2007 Novell/SUSE
+ *
@ -716,7 +716,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ *
+ * returns dfa or ERR_PTR
+ */
+struct aa_dfa *aa_unpack_dfa(struct aa_ext *e)
+static struct aa_dfa *aa_unpack_dfa(struct aa_ext *e)
+{
+ char *blob = NULL;
+ size_t size, error = 0;
@ -748,16 +748,53 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ return dfa;
+}
+
+static int aa_unpack_exec_table(struct aa_ext *e, struct aa_profile *profile)
+{
+ void *pos = e->pos;
+
+ /* exec table is optional */
+ if (aa_is_nameX(e, AA_STRUCT, "xtable")) {
+ int i, size;
+
+ size = aa_is_array(e, NULL);
+ /* currently 4 exec bits and entries 0-3 are reserved iupcx */
+ if (size > 16 - 4)
+ goto fail;
+ profile->exec_table = kzalloc(sizeof(char *) * size,
+ GFP_KERNEL);
+ if (!profile->exec_table)
+ goto fail;
+
+ for (i = 0; i < size; i++) {
+ char *tmp;
+ if (!aa_is_dynstring(e, &tmp, NULL))
+ goto fail;
+ /* note: strings beginning with a : have an embedded
+ \0 seperating the profile ns name from the profile
+ name */
+ profile->exec_table[i] = tmp;
+ }
+ if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
+ goto fail;
+ if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
+ goto fail;
+ }
+ return 1;
+
+fail:
+ e->pos = pos;
+ return 0;
+}
+
+/**
+ * aa_unpack_profile - unpack a serialized profile
+ * @e: serialized data extent information
+ * @operation: operation profile is being unpacked for
+ * @sa: audit struct for the operation
+ */
+static struct aa_profile *aa_unpack_profile(struct aa_ext *e,
+ const char *operation)
+ struct aa_audit *sa)
+{
+ struct aa_profile *profile = NULL;
+ struct aa_audit sa;
+
+ int error = -EPROTO;
+
@ -798,25 +835,21 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ error = PTR_ERR(profile->file_rules);
+ profile->file_rules = NULL;
+ goto fail;
+ if (!aa_is_u16(e, &profile->audit_network[i], NULL))
+ goto fail;
+ if (!aa_is_u16(e, &profile->quiet_network[i], NULL))
+ goto fail;
+ }
+
+ if (!aa_unpack_exec_table(e, profile))
+ goto fail;
+
+ if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
+ goto fail;
+
+ return profile;
+
+fail:
+ memset(&sa, 0, sizeof(sa));
+ sa.operation = operation;
+ sa.gfp_mask = GFP_KERNEL;
+ sa.name = profile && profile->name ? profile->name : "unknown";
+ if (!sa.info)
+ sa.info = "failed to unpack profile";
+ aa_audit_status(NULL, &sa);
+ sa->name = profile && profile->name ? profile->name : "unknown";
+ if (!sa->info)
+ sa->info = "failed to unpack profile";
+ aa_audit_status(NULL, sa);
+
+ if (profile)
+ free_aa_profile(profile);
@ -831,27 +864,19 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ *
+ * returns error or 0 if header is good
+ */
+static int aa_verify_header(struct aa_ext *e, const char *operation)
+static int aa_verify_header(struct aa_ext *e, struct aa_audit *sa)
+{
+ /* get the interface version */
+ if (!aa_is_u32(e, &e->version, "version")) {
+ struct aa_audit sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.operation = operation;
+ sa.gfp_mask = GFP_KERNEL;
+ sa.info = "invalid profile format";
+ aa_audit_status(NULL, &sa);
+ sa->info = "invalid profile format";
+ aa_audit_status(NULL, sa);
+ return -EPROTONOSUPPORT;
+ }
+
+ /* check that the interface version is currently supported */
+ if (e->version != 4) {
+ struct aa_audit sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.operation = operation;
+ sa.gfp_mask = GFP_KERNEL;
+ sa.info = "unsupported interface version";
+ aa_audit_status(NULL, &sa);
+ if (e->version != 5) {
+ sa->info = "unsupported interface version";
+ aa_audit_status(NULL, sa);
+ return -EPROTONOSUPPORT;
+ }
+
@ -878,11 +903,17 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ .pos = data,
+ .ns_name = NULL
+ };
+ ssize_t error = aa_verify_header(&e, "profile_load");
+ ssize_t error;
+ struct aa_audit sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.operation = "profile_load";
+ sa.gfp_mask = GFP_KERNEL;
+
+ error = aa_verify_header(&e, &sa);
+ if (error)
+ return error;
+
+ profile = aa_unpack_profile(&e, "profile_load");
+ profile = aa_unpack_profile(&e, &sa);
+ if (IS_ERR(profile))
+ return PTR_ERR(profile);
+
@ -914,6 +945,10 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ /* A profile with this name exists already. */
+ write_unlock(&ns->lock);
+ write_unlock(&profile_ns_list_lock);
+ sa.name = profile->name;
+ sa.name2 = ns->name;
+ sa.info = "failed: profile already loaded";
+ aa_audit_status(NULL, &sa);
+ mutex_unlock(&aa_interface_lock);
+ aa_put_profile(profile);
+ return -EEXIST;
@ -923,8 +958,11 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ list_add(&profile->list, &ns->profiles);
+ write_unlock(&ns->lock);
+ write_unlock(&profile_ns_list_lock);
+ mutex_unlock(&aa_interface_lock);
+
+ sa.name = profile->name;
+ sa.name2 = ns->name;
+ aa_audit_status(NULL, &sa);
+ mutex_unlock(&aa_interface_lock);
+ return size;
+}
+
@ -970,12 +1008,17 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ .pos = udata,
+ .ns_name = NULL
+ };
+ ssize_t error;
+ struct aa_audit sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.operation = "profile_replace";
+ sa.gfp_mask = GFP_KERNEL;
+
+ ssize_t error = aa_verify_header(&e, "profile_replace");
+ error = aa_verify_header(&e, &sa);
+ if (error)
+ return error;
+
+ new_profile = aa_unpack_profile(&e, "profile_replace");
+ new_profile = aa_unpack_profile(&e, &sa);
+ if (IS_ERR(new_profile))
+ return PTR_ERR(new_profile);
+
@ -1013,13 +1056,16 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ }
+ new_profile->ns = aa_get_namespace(ns);
+ ns->profile_count++;
+ /* not don't need an extra ref count to keep new_profile as
+ * it is protect by the interface mutex */
+ list_add(&new_profile->list, &ns->profiles);
+ write_unlock(&ns->lock);
+ write_unlock(&profile_ns_list_lock);
+
+ if (!old_profile)
+ if (!old_profile) {
+ sa.operation = "profile_load";
+ goto out;
+
+ }
+ /*
+ * Replacement needs to allocate a new aa_task_context for each
+ * task confined by old_profile. To do this the profile locks
@ -1048,6 +1094,9 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ aa_put_profile(old_profile);
+
+out:
+ sa.name = new_profile->name;
+ sa.name2 = ns->name;
+ aa_audit_status(NULL, &sa);
+ mutex_unlock(&aa_interface_lock);
+ return size;
+}
@ -1064,29 +1113,35 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+{
+ struct aa_namespace *ns;
+ struct aa_profile *profile;
+ struct aa_audit sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.operation = "profile_remove";
+ sa.gfp_mask = GFP_KERNEL;
+
+ mutex_lock(&aa_interface_lock);
+ write_lock(&profile_ns_list_lock);
+
+ if (name[0] == '/') {
+ ns = default_namespace;
+ } else {
+ char *split = strchr(name, ':');
+ if (name[0] == ':') {
+ char *split = strchr(name + 1, ':');
+ if (!split)
+ goto noent;
+ *split = 0;
+ ns = __aa_find_namespace(name, &profile_ns_list);
+ ns = __aa_find_namespace(name + 1, &profile_ns_list);
+ name = split + 1;
+ } else {
+ ns = default_namespace;
+ }
+
+ if (!ns)
+ goto noent;
+ sa.name2 = ns->name;
+ write_lock(&ns->lock);
+ profile = __aa_find_profile(name, &ns->profiles);
+ if (!profile) {
+ write_unlock(&ns->lock);
+ goto noent;
+ }
+ sa.name = profile->name;
+
+ /* Remove the profile from each task context it is on. */
+ lock_profile(profile);
@ -1103,6 +1158,8 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+ aa_put_namespace(ns);
+ }
+ write_unlock(&profile_ns_list_lock);
+
+ aa_audit_status(NULL, &sa);
+ mutex_unlock(&aa_interface_lock);
+ aa_put_profile(profile);
+
@ -1110,6 +1167,8 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+
+noent:
+ write_unlock(&profile_ns_list_lock);
+ sa.info = "failed: profile does not exist";
+ aa_audit_status(NULL, &sa);
+ mutex_unlock(&aa_interface_lock);
+ return -ENOENT;
+}

View file

@ -2,9 +2,9 @@
security/apparmor/Makefile | 7 +
security/apparmor/apparmor.h | 9 ++
security/apparmor/lsm.c | 129 ++++++++++++++++++++++++++++++++++-
security/apparmor/main.c | 106 ++++++++++++++++++++++++++++
security/apparmor/module_interface.c | 20 +++++
5 files changed, 267 insertions(+), 4 deletions(-)
security/apparmor/main.c | 107 ++++++++++++++++++++++++++++-
security/apparmor/module_interface.c | 26 ++++++-
5 files changed, 271 insertions(+), 7 deletions(-)
--- a/security/apparmor/Makefile
+++ b/security/apparmor/Makefile
@ -32,7 +32,7 @@
/*
* We use MAY_READ, MAY_WRITE, MAY_EXEC, MAY_APPEND and the following flags
@@ -199,6 +201,9 @@ struct aa_profile {
@@ -208,6 +210,9 @@ struct aa_profile {
struct list_head task_contexts;
spinlock_t lock;
unsigned long int_flags;
@ -42,7 +42,7 @@
};
extern struct list_head profile_ns_list;
@@ -245,6 +250,7 @@ struct aa_audit {
@@ -254,6 +259,7 @@ struct aa_audit {
int request_mask, denied_mask, audit_mask;
struct iattr *iattr;
pid_t task, parent;
@ -50,7 +50,7 @@
int error_code;
};
@@ -306,6 +312,9 @@ extern void aa_change_task_context(struc
@@ -315,6 +321,9 @@ extern void aa_change_task_context(struc
struct aa_profile *previous_profile);
extern int aa_may_ptrace(struct aa_task_context *cxt,
struct aa_profile *tracee);
@ -70,7 +70,7 @@
#include "apparmor.h"
#include "inline.h"
@@ -653,6 +654,117 @@ static void apparmor_task_free_security(
@@ -663,6 +664,117 @@ static void apparmor_task_free_security(
aa_release(task);
}
@ -188,7 +188,7 @@
static int apparmor_getprocattr(struct task_struct *task, char *name,
char **value)
{
@@ -753,9 +865,6 @@ struct security_operations apparmor_ops
@@ -763,9 +875,6 @@ struct security_operations apparmor_ops
.capable = apparmor_capable,
.syslog = cap_syslog,
@ -198,7 +198,7 @@
.bprm_apply_creds = cap_bprm_apply_creds,
.bprm_set_security = apparmor_bprm_set_security,
.bprm_secureexec = apparmor_bprm_secureexec,
@@ -791,6 +900,20 @@ struct security_operations apparmor_ops
@@ -801,6 +910,20 @@ struct security_operations apparmor_ops
.getprocattr = apparmor_getprocattr,
.setprocattr = apparmor_setprocattr,
@ -231,7 +231,7 @@
#include "apparmor.h"
@@ -133,6 +136,24 @@ static void aa_audit_file_mask(struct au
@@ -116,6 +119,24 @@ static void aa_audit_file_mask(struct au
audit_log_format(ab, " %s=\"%s::%s\"", name, user, other);
}
@ -256,10 +256,11 @@
/**
* aa_audit - Log an audit event to the audit subsystem
* @profile: profile to check against
@@ -204,6 +225,25 @@ static int aa_audit_base(struct aa_profi
@@ -187,7 +208,25 @@ static int aa_audit_base(struct aa_profi
audit_log_untrustedstring(ab, sa->name2);
}
- audit_log_format(ab, " pid=%d", current->pid);
+ if (sa->family || sa->type) {
+ if (address_families[sa->family])
+ audit_log_format(ab, " family=\"%s\"",
@ -279,10 +280,10 @@
+ }
+
+ audit_log_format(ab, " pid=%d", current->pid);
audit_log_format(ab, " pid=%d", current->pid);
if (profile) {
@@ -766,6 +806,72 @@ int aa_link(struct aa_profile *profile,
audit_log_format(ab, " profile=");
@@ -768,6 +807,72 @@ int aa_link(struct aa_profile *profile,
return error;
}
@ -357,16 +358,18 @@
*******************************/
--- a/security/apparmor/module_interface.c
+++ b/security/apparmor/module_interface.c
@@ -283,6 +283,8 @@ static struct aa_profile *aa_unpack_prof
@@ -320,8 +320,8 @@ static struct aa_profile *aa_unpack_prof
struct aa_audit *sa)
{
struct aa_profile *profile = NULL;
struct aa_audit sa;
-
- int error = -EPROTO;
+ size_t size = 0;
+ int i;
+ int i, error = -EPROTO;
int error = -EPROTO;
@@ -317,6 +319,24 @@ static struct aa_profile *aa_unpack_prof
profile = alloc_aa_profile();
if (!profile)
@@ -354,6 +354,28 @@ static struct aa_profile *aa_unpack_prof
if (!aa_is_u32(e, &(profile->set_caps), NULL))
goto fail;
@ -378,6 +381,10 @@
+ for (i = 0; i < size; i++) {
+ if (!aa_is_u16(e, &profile->network_families[i], NULL))
+ goto fail;
+ if (!aa_is_u16(e, &profile->audit_network[i], NULL))
+ goto fail;
+ if (!aa_is_u16(e, &profile->quiet_network[i], NULL))
+ goto fail;
+ }
+ if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
+ goto fail;

View file

@ -1,3 +1,23 @@
From: John Johansen <jjohansen@suse.de>
Subject: AppArmor: per profile controls for system rlimits
Provide contol of rlimits on a per profile basis. Each profile provides
a per limit contol and corresponding hard limit value, such that when a
profile becomes attached to a task it sets the tasks limits to be <= to
the profiles specified limits. Note: the profile limit value will not
raise a tasks limit if it is already less than the profile mandates.
In addition to setting a tasks limits, the ability to set limits on
a confined task are controlled. AppArmor only controls the raising
of a tasks limits Tasks with CAP_SYS_RESOURCE can have their hard limits
raised up to the value specified by the profile. AppArmor does not
prevent a task for lowering its hard limits, nor does it provide
additional control on soft limits.
AppArmor only controls the limits specified in a profile so that
any limit not specified is free to be modified subject to standard
linux limitations.
---
security/apparmor/apparmor.h | 23 ++++++
security/apparmor/apparmorfs.c | 2
@ -16,7 +36,7 @@
#include <linux/socket.h>
#include <net/sock.h>
@@ -129,6 +130,18 @@ extern unsigned int apparmor_path_max;
@@ -136,6 +137,18 @@ extern unsigned int apparmor_path_max;
#define AA_ERROR(fmt, args...) printk(KERN_ERR "AppArmor: " fmt, ##args)
@ -35,7 +55,7 @@
struct aa_profile;
/* struct aa_namespace - namespace for a set of profiles
@@ -163,6 +176,8 @@ struct aa_namespace {
@@ -170,6 +183,8 @@ struct aa_namespace {
* @audit_caps: caps that are to be audited
* @quiet_caps: caps that should not be audited
* @capabilities: capabilities granted by the process
@ -44,7 +64,7 @@
* @count: reference count of the profile
* @task_contexts: list of tasks confined by profile
* @lock: lock for the task_contexts list
@@ -197,6 +212,9 @@ struct aa_profile {
@@ -206,6 +221,9 @@ struct aa_profile {
kernel_cap_t audit_caps;
kernel_cap_t quiet_caps;
@ -54,7 +74,7 @@
struct kref count;
struct list_head task_contexts;
spinlock_t lock;
@@ -248,6 +266,7 @@ struct aa_audit {
@@ -257,6 +275,7 @@ struct aa_audit {
const char *name2;
const char *name3;
int request_mask, denied_mask, audit_mask;
@ -62,7 +82,7 @@
struct iattr *iattr;
pid_t task, parent;
int family, type, protocol;
@@ -315,6 +334,10 @@ extern int aa_may_ptrace(struct aa_task_
@@ -324,6 +343,10 @@ extern int aa_may_ptrace(struct aa_task_
extern int aa_net_perm(struct aa_profile *profile, char *operation,
int family, int type, int protocol);
extern int aa_revalidate_sk(struct sock *sk, char *operation);
@ -86,7 +106,7 @@
strlen(features));
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -856,6 +856,21 @@ static int apparmor_setprocattr(struct t
@@ -866,6 +866,21 @@ static int apparmor_setprocattr(struct t
return error;
}
@ -108,7 +128,7 @@
struct security_operations apparmor_ops = {
.ptrace = apparmor_ptrace,
.capget = cap_capget,
@@ -897,6 +912,7 @@ struct security_operations apparmor_ops
@@ -907,6 +922,7 @@ struct security_operations apparmor_ops
.task_free_security = apparmor_task_free_security,
.task_post_setuid = cap_task_post_setuid,
.task_reparent_to_init = cap_task_reparent_to_init,
@ -118,7 +138,7 @@
.setprocattr = apparmor_setprocattr,
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -176,6 +176,9 @@ static int aa_audit_base(struct aa_profi
@@ -177,6 +177,9 @@ static int aa_audit_base(struct aa_profi
if (sa->request_mask)
audit_log_format(ab, " fsuid=%d", current->fsuid);
@ -128,7 +148,7 @@
if (sa->iattr) {
struct iattr *iattr = sa->iattr;
@@ -871,6 +874,79 @@ int aa_revalidate_sk(struct sock *sk, ch
@@ -872,6 +875,79 @@ int aa_revalidate_sk(struct sock *sk, ch
return error;
}
@ -208,7 +228,7 @@
/*******************************
* Global task related functions
@@ -884,6 +960,7 @@ int aa_revalidate_sk(struct sock *sk, ch
@@ -885,6 +961,7 @@ int aa_revalidate_sk(struct sock *sk, ch
*/
int aa_clone(struct task_struct *child)
{
@ -216,7 +236,7 @@
struct aa_task_context *cxt, *child_cxt;
struct aa_profile *profile;
@@ -893,6 +970,11 @@ int aa_clone(struct task_struct *child)
@@ -894,6 +971,11 @@ int aa_clone(struct task_struct *child)
if (!child_cxt)
return -ENOMEM;
@ -228,7 +248,7 @@
repeat:
profile = aa_get_profile(current);
if (profile) {
@@ -909,18 +991,22 @@ repeat:
@@ -910,18 +992,22 @@ repeat:
goto repeat;
}
@ -256,7 +276,7 @@
aa_audit_hint(profile, &sa);
}
aa_put_profile(profile);
@@ -1098,6 +1184,10 @@ repeat:
@@ -1156,6 +1242,10 @@ repeat:
sa.task = current->parent->pid;
aa_audit_reject(profile, &sa);
}
@ -267,7 +287,7 @@
new_profile = old_profile;
goto cleanup;
}
@@ -1237,6 +1327,12 @@ static int do_change_profile(struct aa_p
@@ -1296,6 +1386,12 @@ static int do_change_profile(struct aa_p
goto out;
}
@ -280,7 +300,7 @@
if (new_profile == ns->null_complain_profile)
aa_audit_hint(cxt->profile, sa);
@@ -1425,17 +1521,18 @@ struct aa_profile *__aa_replace_profile(
@@ -1482,17 +1578,18 @@ struct aa_profile *__aa_replace_profile(
cxt = lock_task_and_profiles(task, profile);
if (unlikely(profile && profile->isstale)) {
@ -307,7 +327,7 @@
}
if (cxt)
@@ -1443,8 +1540,15 @@ struct aa_profile *__aa_replace_profile(
@@ -1500,8 +1597,15 @@ struct aa_profile *__aa_replace_profile(
aa_change_task_context(task, new_cxt, profile, 0, NULL);
task_unlock(task);
@ -323,7 +343,7 @@
}
/**
@@ -1509,6 +1613,7 @@ void aa_change_task_context(struct task_
@@ -1566,6 +1670,7 @@ void aa_change_task_context(struct task_
if (old_cxt) {
list_del_init(&old_cxt->list);
@ -331,7 +351,7 @@
call_rcu(&old_cxt->rcu, free_aa_task_context_rcu_callback);
}
if (new_cxt) {
@@ -1520,6 +1625,7 @@ void aa_change_task_context(struct task_
@@ -1577,6 +1682,7 @@ void aa_change_task_context(struct task_
new_cxt->cookie = cookie;
new_cxt->task = task;
new_cxt->profile = aa_dup_profile(profile);
@ -364,8 +384,8 @@
static size_t aa_is_array(struct aa_ext *e, const char *name)
{
void *pos = e->pos;
@@ -273,6 +289,39 @@ struct aa_dfa *aa_unpack_dfa(struct aa_e
return dfa;
@@ -311,6 +327,39 @@ fail:
return 0;
}
+int aa_unpack_rlimits(struct aa_ext *e, struct aa_profile *profile)
@ -404,7 +424,7 @@
/**
* aa_unpack_profile - unpack a serialized profile
* @e: serialized data extent information
@@ -319,6 +368,9 @@ static struct aa_profile *aa_unpack_prof
@@ -354,6 +403,9 @@ static struct aa_profile *aa_unpack_prof
if (!aa_is_u32(e, &(profile->set_caps), NULL))
goto fail;
@ -414,16 +434,16 @@
size = aa_is_array(e, "net_allowed_af");
if (size) {
if (size > AF_MAX)
@@ -565,6 +617,8 @@ ssize_t aa_replace_profile(void *udata,
if (!old_profile)
@@ -613,6 +665,8 @@ ssize_t aa_replace_profile(void *udata,
sa.operation = "profile_load";
goto out;
}
+ /* do not fail replacement based off of profile's NPROC rlimit */
+
/*
* Replacement needs to allocate a new aa_task_context for each
* task confined by old_profile. To do this the profile locks
@@ -585,6 +639,7 @@ ssize_t aa_replace_profile(void *udata,
@@ -633,6 +687,7 @@ ssize_t aa_replace_profile(void *udata,
task_lock(task);
task_replace(task, new_cxt, new_profile);
task_unlock(task);
@ -431,7 +451,7 @@
new_cxt = NULL;
}
unlock_both_profiles(old_profile, new_profile);
@@ -604,6 +659,7 @@ out:
@@ -655,6 +710,7 @@ out:
*
* remove a profile from the profile list and all aa_task_context references
* to said profile.

View file

@ -4,7 +4,7 @@
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -176,8 +176,10 @@ static int aa_audit_base(struct aa_profi
@@ -159,8 +159,10 @@ static int aa_audit_base(struct aa_profi
return type == AUDIT_APPARMOR_ALLOWED ? 0 : -ENOMEM;
}

View file

@ -110,6 +110,7 @@ apparmor-intree.diff
#FS2.2.2_fix-unionfs-with-AppArmor.patch
#FS2.1.3_fix-unionfs-with-AppArmor.patch
#named-transitions.diff
apparmor-network.diff
#fix-net.diff
apparmor-rlimits.diff