Commit a1bd627b authored by John Johansen's avatar John Johansen

apparmor: share profile name on replacement

The profile names are the same, leverage this.
Signed-off-by: default avatarJohn Johansen <john.johansen@canonical.com>
parent cf797c0e
...@@ -100,6 +100,36 @@ static inline bool path_mediated_fs(struct dentry *dentry) ...@@ -100,6 +100,36 @@ static inline bool path_mediated_fs(struct dentry *dentry)
return !(dentry->d_sb->s_flags & MS_NOUSER); 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 /* struct aa_policy - common part of both namespaces and profiles
* @name: name of the object * @name: name of the object
* @hname - The hierarchical name * @hname - The hierarchical name
...@@ -108,7 +138,7 @@ static inline bool path_mediated_fs(struct dentry *dentry) ...@@ -108,7 +138,7 @@ static inline bool path_mediated_fs(struct dentry *dentry)
*/ */
struct aa_policy { struct aa_policy {
const char *name; const char *name;
const char *hname; __counted char *hname;
struct list_head list; struct list_head list;
struct list_head profiles; struct list_head profiles;
}; };
......
...@@ -134,6 +134,24 @@ void aa_info_message(const char *str) ...@@ -134,6 +134,24 @@ void aa_info_message(const char *str)
printk(KERN_INFO "AppArmor: %s\n", 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_chrs[] = "xwracd km l ";
const char *aa_file_perm_names[] = { const char *aa_file_perm_names[] = {
"exec", "exec",
...@@ -296,6 +314,7 @@ void aa_compute_perms(struct aa_dfa *dfa, unsigned int state, ...@@ -296,6 +314,7 @@ void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
* @policy: policy to initialize (NOT NULL) * @policy: policy to initialize (NOT NULL)
* @prefix: prefix name if any is required. (MAYBE NULL) * @prefix: prefix name if any is required. (MAYBE NULL)
* @name: name of the policy, init will make a copy of it (NOT 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 * 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, ...@@ -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, bool aa_policy_init(struct aa_policy *policy, const char *prefix,
const char *name, gfp_t gfp) const char *name, gfp_t gfp)
{ {
char *hname;
/* freed by policy_free */ /* freed by policy_free */
if (prefix) { if (prefix) {
policy->hname = kmalloc(strlen(prefix) + strlen(name) + 3, hname = aa_str_alloc(strlen(prefix) + strlen(name) + 3, gfp);
gfp); if (hname)
if (policy->hname) sprintf(hname, "%s//%s", prefix, name);
sprintf((char *)policy->hname, "%s//%s", prefix, name); } else {
} else hname = aa_str_alloc(strlen(name) + 1, gfp);
policy->hname = kstrdup(name, gfp); if (hname)
if (!policy->hname) strcpy(hname, name);
}
if (!hname)
return false; return false;
policy->hname = hname;
/* base.name is a substring of fqname */ /* base.name is a substring of fqname */
policy->name = basename(policy->hname); policy->name = basename(policy->hname);
INIT_LIST_HEAD(&policy->list); INIT_LIST_HEAD(&policy->list);
...@@ -332,5 +356,5 @@ void aa_policy_destroy(struct aa_policy *policy) ...@@ -332,5 +356,5 @@ void aa_policy_destroy(struct aa_policy *policy)
AA_BUG(on_list_rcu(&policy->list)); AA_BUG(on_list_rcu(&policy->list));
/* don't free name as its a subset of hname */ /* don't free name as its a subset of hname */
kzfree(policy->hname); aa_put_str(policy->hname);
} }
...@@ -829,6 +829,14 @@ static int __lookup_replace(struct aa_ns *ns, const char *hname, ...@@ -829,6 +829,14 @@ static int __lookup_replace(struct aa_ns *ns, const char *hname,
return 0; 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 * aa_replace_profiles - replace profile(s) on the profile list
* @policy_ns: namespace load is occurring on * @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, ...@@ -1013,6 +1021,7 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_profile *profile,
NULL, error); NULL, error);
if (ent->old) { if (ent->old) {
share_name(ent->old, ent->new);
__replace_profile(ent->old, ent->new, 1); __replace_profile(ent->old, ent->new, 1);
if (ent->rename) { if (ent->rename) {
/* aafs interface uses proxy */ /* aafs interface uses proxy */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment