aboutsummaryrefslogtreecommitdiffstats
path: root/security/apparmor/policy_ns.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/apparmor/policy_ns.c')
-rw-r--r--security/apparmor/policy_ns.c80
1 files changed, 73 insertions, 7 deletions
diff --git a/security/apparmor/policy_ns.c b/security/apparmor/policy_ns.c
index 93d1826c4b09..351d3bab3a3d 100644
--- a/security/apparmor/policy_ns.c
+++ b/security/apparmor/policy_ns.c
@@ -23,6 +23,7 @@
#include "include/apparmor.h"
#include "include/context.h"
#include "include/policy_ns.h"
+#include "include/label.h"
#include "include/policy.h"
/* root profile namespace */
@@ -99,15 +100,17 @@ static struct aa_ns *alloc_ns(const char *prefix, const char *name)
goto fail_ns;
INIT_LIST_HEAD(&ns->sub_ns);
+ INIT_LIST_HEAD(&ns->rawdata_list);
mutex_init(&ns->lock);
+ init_waitqueue_head(&ns->wait);
/* released by aa_free_ns() */
- ns->unconfined = aa_alloc_profile("unconfined", GFP_KERNEL);
+ ns->unconfined = aa_alloc_profile("unconfined", NULL, GFP_KERNEL);
if (!ns->unconfined)
goto fail_unconfined;
- ns->unconfined->flags = PFLAG_IX_ON_NAME_ERROR |
- PFLAG_IMMUTABLE | PFLAG_NS_COUNT;
+ ns->unconfined->label.flags |= FLAG_IX_ON_NAME_ERROR |
+ FLAG_IMMUTIBLE | FLAG_NS_COUNT | FLAG_UNCONFINED;
ns->unconfined->mode = APPARMOR_UNCONFINED;
/* ns and ns->unconfined share ns->unconfined refcount */
@@ -115,6 +118,8 @@ static struct aa_ns *alloc_ns(const char *prefix, const char *name)
atomic_set(&ns->uniq_null, 0);
+ aa_labelset_init(&ns->labels);
+
return ns;
fail_unconfined:
@@ -137,6 +142,7 @@ void aa_free_ns(struct aa_ns *ns)
return;
aa_policy_destroy(&ns->base);
+ aa_labelset_destroy(&ns->labels);
aa_put_ns(ns->parent);
ns->unconfined->ns = NULL;
@@ -181,6 +187,60 @@ struct aa_ns *aa_find_ns(struct aa_ns *root, const char *name)
return aa_findn_ns(root, name, strlen(name));
}
+/**
+ * __aa_lookupn_ns - lookup the namespace matching @hname
+ * @base: base list to start looking up profile name from (NOT NULL)
+ * @hname: hierarchical ns name (NOT NULL)
+ * @n: length of @hname
+ *
+ * Requires: rcu_read_lock be held
+ *
+ * Returns: unrefcounted ns pointer or NULL if not found
+ *
+ * Do a relative name lookup, recursing through profile tree.
+ */
+struct aa_ns *__aa_lookupn_ns(struct aa_ns *view, const char *hname, size_t n)
+{
+ struct aa_ns *ns = view;
+ const char *split;
+
+ for (split = strnstr(hname, "//", n); split;
+ split = strnstr(hname, "//", n)) {
+ ns = __aa_findn_ns(&ns->sub_ns, hname, split - hname);
+ if (!ns)
+ return NULL;
+
+ n -= split + 2 - hname;
+ hname = split + 2;
+ }
+
+ if (n)
+ return __aa_findn_ns(&ns->sub_ns, hname, n);
+ return NULL;
+}
+
+/**
+ * aa_lookupn_ns - look up a policy namespace relative to @view
+ * @view: namespace to search in (NOT NULL)
+ * @name: name of namespace to find (NOT NULL)
+ * @n: length of @name
+ *
+ * Returns: a refcounted namespace on the list, or NULL if no namespace
+ * called @name exists.
+ *
+ * refcount released by caller
+ */
+struct aa_ns *aa_lookupn_ns(struct aa_ns *view, const char *name, size_t n)
+{
+ struct aa_ns *ns = NULL;
+
+ rcu_read_lock();
+ ns = aa_get_ns(__aa_lookupn_ns(view, name, n));
+ rcu_read_unlock();
+
+ return ns;
+}
+
static struct aa_ns *__aa_create_ns(struct aa_ns *parent, const char *name,
struct dentry *dir)
{
@@ -195,7 +255,7 @@ static struct aa_ns *__aa_create_ns(struct aa_ns *parent, const char *name,
if (!ns)
return NULL;
mutex_lock(&ns->lock);
- error = __aa_fs_ns_mkdir(ns, ns_subns_dir(parent), name);
+ error = __aafs_ns_mkdir(ns, ns_subns_dir(parent), name, dir);
if (error) {
AA_ERROR("Failed to create interface for ns %s\n",
ns->base.name);
@@ -281,9 +341,15 @@ static void destroy_ns(struct aa_ns *ns)
/* release all sub namespaces */
__ns_list_release(&ns->sub_ns);
- if (ns->parent)
- __aa_update_proxy(ns->unconfined, ns->parent->unconfined);
- __aa_fs_ns_rmdir(ns);
+ if (ns->parent) {
+ unsigned long flags;
+
+ write_lock_irqsave(&ns->labels.lock, flags);
+ __aa_proxy_redirect(ns_unconfined(ns),
+ ns_unconfined(ns->parent));
+ write_unlock_irqrestore(&ns->labels.lock, flags);
+ }
+ __aafs_ns_rmdir(ns);
mutex_unlock(&ns->lock);
}