apparmor/kernel-patches/for-mainline/remove-iterators.diff
2007-02-21 01:08:46 +00:00

333 lines
10 KiB
Diff

Index: b/security/apparmor/apparmor.h
===================================================================
--- a/security/apparmor/apparmor.h
+++ b/security/apparmor/apparmor.h
@@ -128,6 +128,9 @@ struct aa_profile {
extern struct list_head profile_list;
extern rwlock_t profile_list_lock;
+extern struct list_head task_context_list;
+extern rwlock_t task_context_list_lock;
+
/**
* struct aa_task_context - primary label for confined tasks
* @profile: the current profile
@@ -147,8 +150,6 @@ struct aa_task_context {
kernel_cap_t caps_logged;
};
-typedef int (*aa_iter) (struct aa_task_context *, void *);
-
static inline struct aa_task_context *aa_task_context(struct task_struct *task)
{
return (struct aa_task_context *)task->security;
@@ -236,7 +237,6 @@ extern int aa_fork(struct task_struct *t
extern int aa_register(struct linux_binprm *bprm);
extern void aa_release(struct task_struct *task);
extern int aa_change_hat(const char *id, u32 hat_magic);
-extern int aa_associate_filp(struct file *filp);
extern struct aa_profile *__aa_find_profile(const char *name,
struct list_head *list);
@@ -244,8 +244,6 @@ extern struct aa_profile *__aa_find_prof
extern void aa_profilelist_release(void);
extern void aa_task_context_list_add(struct aa_task_context *);
extern void aa_task_context_list_remove(struct aa_task_context *);
-extern void aa_task_context_list_iterate(aa_iter, void *);
-extern void aa_task_context_list_iterateremove(aa_iter, void *);
extern void aa_task_context_list_release(void);
/* module_interface.c */
Index: b/security/apparmor/list.c
===================================================================
--- a/security/apparmor/list.c
+++ b/security/apparmor/list.c
@@ -18,8 +18,8 @@ LIST_HEAD(profile_list);
rwlock_t profile_list_lock = RW_LOCK_UNLOCKED;
/* list of all task_contexts and lock */
-static LIST_HEAD(task_context_list);
-static rwlock_t task_context_list_lock = RW_LOCK_UNLOCKED;
+LIST_HEAD(task_context_list);
+rwlock_t task_context_list_lock = RW_LOCK_UNLOCKED;
/**
* __aa_find_profile - look up a profile on the profile list
@@ -93,29 +93,6 @@ void aa_task_context_list_remove(struct
}
/**
- * aa_task_context_list_iterate - apply @func over the task_context_list
- * @func: method to be called for each element
- * @cookie: user passed data
- *
- * Iterate over aa_task_context list applying @func, stop when @func returns
- * non zero
- */
-void aa_task_context_list_iterate(aa_iter func, void *cookie)
-{
- struct aa_task_context *node;
- int ret = 0;
- unsigned long flags;
-
- read_lock_irqsave(&task_context_list_lock, flags);
- list_for_each_entry(node, &task_context_list, list) {
- ret = (*func) (node, cookie);
- if (ret != 0)
- break;
- }
- read_unlock_irqrestore(&task_context_list_lock, flags);
-}
-
-/**
* aa_task_context_list_release - Remove all aa_task_contexts from
* task_context_list
*/
Index: b/security/apparmor/lsm.c
===================================================================
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -747,27 +747,9 @@ createfs_out:
}
-static int apparmor_exit_removeall_iter(struct aa_task_context *cxt,
- void *cookie)
-{
- /* spin_lock(&cxt_lock) held here */
-
- if (cxt->profile) {
- AA_DEBUG("%s: Dropping profiles %s(%d) "
- "profile %s(%p) active %s(%p)\n",
- __FUNCTION__,
- cxt->task->comm, cxt->task->pid,
- cxt->profile->parent->name,
- cxt->profile->parent,
- cxt->profile->name, cxt->profile);
- aa_switch_to_profile(cxt, NULL, 0);
- }
-
- return 0;
-}
-
static void __exit apparmor_exit(void)
{
+ struct aa_task_context *cxt;
unsigned long flags;
/* Remove profiles from the global profile list.
@@ -782,8 +764,17 @@ static void __exit apparmor_exit(void)
* reattached
*/
+ /*
+ * FIXME: We have a lock inversion here (cp. aa_file_prof_repl,
+ * aa_file_prof_remove).
+ */
spin_lock_irqsave(&cxt_lock, flags);
- aa_task_context_list_iterate(apparmor_exit_removeall_iter, NULL);
+ read_lock(&task_context_list_lock);
+ list_for_each_entry(cxt, &task_context_list, list) {
+ if (cxt->profile)
+ aa_switch_to_profile(cxt, NULL, 0);
+ }
+ read_unlock(&task_context_list_lock);
spin_unlock_irqrestore(&cxt_lock, flags);
/* Free up list of profile aa_task_context */
Index: b/security/apparmor/module_interface.c
===================================================================
--- a/security/apparmor/module_interface.c
+++ b/security/apparmor/module_interface.c
@@ -19,11 +19,6 @@
const int aa_code_datasize[] = { 1, 2, 4, 8, 2, 2, 4, 0, 0, 0, 0, 0, 0 };
-struct aa_taskreplace_data {
- struct aa_profile *old_profile;
- struct aa_profile *new_profile;
-};
-
/**
* free_aa_profile_rcu - rcu callback for free profiles
* @head: rcu_head struct of the profile whose reference is being put.
@@ -37,49 +32,6 @@ static void free_aa_profile_rcu(struct r
free_aa_profile(p);
}
-/**
- * task_remove - remove profile from a task's aa_task_context
- * @cxt: task's aa_task_context
- *
- * remove the profile from a task's aa_task_context, switching the task
- * to an unconfined state.
- */
-static inline void task_remove(struct aa_task_context *cxt)
-{
- /* spin_lock(&cxt_lock) held here */
- AA_DEBUG("%s: removing profile from task %s(%d) profile %s active %s\n",
- __FUNCTION__,
- cxt->task->comm,
- cxt->task->pid,
- cxt->profile->parent->name,
- cxt->profile->name);
-
- aa_switch_to_profile(cxt, NULL, 0);
-}
-
-/** taskremove_iter - Iterator to unconfine aa_task_contexts which match cookie
- * @cxt: aa_task_context to consider for profile removal
- * @cookie: pointer to the oldprofile which is being removed
- *
- * If the aa_task_context's profile matches old_profile, then call
- * task_remove() to remove the profile leaving the task (aa_task_context) unconfined.
- */
-static int taskremove_iter(struct aa_task_context *cxt, void *cookie)
-{
- struct aa_profile *old_profile = (struct aa_profile *)cookie;
- unsigned long flags;
-
- spin_lock_irqsave(&cxt_lock, flags);
-
- if (cxt->profile && cxt->profile->parent == old_profile) {
- task_remove(cxt);
- }
-
- spin_unlock_irqrestore(&cxt_lock, flags);
-
- return 0;
-}
-
/** task_replace - replace aa_task_context's current profile with a new profile
* @cxt: aa_task_context to replace the profile on
* @new: new profile
@@ -99,9 +51,6 @@ static inline void task_replace(struct a
cxt->profile->parent->name, cxt->profile->parent,
cxt->profile->name, cxt->profile);
- if (!cxt->profile)
- return;
-
if (cxt->profile != cxt->profile->parent) {
struct aa_profile *nactive;
@@ -118,29 +67,6 @@ static inline void task_replace(struct a
aa_switch_to_profile(cxt, new, cxt->hat_magic);
}
-/** taskreplace_iter - Iterator to replace a aa_task_context's profile
- * @cxt: aa_task_context to consider for profile replacement
- * @cookie: pointer to the old profile which is being replaced.
- *
- * If the aa_task_context's profile matches old_profile call
- * task_replace() to replace with the aa_task_context's profile with
- * the new profile.
- */
-static int taskreplace_iter(struct aa_task_context *cxt, void *cookie)
-{
- struct aa_taskreplace_data *data = (struct aa_taskreplace_data *)cookie;
- unsigned long flags;
-
- spin_lock_irqsave(&cxt_lock, flags);
-
- if (cxt->profile && cxt->profile->parent == data->old_profile)
- task_replace(cxt, data->new_profile);
-
- spin_unlock_irqrestore(&cxt_lock, flags);
-
- return 0;
-}
-
static inline int aa_inbounds(struct aa_ext *e, size_t size)
{
return (e->pos + size <= e->end);
@@ -518,7 +444,7 @@ ssize_t aa_file_prof_add(void *data, siz
*/
ssize_t aa_file_prof_repl(void *udata, size_t size)
{
- struct aa_taskreplace_data data;
+ struct aa_profile *old_profile, *new_profile;
struct aa_ext e = {
.start = udata,
.end = udata + size,
@@ -526,28 +452,40 @@ ssize_t aa_file_prof_repl(void *udata, s
};
ssize_t error;
- data.new_profile = aa_activate_top_profile(&e, &error);
- if (!data.new_profile)
+ new_profile = aa_activate_top_profile(&e, &error);
+ if (!new_profile)
return error;
write_lock(&profile_list_lock);
- data.old_profile = __aa_find_profile(data.new_profile->name,
- &profile_list);
- if (data.old_profile) {
- list_del_init(&data.old_profile->list);
-
- lock_profile(data.old_profile);
- data.old_profile->isstale = 1;
- unlock_profile(data.old_profile);
+ old_profile = __aa_find_profile(new_profile->name, &profile_list);
+ if (old_profile) {
+ struct aa_task_context *cxt;
+ unsigned long flags;
+
+ list_del_init(&old_profile->list);
+
+ lock_profile(old_profile);
+ old_profile->isstale = 1;
+ unlock_profile(old_profile);
/*
* Find all tasks using the old profile and replace the old
* profile with the new.
*/
- aa_task_context_list_iterate(taskreplace_iter, &data);
- aa_put_profile(data.old_profile);
+ read_lock_irqsave(&task_context_list_lock, flags);
+ list_for_each_entry(cxt, &task_context_list, list) {
+ spin_lock_irqsave(&cxt_lock, flags);
+
+ if (cxt->profile &&
+ cxt->profile->parent == old_profile)
+ task_replace(cxt, new_profile);
+
+ spin_unlock_irqrestore(&cxt_lock, flags);
+ }
+ read_unlock_irqrestore(&task_context_list_lock, flags);
+ aa_put_profile(old_profile);
}
- list_add(&data.new_profile->list, &profile_list);
+ list_add(&new_profile->list, &profile_list);
write_unlock(&profile_list_lock);
return size;
@@ -564,6 +502,8 @@ ssize_t aa_file_prof_repl(void *udata, s
ssize_t aa_file_prof_remove(const char *name, size_t size)
{
struct aa_profile *profile;
+ struct aa_task_context *cxt;
+ unsigned long flags;
write_lock(&profile_list_lock);
profile = __aa_find_profile(name, &profile_list);
@@ -578,7 +518,16 @@ ssize_t aa_file_prof_remove(const char *
profile->isstale = 1;
unlock_profile(profile);
- aa_task_context_list_iterate(taskremove_iter, profile);
+ read_lock_irqsave(&task_context_list_lock, flags);
+ list_for_each_entry(cxt, &task_context_list, list) {
+ if (cxt->profile && cxt->profile->parent == profile) {
+ spin_lock(&cxt_lock);
+ aa_switch_to_profile(cxt, NULL, 0);
+ spin_unlock(&cxt_lock);
+ }
+ }
+ read_unlock_irqrestore(&task_context_list_lock, flags);
+
aa_put_profile(profile);
write_unlock(&profile_list_lock);