For profiles that have been replaced reuse the name string so the
old and new version of the profile share the same string.  This will
make some checks/comparisons in labeling quicker.

Signed-off-by: John Johansen <[email protected]>
---
 security/apparmor/include/policy.h |    1 +
 security/apparmor/policy.c         |   18 +++++++++++++++---
 2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/security/apparmor/include/policy.h 
b/security/apparmor/include/policy.h
index 4bebbbd..3852cd1 100644
--- a/security/apparmor/include/policy.h
+++ b/security/apparmor/include/policy.h
@@ -65,6 +65,7 @@ enum profile_flags {
        PFLAG_IMMUTABLE = 0x10,         /* don't allow changes/replacement */
        PFLAG_USER_DEFINED = 0x20,      /* user based profile - lower privs */
        PFLAG_NO_LIST_REF = 0x40,       /* list doesn't keep profile ref */
+       PFLAG_OWNS_NAME = 0x80,         /* profile owns name */
        PFLAG_OLD_NULL_TRANS = 0x100,   /* use // as the null transition */
        PFLAG_INVALID = 0x200,          /* profile replaced/removed */
        PFLAG_NS_COUNT = 0x400,         /* carries NS ref count */
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index 720b952..fab98ff 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -641,7 +641,8 @@ void aa_free_profile(struct aa_profile *profile)
        }
 
        /* free children profiles */
-       policy_destroy(&profile->base);
+       if (PFLAG_OWNS_NAME & profile->flags)
+               policy_destroy(&profile->base);
        aa_put_profile(profile->parent);
 
        aa_put_namespace(profile->ns);
@@ -706,6 +707,8 @@ struct aa_profile *aa_alloc_profile(const char *hname)
                goto fail;
        kref_init(&profile->count);
 
+       profile->flags = PFLAG_OWNS_NAME;
+
        /* refcount released by caller */
        return profile;
 
@@ -748,7 +751,7 @@ struct aa_profile *aa_new_null_profile(struct aa_profile 
*parent, int hat)
                goto fail;
 
        profile->mode = APPARMOR_COMPLAIN;
-       profile->flags = PFLAG_NULL;
+       profile->flags |= PFLAG_NULL;
        if (hat)
                profile->flags |= PFLAG_HAT;
 
@@ -779,7 +782,7 @@ struct aa_profile *aa_setup_default_profile(void)
                return NULL;
 
        /* the default profile pretends to be unconfined until it is replaced */
-       profile->flags = PFLAG_IX_ON_NAME_ERROR;
+       profile->flags |= PFLAG_IX_ON_NAME_ERROR;
        profile->mode = APPARMOR_UNCONFINED;
 
        profile->ns = aa_get_namespace(root_ns);
@@ -1067,6 +1070,14 @@ static struct aa_policy *__lookup_replace(struct 
aa_namespace *ns,
        return policy;
 }
 
+static void share_name(struct aa_profile *old, struct aa_profile *new)
+{
+       kzfree(new->base.hname);
+       old->flags &= ~PFLAG_OWNS_NAME;
+       new->base.hname = old->base.hname;
+       new->base.name = old->base.name;
+}
+
 /**
  * aa_replace_profiles - replace profile(s) on the profile list
  * @udata: serialized data stream  (NOT NULL)
@@ -1179,6 +1190,7 @@ ssize_t aa_replace_profiles(void *udata, size_t size, 
bool noreplace)
                audit_policy(op, GFP_ATOMIC, new->base.name, NULL, error);
 
                if (old) {
+                       share_name(old, new);
                        __replace_profile(old, new);
                        if (rename) {
                                /* TODO:
-- 
1.7.10.4


-- 
AppArmor mailing list
[email protected]
Modify settings or unsubscribe at: 
https://lists.ubuntu.com/mailman/listinfo/apparmor

Reply via email to