apparmor: share profile name on replacement
authorJohn Johansen <john.johansen@canonical.com>
Fri, 9 Jun 2017 14:09:05 +0000 (07:09 -0700)
committerJohn Johansen <john.johansen@canonical.com>
Sun, 11 Jun 2017 00:11:35 +0000 (17:11 -0700)
The profile names are the same, leverage this.

Signed-off-by: John Johansen <john.johansen@canonical.com>
security/apparmor/include/lib.h
security/apparmor/lib.c
security/apparmor/policy.c

index 89524aade6575e1405090148772b6c80ccb0e13c..593877d38088be71a122e95e27dec00fb422cbc1 100644 (file)
@@ -100,6 +100,36 @@ static inline bool path_mediated_fs(struct dentry *dentry)
        return !(dentry->d_sb->s_flags & MS_NOUSER);
 }
 
+
+struct counted_str {
+       struct kref count;
+       char name[];
+};
+
+#define str_to_counted(str) \
+       ((struct counted_str *)(str - offsetof(struct counted_str, name)))
+
+#define __counted      /* atm just a notation */
+
+void aa_str_kref(struct kref *kref);
+char *aa_str_alloc(int size, gfp_t gfp);
+
+
+static inline __counted char *aa_get_str(__counted char *str)
+{
+       if (str)
+               kref_get(&(str_to_counted(str)->count));
+
+       return str;
+}
+
+static inline void aa_put_str(__counted char *str)
+{
+       if (str)
+               kref_put(&str_to_counted(str)->count, aa_str_kref);
+}
+
+
 /* struct aa_policy - common part of both namespaces and profiles
  * @name: name of the object
  * @hname - The hierarchical name
@@ -108,7 +138,7 @@ static inline bool path_mediated_fs(struct dentry *dentry)
  */
 struct aa_policy {
        const char *name;
-       const char *hname;
+       __counted char *hname;
        struct list_head list;
        struct list_head profiles;
 };
index 3e9146e68c4a862a31317862fc82146cce696e50..0ceecdbb4658b35ea476bf84620fc1505ac23ec6 100644 (file)
@@ -134,6 +134,24 @@ void aa_info_message(const char *str)
        printk(KERN_INFO "AppArmor: %s\n", str);
 }
 
+__counted char *aa_str_alloc(int size, gfp_t gfp)
+{
+       struct counted_str *str;
+
+       str = kmalloc(sizeof(struct counted_str) + size, gfp);
+       if (!str)
+               return NULL;
+
+       kref_init(&str->count);
+       return str->name;
+}
+
+void aa_str_kref(struct kref *kref)
+{
+       kfree(container_of(kref, struct counted_str, count));
+}
+
+
 const char aa_file_perm_chrs[] = "xwracd         km l     ";
 const char *aa_file_perm_names[] = {
        "exec",
@@ -296,6 +314,7 @@ void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
  * @policy: policy to initialize  (NOT NULL)
  * @prefix: prefix name if any is required.  (MAYBE NULL)
  * @name: name of the policy, init will make a copy of it  (NOT NULL)
+ * @gfp: allocation mode
  *
  * Note: this fn creates a copy of strings passed in
  *
@@ -304,16 +323,21 @@ void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
 bool aa_policy_init(struct aa_policy *policy, const char *prefix,
                    const char *name, gfp_t gfp)
 {
+       char *hname;
+
        /* freed by policy_free */
        if (prefix) {
-               policy->hname = kmalloc(strlen(prefix) + strlen(name) + 3,
-                                       gfp);
-               if (policy->hname)
-                       sprintf((char *)policy->hname, "%s//%s", prefix, name);
-       } else
-               policy->hname = kstrdup(name, gfp);
-       if (!policy->hname)
+               hname = aa_str_alloc(strlen(prefix) + strlen(name) + 3, gfp);
+               if (hname)
+                       sprintf(hname, "%s//%s", prefix, name);
+       } else {
+               hname = aa_str_alloc(strlen(name) + 1, gfp);
+               if (hname)
+                       strcpy(hname, name);
+       }
+       if (!hname)
                return false;
+       policy->hname = hname;
        /* base.name is a substring of fqname */
        policy->name = basename(policy->hname);
        INIT_LIST_HEAD(&policy->list);
@@ -332,5 +356,5 @@ void aa_policy_destroy(struct aa_policy *policy)
        AA_BUG(on_list_rcu(&policy->list));
 
        /* don't free name as its a subset of hname */
-       kzfree(policy->hname);
+       aa_put_str(policy->hname);
 }
index 29e04638790f267f3c65586b8f63d7b4ba4dcd70..af925c07ad4e6b134bea13a155dea7da599065cd 100644 (file)
@@ -829,6 +829,14 @@ static int __lookup_replace(struct aa_ns *ns, const char *hname,
        return 0;
 }
 
+static void share_name(struct aa_profile *old, struct aa_profile *new)
+{
+       aa_put_str(new->base.hname);
+       aa_get_str(old->base.hname);
+       new->base.hname = old->base.hname;
+       new->base.name = old->base.name;
+}
+
 /**
  * aa_replace_profiles - replace profile(s) on the profile list
  * @policy_ns: namespace load is occurring on
@@ -1013,6 +1021,7 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_profile *profile,
                             NULL, error);
 
                if (ent->old) {
+                       share_name(ent->old, ent->new);
                        __replace_profile(ent->old, ent->new, 1);
                        if (ent->rename) {
                                /* aafs interface uses proxy */