From: Alexander Viro <aviro@redhat.com> Date: Wed, 21 Apr 2010 01:07:55 -0400 Subject: [audit] fix selinux_audit_rule_update w/audit_inode_hash Message-id: <20100421010755.GB22181@shell.devel.redhat.com> Patchwork-id: 24268 O-Subject: Re: [rhel5][bz 579479] fixes (1/4) Bugzilla: 579479 RH-Acked-by: Eric Paris <eparis@redhat.com> RH-Acked-by: Rik van Riel <riel@redhat.com> [PATCH] selinux_audit_rule_update() misses the audit_inode_hash[] ones Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 70bf6a0..2e75dab 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -1797,6 +1797,41 @@ static inline int audit_rule_has_selinux(struct audit_krule *rule) return 0; } +static int update_lsm_rule(struct audit_entry *entry) +{ + struct audit_entry *nentry; + struct audit_watch *watch; + struct audit_tree *tree; + int err = 0; + + if (!audit_rule_has_selinux(&entry->rule)) + return 0; + + watch = entry->rule.watch; + tree = entry->rule.tree; + nentry = audit_dupe_rule(&entry->rule, watch); + if (unlikely(IS_ERR(nentry))) { + /* save the first error encountered for the + * return value */ + err = PTR_ERR(nentry); + audit_panic("error updating selinux filters"); + if (watch) + list_del(&entry->rule.rlist); + list_del_rcu(&entry->list); + } else { + if (watch) { + list_add(&nentry->rule.rlist, &watch->rules); + list_del(&entry->rule.rlist); + } else if (tree) + list_replace_init(&entry->rule.rlist, + &nentry->rule.rlist); + list_replace_rcu(&entry->list, &nentry->list); + } + call_rcu(&entry->rcu, audit_free_rule_rcu); + + return err; +} + /* This function will re-initialize the se_rule field of all applicable rules. * It will traverse the filter lists serarching for rules that contain selinux * specific filter fields. When such a rule is found, it is copied, the @@ -1804,42 +1839,24 @@ static inline int audit_rule_has_selinux(struct audit_krule *rule) * updated rule. */ int selinux_audit_rule_update(void) { - struct audit_entry *entry, *n, *nentry; - struct audit_watch *watch; - struct audit_tree *tree; + struct audit_entry *e, *n; int i, err = 0; /* audit_filter_mutex synchronizes the writers */ mutex_lock(&audit_filter_mutex); for (i = 0; i < AUDIT_NR_FILTERS; i++) { - list_for_each_entry_safe(entry, n, &audit_filter_list[i], list) { - if (!audit_rule_has_selinux(&entry->rule)) - continue; - - watch = entry->rule.watch; - tree = entry->rule.tree; - nentry = audit_dupe_rule(&entry->rule, watch); - if (unlikely(IS_ERR(nentry))) { - /* save the first error encountered for the - * return value */ - if (!err) - err = PTR_ERR(nentry); - audit_panic("error updating selinux filters"); - if (watch) - list_del(&entry->rule.rlist); - list_del_rcu(&entry->list); - } else { - if (watch) { - list_add(&nentry->rule.rlist, - &watch->rules); - list_del(&entry->rule.rlist); - } else if (tree) - list_replace_init(&entry->rule.rlist, - &nentry->rule.rlist); - list_replace_rcu(&entry->list, &nentry->list); - } - call_rcu(&entry->rcu, audit_free_rule_rcu); + list_for_each_entry_safe(e, n, &audit_filter_list[i], list) { + int res = update_lsm_rule(e); + if (!err) + err = res; + } + } + for (i=0; i< AUDIT_INODE_BUCKETS; i++) { + list_for_each_entry_safe(e, n, &audit_inode_hash[i], list) { + int res = update_lsm_rule(e); + if (!err) + err = res; } }