summaryrefslogtreecommitdiffstats
path: root/security/apparmor/include/policy.h
diff options
context:
space:
mode:
authorJohn Johansen2013-07-11 06:06:43 +0200
committerJohn Johansen2013-08-14 20:42:06 +0200
commit01e2b670aa898a39259bc85c78e3d74820f4d3b6 (patch)
treecd78cea5f92788c213f2eb8ef287535ac1bb3327 /security/apparmor/include/policy.h
parentapparmor: provide base for multiple profiles to be replaced at once (diff)
downloadkernel-qcow2-linux-01e2b670aa898a39259bc85c78e3d74820f4d3b6.tar.gz
kernel-qcow2-linux-01e2b670aa898a39259bc85c78e3d74820f4d3b6.tar.xz
kernel-qcow2-linux-01e2b670aa898a39259bc85c78e3d74820f4d3b6.zip
apparmor: convert profile lists to RCU based locking
Signed-off-by: John Johansen <john.johansen@canonical.com>
Diffstat (limited to 'security/apparmor/include/policy.h')
-rw-r--r--security/apparmor/include/policy.h45
1 files changed, 42 insertions, 3 deletions
diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
index b25491a3046a..82487a853353 100644
--- a/security/apparmor/include/policy.h
+++ b/security/apparmor/include/policy.h
@@ -42,6 +42,8 @@ extern const char *const profile_mode_names[];
#define PROFILE_IS_HAT(_profile) ((_profile)->flags & PFLAG_HAT)
+#define on_list_rcu(X) (!list_empty(X) && (X)->prev != LIST_POISON2)
+
/*
* FIXME: currently need a clean way to replace and remove profiles as a
* set. It should be done at the namespace level.
@@ -75,6 +77,7 @@ struct aa_profile;
* @hname - The hierarchical name
* @count: reference count of the obj
* @list: list policy object is on
+ * @rcu: rcu head used when removing from @list
* @profiles: head of the profiles list contained in the object
*/
struct aa_policy {
@@ -83,6 +86,7 @@ struct aa_policy {
struct kref count;
struct list_head list;
struct list_head profiles;
+ struct rcu_head rcu;
};
/* struct aa_ns_acct - accounting of profiles in namespace
@@ -124,7 +128,7 @@ struct aa_ns_acct {
struct aa_namespace {
struct aa_policy base;
struct aa_namespace *parent;
- rwlock_t lock;
+ struct mutex lock;
struct aa_ns_acct acct;
struct aa_profile *unconfined;
struct list_head sub_ns;
@@ -166,7 +170,7 @@ struct aa_policydb {
* attachments are determined by profile X transition rules.
*
* The @replacedby field is write protected by the profile lock. Reads
- * are assumed to be atomic, and are done without locking.
+ * are assumed to be atomic.
*
* Profiles have a hierarchy where hats and children profiles keep
* a reference to their parent.
@@ -177,7 +181,7 @@ struct aa_policydb {
*/
struct aa_profile {
struct aa_policy base;
- struct aa_profile *parent;
+ struct aa_profile __rcu *parent;
struct aa_namespace *ns;
struct aa_profile *replacedby;
@@ -296,6 +300,41 @@ static inline struct aa_profile *aa_get_profile(struct aa_profile *p)
}
/**
+ * aa_get_profile_not0 - increment refcount on profile @p found via lookup
+ * @p: profile (MAYBE NULL)
+ *
+ * Returns: pointer to @p if @p is NULL will return NULL
+ * Requires: @p must be held with valid refcount when called
+ */
+static inline struct aa_profile *aa_get_profile_not0(struct aa_profile *p)
+{
+ if (p && kref_get_not0(&p->base.count))
+ return p;
+
+ return NULL;
+}
+
+/**
+ * aa_get_profile_rcu - increment a refcount profile that can be replaced
+ * @p: pointer to profile that can be replaced (NOT NULL)
+ *
+ * Returns: pointer to a refcounted profile.
+ * else NULL if no profile
+ */
+static inline struct aa_profile *aa_get_profile_rcu(struct aa_profile __rcu **p)
+{
+ struct aa_profile *c;
+
+ rcu_read_lock();
+ do {
+ c = rcu_dereference(*p);
+ } while (c && !kref_get_not0(&c->base.count));
+ rcu_read_unlock();
+
+ return c;
+}
+
+/**
* aa_put_profile - decrement refcount on profile @p
* @p: profile (MAYBE NULL)
*/