Errors from filter user rules were previously ignored, and worse, an error on
a AUDIT_NEVER rule disabled logging on that rule.  On -ESTALE, retry up to 5
times.  On error on AUDIT_NEVER rules, log.

Signed-off-by: Richard Guy Briggs <[email protected]>
---
 kernel/audit.c       |    2 +-
 kernel/auditfilter.c |   44 +++++++++++++++++++++++++++++++-------------
 2 files changed, 32 insertions(+), 14 deletions(-)

diff --git a/kernel/audit.c b/kernel/audit.c
index 4cbc945..c93cf06 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -706,7 +706,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct 
nlmsghdr *nlh)
                        return 0;
 
                err = audit_filter_user(msg_type);
-               if (err == 1) {
+               if (err) { /* match or error */
                        err = 0;
                        if (msg_type == AUDIT_USER_TTY) {
                                err = tty_audit_push_current();
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index b4c6e03..1a7dfa5 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -1272,8 +1272,8 @@ static int audit_filter_user_rules(struct audit_krule 
*rule, int type,
                        break;
                }
 
-               if (!result)
-                       return 0;
+               if (result <= 0)
+                       return result;
        }
        switch (rule->action) {
        case AUDIT_NEVER:    *state = AUDIT_DISABLED;       break;
@@ -1286,19 +1286,37 @@ int audit_filter_user(int type)
 {
        enum audit_state state = AUDIT_DISABLED;
        struct audit_entry *e;
-       int ret = 1;
-
-       rcu_read_lock();
-       list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) 
{
-               if (audit_filter_user_rules(&e->rule, type, &state)) {
-                       if (state == AUDIT_DISABLED)
-                               ret = 0;
-                       break;
+       int rc, count = 0, retry = 0, ret = 1; /* Audit by default */
+#define FILTER_RETRY_LIMIT 5
+
+       do {
+               rcu_read_lock();
+               list_for_each_entry_rcu(e,
+                                       &audit_filter_list[AUDIT_FILTER_USER],
+                                       list) {
+                       retry = 0;
+                       rc = audit_filter_user_rules(&e->rule, type, &state);
+                       if (rc > 0) {
+                               if (state == AUDIT_DISABLED)
+                                       ret = 0;
+                               break;
+                       } else if (rc < 0) {
+                               if (rc == -ESTALE && count < 
FILTER_RETRY_LIMIT) {
+                                       rcu_read_unlock();
+                                       count++;
+                                       retry = 1;
+                                       cond_resched();
+                               } else {
+                                       ret = rc;
+                               }
+                               break;
+                       }
                }
-       }
-       rcu_read_unlock();
+               if (!retry)
+                       rcu_read_unlock();
+       } while (retry);
 
-       return ret; /* Audit by default */
+       return ret;
 }
 
 int audit_filter_type(int type)
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to