]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
apparmor: refactor updating profiles to the newest parent
authorJohn Johansen <john.johansen@canonical.com>
Fri, 9 Jun 2017 14:16:46 +0000 (07:16 -0700)
committerJohn Johansen <john.johansen@canonical.com>
Sun, 11 Jun 2017 00:11:35 +0000 (17:11 -0700)
Signed-off-by: John Johansen <john.johansen@canonical.com>
security/apparmor/policy.c

index af925c07ad4e6b134bea13a155dea7da599065cd..20613186b1d87ebe100ca502a0ecebefd8c4d8c4 100644 (file)
@@ -837,6 +837,27 @@ static void share_name(struct aa_profile *old, struct aa_profile *new)
        new->base.name = old->base.name;
 }
 
+/* Update to newest version of parent after previous replacements
+ * Returns: unrefcount newest version of parent
+ */
+static struct aa_profile *update_to_newest_parent(struct aa_profile *new)
+{
+       struct aa_profile *parent, *newest;
+
+       parent = rcu_dereference_protected(new->parent,
+                                          mutex_is_locked(&new->ns->lock));
+       newest = aa_get_newest_profile(parent);
+
+       /* parent replaced in this atomic set? */
+       if (newest != parent) {
+               aa_put_profile(parent);
+               rcu_assign_pointer(new->parent, newest);
+       } else
+               aa_put_profile(newest);
+
+       return newest;
+}
+
 /**
  * aa_replace_profiles - replace profile(s) on the profile list
  * @policy_ns: namespace load is occurring on
@@ -1052,10 +1073,16 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_profile *profile,
                        __list_add_profile(&newest->base.profiles, ent->new);
                        aa_put_profile(newest);
                } else {
-                       /* aafs interface uses proxy */
-                       rcu_assign_pointer(ent->new->proxy->profile,
-                                          aa_get_profile(ent->new));
-                       __list_add_profile(&ns->base.profiles, ent->new);
+                       struct list_head *lh;
+
+                       if (rcu_access_pointer(ent->new->parent)) {
+                               struct aa_profile *parent;
+
+                               parent = update_to_newest_parent(ent->new);
+                               lh = &parent->base.profiles;
+                       } else
+                               lh = &ns->base.profiles;
+                       __list_add_profile(lh, ent->new);
                }
        skip:
                aa_load_ent_free(ent);