From ae7b8f4108bcffb42173f867ce845268c7202d48 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 17 Dec 2009 20:12:04 -0500 Subject: Audit: clean up the audit_watch split No real changes, just cleanup to the audit_watch split patch which we done with minimal code changes for easy review. Now fix interfaces to make things work better. Signed-off-by: Eric Paris --- kernel/auditfilter.c | 41 +++++++++++++++-------------------------- 1 file changed, 15 insertions(+), 26 deletions(-) (limited to 'kernel/auditfilter.c') diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index ce08041f578..ac87577f36b 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -71,6 +71,7 @@ static inline void audit_free_rule(struct audit_entry *e) { int i; struct audit_krule *erule = &e->rule; + /* some rules don't have associated watches */ if (erule->watch) audit_put_watch(erule->watch); @@ -746,8 +747,7 @@ static inline int audit_dupe_lsm_field(struct audit_field *df, * rule with the new rule in the filterlist, then free the old rule. * The rlist element is undefined; list manipulations are handled apart from * the initial copy. */ -struct audit_entry *audit_dupe_rule(struct audit_krule *old, - struct audit_watch *watch) +struct audit_entry *audit_dupe_rule(struct audit_krule *old) { u32 fcount = old->field_count; struct audit_entry *entry; @@ -769,8 +769,8 @@ struct audit_entry *audit_dupe_rule(struct audit_krule *old, new->prio = old->prio; new->buflen = old->buflen; new->inode_f = old->inode_f; - new->watch = NULL; new->field_count = old->field_count; + /* * note that we are OK with not refcounting here; audit_match_tree() * never dereferences tree and we can't get false positives there @@ -811,9 +811,9 @@ struct audit_entry *audit_dupe_rule(struct audit_krule *old, } } - if (watch) { - audit_get_watch(watch); - new->watch = watch; + if (old->watch) { + audit_get_watch(old->watch); + new->watch = old->watch; } return entry; @@ -866,7 +866,7 @@ static inline int audit_add_rule(struct audit_entry *entry) struct audit_watch *watch = entry->rule.watch; struct audit_tree *tree = entry->rule.tree; struct list_head *list; - int h, err; + int err; #ifdef CONFIG_AUDITSYSCALL int dont_count = 0; @@ -889,15 +889,11 @@ static inline int audit_add_rule(struct audit_entry *entry) if (watch) { /* audit_filter_mutex is dropped and re-taken during this call */ - err = audit_add_watch(&entry->rule); + err = audit_add_watch(&entry->rule, &list); if (err) { mutex_unlock(&audit_filter_mutex); goto error; } - /* entry->rule.watch may have changed during audit_add_watch() */ - watch = entry->rule.watch; - h = audit_hash_ino((u32)audit_watch_inode(watch)); - list = &audit_inode_hash[h]; } if (tree) { err = audit_add_tree_rule(&entry->rule); @@ -949,7 +945,7 @@ static inline int audit_del_rule(struct audit_entry *entry) struct audit_watch *watch = entry->rule.watch; struct audit_tree *tree = entry->rule.tree; struct list_head *list; - LIST_HEAD(inotify_list); + LIST_HEAD(inotify_unregister_list); int ret = 0; #ifdef CONFIG_AUDITSYSCALL int dont_count = 0; @@ -969,7 +965,7 @@ static inline int audit_del_rule(struct audit_entry *entry) } if (e->rule.watch) - audit_remove_watch_rule(&e->rule, &inotify_list); + audit_remove_watch_rule(&e->rule, &inotify_unregister_list); if (e->rule.tree) audit_remove_tree_rule(&e->rule); @@ -987,8 +983,8 @@ static inline int audit_del_rule(struct audit_entry *entry) #endif mutex_unlock(&audit_filter_mutex); - if (!list_empty(&inotify_list)) - audit_inotify_unregister(&inotify_list); + if (!list_empty(&inotify_unregister_list)) + audit_watch_inotify_unregister(&inotify_unregister_list); out: if (watch) @@ -1323,30 +1319,23 @@ static int update_lsm_rule(struct audit_krule *r) { struct audit_entry *entry = container_of(r, struct audit_entry, rule); struct audit_entry *nentry; - struct audit_watch *watch; - struct audit_tree *tree; int err = 0; if (!security_audit_rule_known(r)) return 0; - watch = r->watch; - tree = r->tree; - nentry = audit_dupe_rule(r, watch); + nentry = audit_dupe_rule(r); if (IS_ERR(nentry)) { /* save the first error encountered for the * return value */ err = PTR_ERR(nentry); audit_panic("error updating LSM filters"); - if (watch) + if (r->watch) list_del(&r->rlist); list_del_rcu(&entry->list); list_del(&r->list); } else { - if (watch) { - list_add(&nentry->rule.rlist, audit_watch_rules(watch)); - list_del(&r->rlist); - } else if (tree) + if (r->watch || r->tree) list_replace_init(&r->rlist, &nentry->rule.rlist); list_replace_rcu(&entry->list, &nentry->list); list_replace(&r->list, &nentry->rule.list); -- cgit v1.2.3-70-g09d2 From a05fb6cc573130915380e00d182a4c6571cec6b2 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 17 Dec 2009 20:12:05 -0500 Subject: 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 --- kernel/audit.h | 3 +-- kernel/audit_watch.c | 27 +++------------------------ kernel/auditfilter.c | 6 +----- 3 files changed, 5 insertions(+), 31 deletions(-) (limited to 'kernel/auditfilter.c') diff --git a/kernel/audit.h b/kernel/audit.h index 82c8a09099f..100b454a735 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -108,8 +108,7 @@ extern void audit_put_watch(struct audit_watch *watch); extern void audit_get_watch(struct audit_watch *watch); extern int audit_to_watch(struct audit_krule *krule, char *path, int len, u32 op); extern int audit_add_watch(struct audit_krule *krule, struct list_head **list); -extern void audit_remove_watch_rule(struct audit_krule *krule, struct list_head *list); -extern void audit_watch_inotify_unregister(struct list_head *in_list); +extern void audit_remove_watch_rule(struct audit_krule *krule); extern char *audit_watch_path(struct audit_watch *watch); extern int audit_watch_compare(struct audit_watch *watch, unsigned long ino, dev_t dev); extern struct audit_entry *audit_dupe_rule(struct audit_krule *old); diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index da66197e3ab..75ab53987ec 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -55,7 +55,6 @@ struct audit_watch { }; struct audit_parent { - struct list_head ilist; /* tmp list used to free parents */ struct list_head watches; /* anchor for audit_watch->wlist */ struct fsnotify_mark_entry mark; /* fsnotify mark on the inode */ }; @@ -356,20 +355,6 @@ static void audit_remove_parent_watches(struct audit_parent *parent) fsnotify_destroy_mark_by_entry(&parent->mark); } -/* Unregister inotify watches for parents on in_list. - * Generates an FS_IGNORED event. */ -void audit_watch_inotify_unregister(struct list_head *in_list) -{ - struct audit_parent *p, *n; - - list_for_each_entry_safe(p, n, in_list, ilist) { - list_del(&p->ilist); - fsnotify_destroy_mark_by_entry(&p->mark); - /* matches the get in audit_remove_watch_rule() */ - audit_put_parent(p); - } -} - /* Get path information necessary for adding watches. */ static int audit_get_nd(char *path, struct nameidata **ndp, struct nameidata **ndw) { @@ -502,7 +487,7 @@ error: } -void audit_remove_watch_rule(struct audit_krule *krule, struct list_head *list) +void audit_remove_watch_rule(struct audit_krule *krule) { struct audit_watch *watch = krule->watch; struct audit_parent *parent = watch->parent; @@ -513,15 +498,9 @@ void audit_remove_watch_rule(struct audit_krule *krule, struct list_head *list) audit_remove_watch(watch); if (list_empty(&parent->watches)) { - /* Put parent on the un-registration list. - * Grab a reference before releasing - * audit_filter_mutex, to be released in - * audit_watch_inotify_unregister(). - * If filesystem is going away, just leave - * the sucker alone, eviction will take - * care of it. */ audit_get_parent(parent); - list_add(&parent->ilist, list); + fsnotify_destroy_mark_by_entry(&parent->mark); + audit_put_parent(parent); } } } diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index ac87577f36b..eb7675499fb 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -945,7 +945,6 @@ static inline int audit_del_rule(struct audit_entry *entry) struct audit_watch *watch = entry->rule.watch; struct audit_tree *tree = entry->rule.tree; struct list_head *list; - LIST_HEAD(inotify_unregister_list); int ret = 0; #ifdef CONFIG_AUDITSYSCALL int dont_count = 0; @@ -965,7 +964,7 @@ static inline int audit_del_rule(struct audit_entry *entry) } if (e->rule.watch) - audit_remove_watch_rule(&e->rule, &inotify_unregister_list); + audit_remove_watch_rule(&e->rule); if (e->rule.tree) audit_remove_tree_rule(&e->rule); @@ -983,9 +982,6 @@ static inline int audit_del_rule(struct audit_entry *entry) #endif mutex_unlock(&audit_filter_mutex); - if (!list_empty(&inotify_unregister_list)) - audit_watch_inotify_unregister(&inotify_unregister_list); - out: if (watch) audit_put_watch(watch); /* match initial get */ -- cgit v1.2.3-70-g09d2