aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/audit_tree.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2009-06-24 00:02:38 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2009-06-24 00:02:38 -0400
commit916d75761c971b6e630a26bd4ba472e90ac9a4b9 (patch)
tree3a4b18d0d29c1d12f64fefbb2bc5559813a686f7 /kernel/audit_tree.c
parent9d9609851003ebed15957f0f2ce18492739ee124 (diff)
Fix rule eviction order for AUDIT_DIR
If syscall removes the root of subtree being watched, we definitely do not want the rules refering that subtree to be destroyed without the syscall in question having a chance to match them. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'kernel/audit_tree.c')
-rw-r--r--kernel/audit_tree.c56
1 files changed, 51 insertions, 5 deletions
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
index 3ff0731284a1..2451dc6f3282 100644
--- a/kernel/audit_tree.c
+++ b/kernel/audit_tree.c
@@ -2,6 +2,7 @@
2#include <linux/inotify.h> 2#include <linux/inotify.h>
3#include <linux/namei.h> 3#include <linux/namei.h>
4#include <linux/mount.h> 4#include <linux/mount.h>
5#include <linux/kthread.h>
5 6
6struct audit_tree; 7struct audit_tree;
7struct audit_chunk; 8struct audit_chunk;
@@ -517,6 +518,8 @@ static void trim_marked(struct audit_tree *tree)
517 } 518 }
518} 519}
519 520
521static void audit_schedule_prune(void);
522
520/* called with audit_filter_mutex */ 523/* called with audit_filter_mutex */
521int audit_remove_tree_rule(struct audit_krule *rule) 524int audit_remove_tree_rule(struct audit_krule *rule)
522{ 525{
@@ -822,10 +825,11 @@ int audit_tag_tree(char *old, char *new)
822 825
823/* 826/*
824 * That gets run when evict_chunk() ends up needing to kill audit_tree. 827 * That gets run when evict_chunk() ends up needing to kill audit_tree.
825 * Runs from a separate thread, with audit_cmd_mutex held. 828 * Runs from a separate thread.
826 */ 829 */
827void audit_prune_trees(void) 830static int prune_tree_thread(void *unused)
828{ 831{
832 mutex_lock(&audit_cmd_mutex);
829 mutex_lock(&audit_filter_mutex); 833 mutex_lock(&audit_filter_mutex);
830 834
831 while (!list_empty(&prune_list)) { 835 while (!list_empty(&prune_list)) {
@@ -842,6 +846,40 @@ void audit_prune_trees(void)
842 } 846 }
843 847
844 mutex_unlock(&audit_filter_mutex); 848 mutex_unlock(&audit_filter_mutex);
849 mutex_unlock(&audit_cmd_mutex);
850 return 0;
851}
852
853static void audit_schedule_prune(void)
854{
855 kthread_run(prune_tree_thread, NULL, "audit_prune_tree");
856}
857
858/*
859 * ... and that one is done if evict_chunk() decides to delay until the end
860 * of syscall. Runs synchronously.
861 */
862void audit_kill_trees(struct list_head *list)
863{
864 mutex_lock(&audit_cmd_mutex);
865 mutex_lock(&audit_filter_mutex);
866
867 while (!list_empty(list)) {
868 struct audit_tree *victim;
869
870 victim = list_entry(list->next, struct audit_tree, list);
871 kill_rules(victim);
872 list_del_init(&victim->list);
873
874 mutex_unlock(&audit_filter_mutex);
875
876 prune_one(victim);
877
878 mutex_lock(&audit_filter_mutex);
879 }
880
881 mutex_unlock(&audit_filter_mutex);
882 mutex_unlock(&audit_cmd_mutex);
845} 883}
846 884
847/* 885/*
@@ -852,6 +890,8 @@ void audit_prune_trees(void)
852static void evict_chunk(struct audit_chunk *chunk) 890static void evict_chunk(struct audit_chunk *chunk)
853{ 891{
854 struct audit_tree *owner; 892 struct audit_tree *owner;
893 struct list_head *postponed = audit_killed_trees();
894 int need_prune = 0;
855 int n; 895 int n;
856 896
857 if (chunk->dead) 897 if (chunk->dead)
@@ -867,15 +907,21 @@ static void evict_chunk(struct audit_chunk *chunk)
867 owner->root = NULL; 907 owner->root = NULL;
868 list_del_init(&owner->same_root); 908 list_del_init(&owner->same_root);
869 spin_unlock(&hash_lock); 909 spin_unlock(&hash_lock);
870 kill_rules(owner); 910 if (!postponed) {
871 list_move(&owner->list, &prune_list); 911 kill_rules(owner);
872 audit_schedule_prune(); 912 list_move(&owner->list, &prune_list);
913 need_prune = 1;
914 } else {
915 list_move(&owner->list, postponed);
916 }
873 spin_lock(&hash_lock); 917 spin_lock(&hash_lock);
874 } 918 }
875 list_del_rcu(&chunk->hash); 919 list_del_rcu(&chunk->hash);
876 for (n = 0; n < chunk->count; n++) 920 for (n = 0; n < chunk->count; n++)
877 list_del_init(&chunk->owners[n].list); 921 list_del_init(&chunk->owners[n].list);
878 spin_unlock(&hash_lock); 922 spin_unlock(&hash_lock);
923 if (need_prune)
924 audit_schedule_prune();
879 mutex_unlock(&audit_filter_mutex); 925 mutex_unlock(&audit_filter_mutex);
880} 926}
881 927