aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2009-12-17 20:12:05 -0500
committerEric Paris <eparis@redhat.com>2010-07-28 09:58:17 -0400
commita05fb6cc573130915380e00d182a4c6571cec6b2 (patch)
treec67e626c5307d89e6d7e65d0b2f9834c3591edb2
parente118e9c5638bbe877aa26b5cd2fd223cc24cdc8a (diff)
audit: do not get and put just to free a watch
deleting audit watch rules is not currently done under audit_filter_mutex. It was done this way because we could not hold the mutex during inotify manipulation. Since we are using fsnotify we don't need to do the extra get/put pair nor do we need the private list on which to store the parents while they are about to be freed. Signed-off-by: Eric Paris <eparis@redhat.com>
-rw-r--r--kernel/audit.h3
-rw-r--r--kernel/audit_watch.c27
-rw-r--r--kernel/auditfilter.c6
3 files changed, 5 insertions, 31 deletions
diff --git a/kernel/audit.h b/kernel/audit.h
index 82c8a09099f4..100b454a7354 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -108,8 +108,7 @@ extern void audit_put_watch(struct audit_watch *watch);
108extern void audit_get_watch(struct audit_watch *watch); 108extern void audit_get_watch(struct audit_watch *watch);
109extern int audit_to_watch(struct audit_krule *krule, char *path, int len, u32 op); 109extern int audit_to_watch(struct audit_krule *krule, char *path, int len, u32 op);
110extern int audit_add_watch(struct audit_krule *krule, struct list_head **list); 110extern int audit_add_watch(struct audit_krule *krule, struct list_head **list);
111extern void audit_remove_watch_rule(struct audit_krule *krule, struct list_head *list); 111extern void audit_remove_watch_rule(struct audit_krule *krule);
112extern void audit_watch_inotify_unregister(struct list_head *in_list);
113extern char *audit_watch_path(struct audit_watch *watch); 112extern char *audit_watch_path(struct audit_watch *watch);
114extern int audit_watch_compare(struct audit_watch *watch, unsigned long ino, dev_t dev); 113extern int audit_watch_compare(struct audit_watch *watch, unsigned long ino, dev_t dev);
115extern struct audit_entry *audit_dupe_rule(struct audit_krule *old); 114extern struct audit_entry *audit_dupe_rule(struct audit_krule *old);
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index da66197e3abc..75ab53987ece 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -55,7 +55,6 @@ struct audit_watch {
55}; 55};
56 56
57struct audit_parent { 57struct audit_parent {
58 struct list_head ilist; /* tmp list used to free parents */
59 struct list_head watches; /* anchor for audit_watch->wlist */ 58 struct list_head watches; /* anchor for audit_watch->wlist */
60 struct fsnotify_mark_entry mark; /* fsnotify mark on the inode */ 59 struct fsnotify_mark_entry mark; /* fsnotify mark on the inode */
61}; 60};
@@ -356,20 +355,6 @@ static void audit_remove_parent_watches(struct audit_parent *parent)
356 fsnotify_destroy_mark_by_entry(&parent->mark); 355 fsnotify_destroy_mark_by_entry(&parent->mark);
357} 356}
358 357
359/* Unregister inotify watches for parents on in_list.
360 * Generates an FS_IGNORED event. */
361void audit_watch_inotify_unregister(struct list_head *in_list)
362{
363 struct audit_parent *p, *n;
364
365 list_for_each_entry_safe(p, n, in_list, ilist) {
366 list_del(&p->ilist);
367 fsnotify_destroy_mark_by_entry(&p->mark);
368 /* matches the get in audit_remove_watch_rule() */
369 audit_put_parent(p);
370 }
371}
372
373/* Get path information necessary for adding watches. */ 358/* Get path information necessary for adding watches. */
374static int audit_get_nd(char *path, struct nameidata **ndp, struct nameidata **ndw) 359static int audit_get_nd(char *path, struct nameidata **ndp, struct nameidata **ndw)
375{ 360{
@@ -502,7 +487,7 @@ error:
502 487
503} 488}
504 489
505void audit_remove_watch_rule(struct audit_krule *krule, struct list_head *list) 490void audit_remove_watch_rule(struct audit_krule *krule)
506{ 491{
507 struct audit_watch *watch = krule->watch; 492 struct audit_watch *watch = krule->watch;
508 struct audit_parent *parent = watch->parent; 493 struct audit_parent *parent = watch->parent;
@@ -513,15 +498,9 @@ void audit_remove_watch_rule(struct audit_krule *krule, struct list_head *list)
513 audit_remove_watch(watch); 498 audit_remove_watch(watch);
514 499
515 if (list_empty(&parent->watches)) { 500 if (list_empty(&parent->watches)) {
516 /* Put parent on the un-registration list.
517 * Grab a reference before releasing
518 * audit_filter_mutex, to be released in
519 * audit_watch_inotify_unregister().
520 * If filesystem is going away, just leave
521 * the sucker alone, eviction will take
522 * care of it. */
523 audit_get_parent(parent); 501 audit_get_parent(parent);
524 list_add(&parent->ilist, list); 502 fsnotify_destroy_mark_by_entry(&parent->mark);
503 audit_put_parent(parent);
525 } 504 }
526 } 505 }
527} 506}
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index ac87577f36b5..eb7675499fb5 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -945,7 +945,6 @@ static inline int audit_del_rule(struct audit_entry *entry)
945 struct audit_watch *watch = entry->rule.watch; 945 struct audit_watch *watch = entry->rule.watch;
946 struct audit_tree *tree = entry->rule.tree; 946 struct audit_tree *tree = entry->rule.tree;
947 struct list_head *list; 947 struct list_head *list;
948 LIST_HEAD(inotify_unregister_list);
949 int ret = 0; 948 int ret = 0;
950#ifdef CONFIG_AUDITSYSCALL 949#ifdef CONFIG_AUDITSYSCALL
951 int dont_count = 0; 950 int dont_count = 0;
@@ -965,7 +964,7 @@ static inline int audit_del_rule(struct audit_entry *entry)
965 } 964 }
966 965
967 if (e->rule.watch) 966 if (e->rule.watch)
968 audit_remove_watch_rule(&e->rule, &inotify_unregister_list); 967 audit_remove_watch_rule(&e->rule);
969 968
970 if (e->rule.tree) 969 if (e->rule.tree)
971 audit_remove_tree_rule(&e->rule); 970 audit_remove_tree_rule(&e->rule);
@@ -983,9 +982,6 @@ static inline int audit_del_rule(struct audit_entry *entry)
983#endif 982#endif
984 mutex_unlock(&audit_filter_mutex); 983 mutex_unlock(&audit_filter_mutex);
985 984
986 if (!list_empty(&inotify_unregister_list))
987 audit_watch_inotify_unregister(&inotify_unregister_list);
988
989out: 985out:
990 if (watch) 986 if (watch)
991 audit_put_watch(watch); /* match initial get */ 987 audit_put_watch(watch); /* match initial get */