From 73688d1ed0b8f800f312f7bc9d583463858da861 Mon Sep 17 00:00:00 2001 From: John Johansen Date: Mon, 16 Jan 2017 00:42:34 -0800 Subject: apparmor: refactor prepare_ns() and make usable from different views prepare_ns() will need to be called from alternate views, and namespaces will need to be created via different interfaces. So refactor and allow specifying the view ns. Signed-off-by: John Johansen --- security/apparmor/policy_ns.c | 98 +++++++++++++++++++++++++++++-------------- 1 file changed, 66 insertions(+), 32 deletions(-) (limited to 'security/apparmor/policy_ns.c') diff --git a/security/apparmor/policy_ns.c b/security/apparmor/policy_ns.c index 8a5632f39751..f6cdc738ffcd 100644 --- a/security/apparmor/policy_ns.c +++ b/security/apparmor/policy_ns.c @@ -181,48 +181,82 @@ struct aa_ns *aa_find_ns(struct aa_ns *root, const char *name) return aa_findn_ns(root, name, strlen(name)); } +static struct aa_ns *__aa_create_ns(struct aa_ns *parent, const char *name, + struct dentry *dir) +{ + struct aa_ns *ns; + int error; + + AA_BUG(!parent); + AA_BUG(!name); + AA_BUG(!mutex_is_locked(&parent->lock)); + + ns = alloc_ns(parent->base.hname, name); + if (!ns) + return NULL; + mutex_lock(&ns->lock); + error = __aa_fs_ns_mkdir(ns, ns_subns_dir(parent), name); + if (error) { + AA_ERROR("Failed to create interface for ns %s\n", + ns->base.name); + mutex_unlock(&ns->lock); + aa_free_ns(ns); + return ERR_PTR(error); + } + ns->parent = aa_get_ns(parent); + list_add_rcu(&ns->base.list, &parent->sub_ns); + /* add list ref */ + aa_get_ns(ns); + mutex_unlock(&ns->lock); + + return ns; +} + /** - * aa_prepare_ns - find an existing or create a new namespace of @name - * @name: the namespace to find or add (MAYBE NULL) + * aa_create_ns - create an ns, fail if it already exists + * @parent: the parent of the namespace being created + * @name: the name of the namespace + * @dir: if not null the dir to put the ns entries in * - * Returns: refcounted ns or NULL if failed to create one + * Returns: the a refcounted ns that has been add or an ERR_PTR */ -struct aa_ns *aa_prepare_ns(const char *name) +struct aa_ns *__aa_find_or_create_ns(struct aa_ns *parent, const char *name, + struct dentry *dir) { - struct aa_ns *ns, *root; + struct aa_ns *ns; - root = aa_current_profile()->ns; + AA_BUG(!mutex_is_locked(&parent->lock)); - mutex_lock(&root->lock); + /* try and find the specified ns */ + /* released by caller */ + ns = aa_get_ns(__aa_find_ns(&parent->sub_ns, name)); + if (!ns) + ns = __aa_create_ns(parent, name, dir); + else + ns = ERR_PTR(-EEXIST); - /* if name isn't specified the profile is loaded to the current ns */ - if (!name) { - /* released by caller */ - ns = aa_get_ns(root); - goto out; - } + /* return ref */ + return ns; +} +/** + * aa_prepare_ns - find an existing or create a new namespace of @name + * @parent: ns to treat as parent + * @name: the namespace to find or add (NOT NULL) + * + * Returns: refcounted namespace or PTR_ERR if failed to create one + */ +struct aa_ns *aa_prepare_ns(struct aa_ns *parent, const char *name) +{ + struct aa_ns *ns; + + mutex_lock(&parent->lock); /* try and find the specified ns and if it doesn't exist create it */ /* released by caller */ - ns = aa_get_ns(__aa_find_ns(&root->sub_ns, name)); - if (!ns) { - ns = alloc_ns(root->base.hname, name); - if (!ns) - goto out; - if (__aa_fs_ns_mkdir(ns, ns_subns_dir(root), name)) { - AA_ERROR("Failed to create interface for ns %s\n", - ns->base.name); - aa_free_ns(ns); - ns = NULL; - goto out; - } - ns->parent = aa_get_ns(root); - list_add_rcu(&ns->base.list, &root->sub_ns); - /* add list ref */ - aa_get_ns(ns); - } -out: - mutex_unlock(&root->lock); + ns = aa_get_ns(__aa_find_ns(&parent->sub_ns, name)); + if (!ns) + ns = __aa_create_ns(parent, name, NULL); + mutex_unlock(&parent->lock); /* return ref */ return ns; -- cgit v1.2.1