In audit_add_rule(), check the inode hash so duplicate rules can't be
added.

Signed-off-by: Amy Griffis <[EMAIL PROTECTED]>

---

 kernel/auditfilter.c |   52 +++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 41 insertions(+), 11 deletions(-)

745105541b430c90127a2b7ad1806d995fd793b0
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index d53a80d..3cedc73 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -880,6 +880,37 @@ static void audit_inotify_unregister(str
        }
 }
 
+/* Find an existing audit rule.
+ * Caller must hold audit_filter_mutex to prevent stale rule data. */
+static struct audit_entry *audit_find_rule(struct audit_entry *entry,
+                                          struct list_head *list)
+{
+       struct audit_entry *e, *found = NULL;
+       int h;
+
+       if (entry->rule.watch) {
+               /* we don't know the inode number, so must walk entire hash */
+               for (h = 0; h < AUDIT_INODE_BUCKETS; h++) {
+                       list = &audit_inode_hash[h];
+                       list_for_each_entry(e, list, list)
+                               if (!audit_compare_rule(&entry->rule, 
&e->rule)) {
+                                       found = e;
+                                       goto out;
+                               }
+               }
+               goto out;
+       }
+
+       list_for_each_entry(e, list, list)
+               if (!audit_compare_rule(&entry->rule, &e->rule)) {
+                       found = e;
+                       goto out;
+               }
+
+out:
+       return found;
+}
+
 /* Get path information necessary for adding watches. */
 static int audit_get_nd(char *path, struct nameidata **ndp,
                        struct nameidata **ndw)
@@ -1017,16 +1048,18 @@ static inline int audit_add_rule(struct 
        struct nameidata *ndp, *ndw;
        int h, err, putnd_needed = 0;
 
-       /* Taking audit_filter_mutex protects from stale rule data. */
-       mutex_lock(&audit_filter_mutex);
-       list_for_each_entry(e, list, list) {
-               if (!audit_compare_rule(&entry->rule, &e->rule)) {
-                       err = -EEXIST;
-                       mutex_unlock(&audit_filter_mutex);
-                       goto error;
-               }
+       if (inode_f) {
+               h = audit_hash_ino(inode_f->val);
+               list = &audit_inode_hash[h];
        }
+
+       mutex_lock(&audit_filter_mutex);
+       e = audit_find_rule(entry, list);
        mutex_unlock(&audit_filter_mutex);
+       if (e) {
+               err = -EEXIST;
+               goto error;
+       }
 
        /* Avoid calling path_lookup under audit_filter_mutex. */
        if (watch) {
@@ -1046,9 +1079,6 @@ static inline int audit_add_rule(struct 
                }
                h = audit_hash_ino((u32)watch->ino);
                list = &audit_inode_hash[h];
-       } else if (inode_f) {
-               h = audit_hash_ino(inode_f->val);
-               list = &audit_inode_hash[h];
        }
 
        if (entry->rule.flags & AUDIT_FILTER_PREPEND) {
-- 
1.3.0

--
Linux-audit mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/linux-audit

Reply via email to