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
*/
struct aa_policy {
const char *name;
- const char *hname;
+ __counted char *hname;
struct list_head list;
struct list_head profiles;
};
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",
* @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
*
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);
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);
}
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
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 */