audit: add fields to exclude filter by reusing user filter
authorRichard Guy Briggs <rgb@redhat.com>
Fri, 24 Jun 2016 20:35:46 +0000 (16:35 -0400)
committerPaul Moore <paul@paul-moore.com>
Mon, 27 Jun 2016 15:01:00 +0000 (11:01 -0400)
RFE: add additional fields for use in audit filter exclude rules
https://github.com/linux-audit/audit-kernel/issues/5

Re-factor and combine audit_filter_type() with audit_filter_user() to
use audit_filter_user_rules() to enable the exclude filter to
additionally filter on PID, UID, GID, AUID, LOGINUID_SET, SUBJ_*.

The process of combining the similar audit_filter_user() and
audit_filter_type() functions, required inverting the meaning and
including the ALWAYS action of the latter.

Include audit_filter_user_rules() into audit_filter(), removing
unneeded logic in the process.

Keep the check to quit early if the list is empty.

Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
[PM: checkpatch.pl fixes - whitespace damage, wrapped description]
Signed-off-by: Paul Moore <paul@paul-moore.com>
include/linux/audit.h
kernel/audit.c
kernel/audit.h
kernel/auditfilter.c

index e38e3fc13ea8764a66d4c84a6dea1bee3f4e630b..9d4443f93db6b1568baa5bd1066b66cf6885484d 100644 (file)
@@ -163,8 +163,6 @@ extern void audit_log_task_info(struct audit_buffer *ab,
 extern int                 audit_update_lsm_rules(void);
 
                                /* Private API (for audit.c only) */
-extern int audit_filter_user(int type);
-extern int audit_filter_type(int type);
 extern int audit_rule_change(int type, __u32 portid, int seq,
                                void *data, size_t datasz);
 extern int audit_list_rules_send(struct sk_buff *request_skb, int seq);
index 678c3f000191be66aed944e764209ef5c2924b98..994588ef9489a8fdc72a4f9feefbd40a9dacbee3 100644 (file)
@@ -934,7 +934,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                if (!audit_enabled && msg_type != AUDIT_USER_AVC)
                        return 0;
 
-               err = audit_filter_user(msg_type);
+               err = audit_filter(msg_type, AUDIT_FILTER_USER);
                if (err == 1) { /* match or error */
                        err = 0;
                        if (msg_type == AUDIT_USER_TTY) {
@@ -1382,7 +1382,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
        if (audit_initialized != AUDIT_INITIALIZED)
                return NULL;
 
-       if (unlikely(audit_filter_type(type)))
+       if (unlikely(!audit_filter(type, AUDIT_FILTER_TYPE)))
                return NULL;
 
        if (gfp_mask & __GFP_DIRECT_RECLAIM) {
index cbbe6bb6496ea934f86ffcfedffe971c76bbb692..1879f02cb2c35c653deb9e4dffeb8a166135629c 100644 (file)
@@ -327,6 +327,8 @@ extern pid_t audit_sig_pid;
 extern kuid_t audit_sig_uid;
 extern u32 audit_sig_sid;
 
+extern int audit_filter(int msgtype, unsigned int listtype);
+
 #ifdef CONFIG_AUDITSYSCALL
 extern int __audit_signal_info(int sig, struct task_struct *t);
 static inline int audit_signal_info(int sig, struct task_struct *t)
index ff59a5eed691763063249fff5ad39398150c2f23..85d9cac497e4602e76389c8d56d274372a31c0aa 100644 (file)
@@ -1290,117 +1290,72 @@ int audit_compare_dname_path(const char *dname, const char *path, int parentlen)
        return strncmp(p, dname, dlen);
 }
 
-static int audit_filter_user_rules(struct audit_krule *rule, int type,
-                                  enum audit_state *state)
-{
-       int i;
-
-       for (i = 0; i < rule->field_count; i++) {
-               struct audit_field *f = &rule->fields[i];
-               pid_t pid;
-               int result = 0;
-               u32 sid;
-
-               switch (f->type) {
-               case AUDIT_PID:
-                       pid = task_pid_nr(current);
-                       result = audit_comparator(pid, f->op, f->val);
-                       break;
-               case AUDIT_UID:
-                       result = audit_uid_comparator(current_uid(), f->op, f->uid);
-                       break;
-               case AUDIT_GID:
-                       result = audit_gid_comparator(current_gid(), f->op, f->gid);
-                       break;
-               case AUDIT_LOGINUID:
-                       result = audit_uid_comparator(audit_get_loginuid(current),
-                                                 f->op, f->uid);
-                       break;
-               case AUDIT_LOGINUID_SET:
-                       result = audit_comparator(audit_loginuid_set(current),
-                                                 f->op, f->val);
-                       break;
-               case AUDIT_MSGTYPE:
-                       result = audit_comparator(type, f->op, f->val);
-                       break;
-               case AUDIT_SUBJ_USER:
-               case AUDIT_SUBJ_ROLE:
-               case AUDIT_SUBJ_TYPE:
-               case AUDIT_SUBJ_SEN:
-               case AUDIT_SUBJ_CLR:
-                       if (f->lsm_rule) {
-                               security_task_getsecid(current, &sid);
-                               result = security_audit_rule_match(sid,
-                                                                  f->type,
-                                                                  f->op,
-                                                                  f->lsm_rule,
-                                                                  NULL);
-                       }
-                       break;
-               }
-
-               if (result <= 0)
-                       return result;
-       }
-       switch (rule->action) {
-       case AUDIT_NEVER:
-               *state = AUDIT_DISABLED;
-               break;
-       case AUDIT_ALWAYS:
-               *state = AUDIT_RECORD_CONTEXT;
-               break;
-       }
-       return 1;
-}
-
-int audit_filter_user(int type)
-{
-       enum audit_state state = AUDIT_DISABLED;
-       struct audit_entry *e;
-       int rc, ret;
-
-       ret = 1; /* Audit by default */
-
-       rcu_read_lock();
-       list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) {
-               rc = audit_filter_user_rules(&e->rule, type, &state);
-               if (rc) {
-                       if (rc > 0 && state == AUDIT_DISABLED)
-                               ret = 0;
-                       break;
-               }
-       }
-       rcu_read_unlock();
-
-       return ret;
-}
-
-int audit_filter_type(int type)
+int audit_filter(int msgtype, unsigned int listtype)
 {
        struct audit_entry *e;
-       int result = 0;
+       int ret = 1; /* Audit by default */
 
        rcu_read_lock();
-       if (list_empty(&audit_filter_list[AUDIT_FILTER_TYPE]))
+       if (list_empty(&audit_filter_list[listtype]))
                goto unlock_and_return;
+       list_for_each_entry_rcu(e, &audit_filter_list[listtype], list) {
+               int i, result = 0;
 
-       list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TYPE],
-                               list) {
-               int i;
                for (i = 0; i < e->rule.field_count; i++) {
                        struct audit_field *f = &e->rule.fields[i];
-                       if (f->type == AUDIT_MSGTYPE) {
-                               result = audit_comparator(type, f->op, f->val);
-                               if (!result)
-                                       break;
+                       pid_t pid;
+                       u32 sid;
+
+                       switch (f->type) {
+                       case AUDIT_PID:
+                               pid = task_pid_nr(current);
+                               result = audit_comparator(pid, f->op, f->val);
+                               break;
+                       case AUDIT_UID:
+                               result = audit_uid_comparator(current_uid(), f->op, f->uid);
+                               break;
+                       case AUDIT_GID:
+                               result = audit_gid_comparator(current_gid(), f->op, f->gid);
+                               break;
+                       case AUDIT_LOGINUID:
+                               result = audit_uid_comparator(audit_get_loginuid(current),
+                                                             f->op, f->uid);
+                               break;
+                       case AUDIT_LOGINUID_SET:
+                               result = audit_comparator(audit_loginuid_set(current),
+                                                         f->op, f->val);
+                               break;
+                       case AUDIT_MSGTYPE:
+                               result = audit_comparator(msgtype, f->op, f->val);
+                               break;
+                       case AUDIT_SUBJ_USER:
+                       case AUDIT_SUBJ_ROLE:
+                       case AUDIT_SUBJ_TYPE:
+                       case AUDIT_SUBJ_SEN:
+                       case AUDIT_SUBJ_CLR:
+                               if (f->lsm_rule) {
+                                       security_task_getsecid(current, &sid);
+                                       result = security_audit_rule_match(sid,
+                                                       f->type, f->op, f->lsm_rule, NULL);
+                               }
+                               break;
+                       default:
+                               goto unlock_and_return;
                        }
+                       if (result < 0) /* error */
+                               goto unlock_and_return;
+                       if (!result)
+                               break;
+               }
+               if (result > 0) {
+                       if (e->rule.action == AUDIT_NEVER || listtype == AUDIT_FILTER_TYPE)
+                               ret = 0;
+                       break;
                }
-               if (result)
-                       goto unlock_and_return;
        }
 unlock_and_return:
        rcu_read_unlock();
-       return result;
+       return ret;
 }
 
 static int update_lsm_rule(struct audit_krule *r)