1
Index: b/security/apparmor/apparmor.h
2
===================================================================
3
--- a/security/apparmor/apparmor.h
4
+++ b/security/apparmor/apparmor.h
5
@@ -128,6 +128,9 @@ struct aa_profile {
6
extern struct list_head profile_list;
7
extern rwlock_t profile_list_lock;
9
+extern struct list_head task_context_list;
10
+extern rwlock_t task_context_list_lock;
13
* struct aa_task_context - primary label for confined tasks
14
* @profile: the current profile
15
@@ -147,8 +150,6 @@ struct aa_task_context {
16
kernel_cap_t caps_logged;
19
-typedef int (*aa_iter) (struct aa_task_context *, void *);
21
static inline struct aa_task_context *aa_task_context(struct task_struct *task)
23
return (struct aa_task_context *)task->security;
24
@@ -236,7 +237,6 @@ extern int aa_fork(struct task_struct *t
25
extern int aa_register(struct linux_binprm *bprm);
26
extern void aa_release(struct task_struct *task);
27
extern int aa_change_hat(const char *id, u32 hat_magic);
28
-extern int aa_associate_filp(struct file *filp);
29
extern struct aa_profile *__aa_find_profile(const char *name,
30
struct list_head *list);
32
@@ -244,8 +244,6 @@ extern struct aa_profile *__aa_find_prof
33
extern void aa_profilelist_release(void);
34
extern void aa_task_context_list_add(struct aa_task_context *);
35
extern void aa_task_context_list_remove(struct aa_task_context *);
36
-extern void aa_task_context_list_iterate(aa_iter, void *);
37
-extern void aa_task_context_list_iterateremove(aa_iter, void *);
38
extern void aa_task_context_list_release(void);
40
/* module_interface.c */
41
Index: b/security/apparmor/list.c
42
===================================================================
43
--- a/security/apparmor/list.c
44
+++ b/security/apparmor/list.c
45
@@ -18,8 +18,8 @@ LIST_HEAD(profile_list);
46
rwlock_t profile_list_lock = RW_LOCK_UNLOCKED;
48
/* list of all task_contexts and lock */
49
-static LIST_HEAD(task_context_list);
50
-static rwlock_t task_context_list_lock = RW_LOCK_UNLOCKED;
51
+LIST_HEAD(task_context_list);
52
+rwlock_t task_context_list_lock = RW_LOCK_UNLOCKED;
55
* __aa_find_profile - look up a profile on the profile list
56
@@ -93,29 +93,6 @@ void aa_task_context_list_remove(struct
60
- * aa_task_context_list_iterate - apply @func over the task_context_list
61
- * @func: method to be called for each element
62
- * @cookie: user passed data
64
- * Iterate over aa_task_context list applying @func, stop when @func returns
67
-void aa_task_context_list_iterate(aa_iter func, void *cookie)
69
- struct aa_task_context *node;
71
- unsigned long flags;
73
- read_lock_irqsave(&task_context_list_lock, flags);
74
- list_for_each_entry(node, &task_context_list, list) {
75
- ret = (*func) (node, cookie);
79
- read_unlock_irqrestore(&task_context_list_lock, flags);
83
* aa_task_context_list_release - Remove all aa_task_contexts from
86
Index: b/security/apparmor/lsm.c
87
===================================================================
88
--- a/security/apparmor/lsm.c
89
+++ b/security/apparmor/lsm.c
90
@@ -747,27 +747,9 @@ createfs_out:
94
-static int apparmor_exit_removeall_iter(struct aa_task_context *cxt,
97
- /* spin_lock(&cxt_lock) held here */
100
- AA_DEBUG("%s: Dropping profiles %s(%d) "
101
- "profile %s(%p) active %s(%p)\n",
103
- cxt->task->comm, cxt->task->pid,
104
- cxt->profile->parent->name,
105
- cxt->profile->parent,
106
- cxt->profile->name, cxt->profile);
107
- aa_switch_to_profile(cxt, NULL, 0);
113
static void __exit apparmor_exit(void)
115
+ struct aa_task_context *cxt;
118
/* Remove profiles from the global profile list.
119
@@ -782,8 +764,17 @@ static void __exit apparmor_exit(void)
124
+ * FIXME: We have a lock inversion here (cp. aa_file_prof_repl,
125
+ * aa_file_prof_remove).
127
spin_lock_irqsave(&cxt_lock, flags);
128
- aa_task_context_list_iterate(apparmor_exit_removeall_iter, NULL);
129
+ read_lock(&task_context_list_lock);
130
+ list_for_each_entry(cxt, &task_context_list, list) {
132
+ aa_switch_to_profile(cxt, NULL, 0);
134
+ read_unlock(&task_context_list_lock);
135
spin_unlock_irqrestore(&cxt_lock, flags);
137
/* Free up list of profile aa_task_context */
138
Index: b/security/apparmor/module_interface.c
139
===================================================================
140
--- a/security/apparmor/module_interface.c
141
+++ b/security/apparmor/module_interface.c
144
const int aa_code_datasize[] = { 1, 2, 4, 8, 2, 2, 4, 0, 0, 0, 0, 0, 0 };
146
-struct aa_taskreplace_data {
147
- struct aa_profile *old_profile;
148
- struct aa_profile *new_profile;
152
* free_aa_profile_rcu - rcu callback for free profiles
153
* @head: rcu_head struct of the profile whose reference is being put.
154
@@ -37,49 +32,6 @@ static void free_aa_profile_rcu(struct r
159
- * task_remove - remove profile from a task's aa_task_context
160
- * @cxt: task's aa_task_context
162
- * remove the profile from a task's aa_task_context, switching the task
163
- * to an unconfined state.
165
-static inline void task_remove(struct aa_task_context *cxt)
167
- /* spin_lock(&cxt_lock) held here */
168
- AA_DEBUG("%s: removing profile from task %s(%d) profile %s active %s\n",
172
- cxt->profile->parent->name,
173
- cxt->profile->name);
175
- aa_switch_to_profile(cxt, NULL, 0);
178
-/** taskremove_iter - Iterator to unconfine aa_task_contexts which match cookie
179
- * @cxt: aa_task_context to consider for profile removal
180
- * @cookie: pointer to the oldprofile which is being removed
182
- * If the aa_task_context's profile matches old_profile, then call
183
- * task_remove() to remove the profile leaving the task (aa_task_context) unconfined.
185
-static int taskremove_iter(struct aa_task_context *cxt, void *cookie)
187
- struct aa_profile *old_profile = (struct aa_profile *)cookie;
188
- unsigned long flags;
190
- spin_lock_irqsave(&cxt_lock, flags);
192
- if (cxt->profile && cxt->profile->parent == old_profile) {
196
- spin_unlock_irqrestore(&cxt_lock, flags);
201
/** task_replace - replace aa_task_context's current profile with a new profile
202
* @cxt: aa_task_context to replace the profile on
204
@@ -99,9 +51,6 @@ static inline void task_replace(struct a
205
cxt->profile->parent->name, cxt->profile->parent,
206
cxt->profile->name, cxt->profile);
211
if (cxt->profile != cxt->profile->parent) {
212
struct aa_profile *nactive;
214
@@ -118,29 +67,6 @@ static inline void task_replace(struct a
215
aa_switch_to_profile(cxt, new, cxt->hat_magic);
218
-/** taskreplace_iter - Iterator to replace a aa_task_context's profile
219
- * @cxt: aa_task_context to consider for profile replacement
220
- * @cookie: pointer to the old profile which is being replaced.
222
- * If the aa_task_context's profile matches old_profile call
223
- * task_replace() to replace with the aa_task_context's profile with
226
-static int taskreplace_iter(struct aa_task_context *cxt, void *cookie)
228
- struct aa_taskreplace_data *data = (struct aa_taskreplace_data *)cookie;
229
- unsigned long flags;
231
- spin_lock_irqsave(&cxt_lock, flags);
233
- if (cxt->profile && cxt->profile->parent == data->old_profile)
234
- task_replace(cxt, data->new_profile);
236
- spin_unlock_irqrestore(&cxt_lock, flags);
241
static inline int aa_inbounds(struct aa_ext *e, size_t size)
243
return (e->pos + size <= e->end);
244
@@ -518,7 +444,7 @@ ssize_t aa_file_prof_add(void *data, siz
246
ssize_t aa_file_prof_repl(void *udata, size_t size)
248
- struct aa_taskreplace_data data;
249
+ struct aa_profile *old_profile, *new_profile;
253
@@ -526,28 +452,40 @@ ssize_t aa_file_prof_repl(void *udata, s
257
- data.new_profile = aa_activate_top_profile(&e, &error);
258
- if (!data.new_profile)
259
+ new_profile = aa_activate_top_profile(&e, &error);
263
write_lock(&profile_list_lock);
264
- data.old_profile = __aa_find_profile(data.new_profile->name,
266
- if (data.old_profile) {
267
- list_del_init(&data.old_profile->list);
269
- lock_profile(data.old_profile);
270
- data.old_profile->isstale = 1;
271
- unlock_profile(data.old_profile);
272
+ old_profile = __aa_find_profile(new_profile->name, &profile_list);
274
+ struct aa_task_context *cxt;
275
+ unsigned long flags;
277
+ list_del_init(&old_profile->list);
279
+ lock_profile(old_profile);
280
+ old_profile->isstale = 1;
281
+ unlock_profile(old_profile);
284
* Find all tasks using the old profile and replace the old
285
* profile with the new.
287
- aa_task_context_list_iterate(taskreplace_iter, &data);
288
- aa_put_profile(data.old_profile);
289
+ read_lock_irqsave(&task_context_list_lock, flags);
290
+ list_for_each_entry(cxt, &task_context_list, list) {
291
+ spin_lock_irqsave(&cxt_lock, flags);
293
+ if (cxt->profile &&
294
+ cxt->profile->parent == old_profile)
295
+ task_replace(cxt, new_profile);
297
+ spin_unlock_irqrestore(&cxt_lock, flags);
299
+ read_unlock_irqrestore(&task_context_list_lock, flags);
300
+ aa_put_profile(old_profile);
302
- list_add(&data.new_profile->list, &profile_list);
303
+ list_add(&new_profile->list, &profile_list);
304
write_unlock(&profile_list_lock);
307
@@ -564,6 +502,8 @@ ssize_t aa_file_prof_repl(void *udata, s
308
ssize_t aa_file_prof_remove(const char *name, size_t size)
310
struct aa_profile *profile;
311
+ struct aa_task_context *cxt;
312
+ unsigned long flags;
314
write_lock(&profile_list_lock);
315
profile = __aa_find_profile(name, &profile_list);
316
@@ -578,7 +518,16 @@ ssize_t aa_file_prof_remove(const char *
317
profile->isstale = 1;
318
unlock_profile(profile);
320
- aa_task_context_list_iterate(taskremove_iter, profile);
321
+ read_lock_irqsave(&task_context_list_lock, flags);
322
+ list_for_each_entry(cxt, &task_context_list, list) {
323
+ if (cxt->profile && cxt->profile->parent == profile) {
324
+ spin_lock(&cxt_lock);
325
+ aa_switch_to_profile(cxt, NULL, 0);
326
+ spin_unlock(&cxt_lock);
329
+ read_unlock_irqrestore(&task_context_list_lock, flags);
331
aa_put_profile(profile);
332
write_unlock(&profile_list_lock);