diff options
author | John Johansen <john.johansen@canonical.com> | 2013-07-11 00:06:43 -0400 |
---|---|---|
committer | John Johansen <john.johansen@canonical.com> | 2013-08-14 14:42:06 -0400 |
commit | 01e2b670aa898a39259bc85c78e3d74820f4d3b6 (patch) | |
tree | cd78cea5f92788c213f2eb8ef287535ac1bb3327 /security/apparmor/include | |
parent | dd51c84857630e77c139afe4d9bba65fc051dc3f (diff) |
apparmor: convert profile lists to RCU based locking
Signed-off-by: John Johansen <john.johansen@canonical.com>
Diffstat (limited to 'security/apparmor/include')
-rw-r--r-- | security/apparmor/include/apparmor.h | 6 | ||||
-rw-r--r-- | security/apparmor/include/policy.h | 45 |
2 files changed, 48 insertions, 3 deletions
diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h index 1ba2ca56a6ef..8fb1488a3cd4 100644 --- a/security/apparmor/include/apparmor.h +++ b/security/apparmor/include/apparmor.h | |||
@@ -78,6 +78,12 @@ static inline void *kvzalloc(size_t size) | |||
78 | return __aa_kvmalloc(size, __GFP_ZERO); | 78 | return __aa_kvmalloc(size, __GFP_ZERO); |
79 | } | 79 | } |
80 | 80 | ||
81 | /* returns 0 if kref not incremented */ | ||
82 | static inline int kref_get_not0(struct kref *kref) | ||
83 | { | ||
84 | return atomic_inc_not_zero(&kref->refcount); | ||
85 | } | ||
86 | |||
81 | /** | 87 | /** |
82 | * aa_strneq - compare null terminated @str to a non null terminated substring | 88 | * aa_strneq - compare null terminated @str to a non null terminated substring |
83 | * @str: a null terminated string | 89 | * @str: a null terminated string |
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[]; | |||
42 | 42 | ||
43 | #define PROFILE_IS_HAT(_profile) ((_profile)->flags & PFLAG_HAT) | 43 | #define PROFILE_IS_HAT(_profile) ((_profile)->flags & PFLAG_HAT) |
44 | 44 | ||
45 | #define on_list_rcu(X) (!list_empty(X) && (X)->prev != LIST_POISON2) | ||
46 | |||
45 | /* | 47 | /* |
46 | * FIXME: currently need a clean way to replace and remove profiles as a | 48 | * FIXME: currently need a clean way to replace and remove profiles as a |
47 | * set. It should be done at the namespace level. | 49 | * set. It should be done at the namespace level. |
@@ -75,6 +77,7 @@ struct aa_profile; | |||
75 | * @hname - The hierarchical name | 77 | * @hname - The hierarchical name |
76 | * @count: reference count of the obj | 78 | * @count: reference count of the obj |
77 | * @list: list policy object is on | 79 | * @list: list policy object is on |
80 | * @rcu: rcu head used when removing from @list | ||
78 | * @profiles: head of the profiles list contained in the object | 81 | * @profiles: head of the profiles list contained in the object |
79 | */ | 82 | */ |
80 | struct aa_policy { | 83 | struct aa_policy { |
@@ -83,6 +86,7 @@ struct aa_policy { | |||
83 | struct kref count; | 86 | struct kref count; |
84 | struct list_head list; | 87 | struct list_head list; |
85 | struct list_head profiles; | 88 | struct list_head profiles; |
89 | struct rcu_head rcu; | ||
86 | }; | 90 | }; |
87 | 91 | ||
88 | /* struct aa_ns_acct - accounting of profiles in namespace | 92 | /* struct aa_ns_acct - accounting of profiles in namespace |
@@ -124,7 +128,7 @@ struct aa_ns_acct { | |||
124 | struct aa_namespace { | 128 | struct aa_namespace { |
125 | struct aa_policy base; | 129 | struct aa_policy base; |
126 | struct aa_namespace *parent; | 130 | struct aa_namespace *parent; |
127 | rwlock_t lock; | 131 | struct mutex lock; |
128 | struct aa_ns_acct acct; | 132 | struct aa_ns_acct acct; |
129 | struct aa_profile *unconfined; | 133 | struct aa_profile *unconfined; |
130 | struct list_head sub_ns; | 134 | struct list_head sub_ns; |
@@ -166,7 +170,7 @@ struct aa_policydb { | |||
166 | * attachments are determined by profile X transition rules. | 170 | * attachments are determined by profile X transition rules. |
167 | * | 171 | * |
168 | * The @replacedby field is write protected by the profile lock. Reads | 172 | * The @replacedby field is write protected by the profile lock. Reads |
169 | * are assumed to be atomic, and are done without locking. | 173 | * are assumed to be atomic. |
170 | * | 174 | * |
171 | * Profiles have a hierarchy where hats and children profiles keep | 175 | * Profiles have a hierarchy where hats and children profiles keep |
172 | * a reference to their parent. | 176 | * a reference to their parent. |
@@ -177,7 +181,7 @@ struct aa_policydb { | |||
177 | */ | 181 | */ |
178 | struct aa_profile { | 182 | struct aa_profile { |
179 | struct aa_policy base; | 183 | struct aa_policy base; |
180 | struct aa_profile *parent; | 184 | struct aa_profile __rcu *parent; |
181 | 185 | ||
182 | struct aa_namespace *ns; | 186 | struct aa_namespace *ns; |
183 | struct aa_profile *replacedby; | 187 | struct aa_profile *replacedby; |
@@ -296,6 +300,41 @@ static inline struct aa_profile *aa_get_profile(struct aa_profile *p) | |||
296 | } | 300 | } |
297 | 301 | ||
298 | /** | 302 | /** |
303 | * aa_get_profile_not0 - increment refcount on profile @p found via lookup | ||
304 | * @p: profile (MAYBE NULL) | ||
305 | * | ||
306 | * Returns: pointer to @p if @p is NULL will return NULL | ||
307 | * Requires: @p must be held with valid refcount when called | ||
308 | */ | ||
309 | static inline struct aa_profile *aa_get_profile_not0(struct aa_profile *p) | ||
310 | { | ||
311 | if (p && kref_get_not0(&p->base.count)) | ||
312 | return p; | ||
313 | |||
314 | return NULL; | ||
315 | } | ||
316 | |||
317 | /** | ||
318 | * aa_get_profile_rcu - increment a refcount profile that can be replaced | ||
319 | * @p: pointer to profile that can be replaced (NOT NULL) | ||
320 | * | ||
321 | * Returns: pointer to a refcounted profile. | ||
322 | * else NULL if no profile | ||
323 | */ | ||
324 | static inline struct aa_profile *aa_get_profile_rcu(struct aa_profile __rcu **p) | ||
325 | { | ||
326 | struct aa_profile *c; | ||
327 | |||
328 | rcu_read_lock(); | ||
329 | do { | ||
330 | c = rcu_dereference(*p); | ||
331 | } while (c && !kref_get_not0(&c->base.count)); | ||
332 | rcu_read_unlock(); | ||
333 | |||
334 | return c; | ||
335 | } | ||
336 | |||
337 | /** | ||
299 | * aa_put_profile - decrement refcount on profile @p | 338 | * aa_put_profile - decrement refcount on profile @p |
300 | * @p: profile (MAYBE NULL) | 339 | * @p: profile (MAYBE NULL) |
301 | */ | 340 | */ |