1
Index: linux-2.6-apparmor/security/apparmor/apparmor.h
2
===================================================================
3
--- linux-2.6-apparmor.orig/security/apparmor/apparmor.h
4
+++ linux-2.6-apparmor/security/apparmor/apparmor.h
5
@@ -257,6 +257,7 @@ extern ssize_t aa_file_prof_replace(void
6
extern ssize_t aa_file_prof_remove(const char *, size_t);
7
extern void free_aa_profile(struct aa_profile *profile);
8
extern void free_aa_profile_kref(struct kref *kref);
9
+extern void aa_unconfine_tasks(struct aa_profile *profile);
12
extern int aa_getprocattr(struct aa_profile *profile, char **string,
13
Index: linux-2.6-apparmor/security/apparmor/lsm.c
14
===================================================================
15
--- linux-2.6-apparmor.orig/security/apparmor/lsm.c
16
+++ linux-2.6-apparmor/security/apparmor/lsm.c
17
@@ -807,7 +807,7 @@ static void __exit apparmor_exit(void)
18
/* Remove the profile from each task context it is on. */
19
lock_profile(profile);
20
profile->isstale = ERR_PTR(-ENOENT);
21
- remove_tasks_on_context_list(profile);
22
+ aa_unconfine_tasks(profile);
23
unlock_profile(profile);
25
/* Release the profile itself. */
26
Index: linux-2.6-apparmor/security/apparmor/module_interface.c
27
===================================================================
28
--- linux-2.6-apparmor.orig/security/apparmor/module_interface.c
29
+++ linux-2.6-apparmor/security/apparmor/module_interface.c
30
@@ -444,7 +444,9 @@ ssize_t aa_file_prof_replace(void *udata
31
write_lock(&profile_list_lock);
32
old_profile = __aa_find_profile(new_profile->name, &profile_list);
34
- old_profile->isstale = aa_dup_profile(new_profile);
35
+ lock_profile(old_profile);
36
+ old_profile->isstale = new_profile;
37
+ unlock_profile(old_profile);
38
list_del_init(&old_profile->list);
40
aa_dup_profile(new_profile);
41
@@ -471,20 +473,14 @@ ssize_t aa_file_prof_replace(void *udata
43
new_cxt = aa_alloc_task_context(GFP_KERNEL | __GFP_NOFAIL);
46
- * new_profile needs to be locked in the case that there
47
- * are multiple tasks on old_profile->list, this avoids
48
- * a race between an already replaced task changing its
49
- * profile (updating the list) and replacement updating
53
lock_both_profiles(old_profile, new_profile);
54
if (new_profile->isstale) {
55
struct aa_profile *profile;
57
if (IS_ERR(new_profile->isstale)) {
58
/* new_profile was removed so become removal */
59
- remove_tasks_on_context_list(old_profile);
60
+ aa_unconfine_tasks(old_profile);
61
unlock_both_profiles(old_profile, new_profile);
64
@@ -531,14 +527,17 @@ ssize_t aa_file_prof_remove(const char *
65
write_unlock(&profile_list_lock);
68
- profile->isstale = ERR_PTR(-ENOENT);
69
- list_del_init(&profile->list);
70
- write_unlock(&profile_list_lock);
72
+ /* Remove the profile from each task context it is on. */
73
lock_profile(profile);
74
- remove_tasks_on_context_list(profile);
75
+ profile->isstale = ERR_PTR(-ENOENT);
76
+ aa_unconfine_tasks(profile);
77
unlock_profile(profile);
79
+ /* Release the profile itself. */
80
+ list_del_init(&profile->list);
81
aa_put_profile(profile);
82
+ write_unlock(&profile_list_lock);
86
@@ -581,8 +580,6 @@ void free_aa_profile(struct aa_profile *
90
- if (!IS_ERR(profile->isstale))
91
- aa_put_profile(profile->isstale);
92
aa_match_free(profile->file_rules);
94
/* use free_aa_profile instead of aa_put_profile to destroy the
95
@@ -603,3 +600,21 @@ void free_aa_profile(struct aa_profile *
101
+ * aa_unconfine_tasks - remove tasks on @profiles task_contexts list
102
+ * @profile: profile to remove associated tasks
104
+ * Assumes that @profile lock is held
106
+void aa_unconfine_tasks(struct aa_profile *profile)
108
+ while (!list_empty(&profile->task_contexts)) {
109
+ struct task_struct *task =
110
+ list_entry(profile->task_contexts.next,
111
+ struct aa_task_context, list)->task;
113
+ aa_change_task_context(task, NULL, NULL, 0);
117
Index: linux-2.6-apparmor/security/apparmor/inline.h
118
===================================================================
119
--- linux-2.6-apparmor.orig/security/apparmor/inline.h
120
+++ linux-2.6-apparmor/security/apparmor/inline.h
121
@@ -104,24 +104,6 @@ static inline struct aa_profile *alloc_a
125
- * remove_tasks_on_context_list - remove tasks on @profiles task_contexts list
126
- * @profile: profile to remove associated tasks
128
- * Assumes that @profile lock is held
130
-static inline void remove_tasks_on_context_list(struct aa_profile *profile)
132
- while (!list_empty(&profile->task_contexts)) {
133
- struct task_struct *task =
134
- list_entry(profile->task_contexts.next,
135
- struct aa_task_context, list)->task;
137
- aa_change_task_context(task, NULL, NULL, 0);
143
* lock_profile - lock a profile
144
* @profile: the profile to lock
146
Index: linux-2.6-apparmor/security/apparmor/main.c
147
===================================================================
148
--- linux-2.6-apparmor.orig/security/apparmor/main.c
149
+++ linux-2.6-apparmor/security/apparmor/main.c
150
@@ -1201,7 +1201,7 @@ struct aa_profile *aa_replace_profile(st
153
cxt = lock_task_and_profiles(task, profile);
154
- if (profile && profile->isstale) {
155
+ if (unlikely(profile && profile->isstale)) {
157
unlock_both_profiles(profile, cxt ? cxt->profile : NULL);
158
aa_free_task_context(new_cxt);