audit: make validity checking generic
authorEric Paris <eparis@redhat.com>
Tue, 16 Apr 2013 21:26:51 +0000 (17:26 -0400)
committerEric Paris <eparis@redhat.com>
Tue, 30 Apr 2013 19:31:28 +0000 (15:31 -0400)
We have 2 interfaces to send audit rules.  Rather than check validity of
things in 2 places make a helper function.

Signed-off-by: Eric Paris <eparis@redhat.com>
kernel/auditfilter.c

index 9e666004e0dc052a8d0417923fa9ab6091aa18ea..ff6e09d89278fc853dc09d413e1c1024ec56f2ff 100644 (file)
@@ -310,7 +310,7 @@ static u32 audit_to_op(u32 op)
        return n;
 }
 
-/* check if a field is valid for a given list */
+/* check if an audit field is valid */
 static int audit_field_valid(struct audit_entry *entry, struct audit_field *f)
 {
        switch(f->type) {
@@ -320,6 +320,69 @@ static int audit_field_valid(struct audit_entry *entry, struct audit_field *f)
                        return -EINVAL;
                break;
        };
+
+       switch(f->type) {
+       default:
+               return -EINVAL;
+       case AUDIT_UID:
+       case AUDIT_EUID:
+       case AUDIT_SUID:
+       case AUDIT_FSUID:
+       case AUDIT_LOGINUID:
+       case AUDIT_OBJ_UID:
+       case AUDIT_GID:
+       case AUDIT_EGID:
+       case AUDIT_SGID:
+       case AUDIT_FSGID:
+       case AUDIT_OBJ_GID:
+       case AUDIT_PID:
+       case AUDIT_PERS:
+       case AUDIT_MSGTYPE:
+       case AUDIT_PPID:
+       case AUDIT_DEVMAJOR:
+       case AUDIT_DEVMINOR:
+       case AUDIT_EXIT:
+       case AUDIT_SUCCESS:
+               /* bit ops are only useful on syscall args */
+               if (f->op == Audit_bitmask || f->op == Audit_bittest)
+                       return -EINVAL;
+               break;
+       case AUDIT_ARG0:
+       case AUDIT_ARG1:
+       case AUDIT_ARG2:
+       case AUDIT_ARG3:
+       case AUDIT_SUBJ_USER:
+       case AUDIT_SUBJ_ROLE:
+       case AUDIT_SUBJ_TYPE:
+       case AUDIT_SUBJ_SEN:
+       case AUDIT_SUBJ_CLR:
+       case AUDIT_OBJ_USER:
+       case AUDIT_OBJ_ROLE:
+       case AUDIT_OBJ_TYPE:
+       case AUDIT_OBJ_LEV_LOW:
+       case AUDIT_OBJ_LEV_HIGH:
+       case AUDIT_WATCH:
+       case AUDIT_DIR:
+       case AUDIT_FILTERKEY:
+               break;
+       /* arch is only allowed to be = or != */
+       case AUDIT_ARCH:
+               if (f->op != Audit_not_equal && f->op != Audit_equal)
+                       return -EINVAL;
+               break;
+       case AUDIT_PERM:
+               if (f->val & ~15)
+                       return -EINVAL;
+               break;
+       case AUDIT_FILETYPE:
+               if (f->val & ~S_IFMT)
+                       return -EINVAL;
+               break;
+       case AUDIT_FIELD_COMPARE:
+               if (f->val > AUDIT_MAX_FIELD_COMPARE)
+                       return -EINVAL;
+               break;
+       };
        return 0;
 }
 
@@ -361,18 +424,17 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
                if (f->op == Audit_bad)
                        goto exit_free;
 
-               switch(f->type) {
-               default:
+               err = audit_field_valid(entry, f);
+               if (err)
                        goto exit_free;
+
+               err = -EINVAL;
+               switch (f->type) {
                case AUDIT_UID:
                case AUDIT_EUID:
                case AUDIT_SUID:
                case AUDIT_FSUID:
                case AUDIT_LOGINUID:
-                       /* bit ops not implemented for uid comparisons */
-                       if (f->op == Audit_bitmask || f->op == Audit_bittest)
-                               goto exit_free;
-
                        f->uid = make_kuid(current_user_ns(), f->val);
                        if (!uid_valid(f->uid))
                                goto exit_free;
@@ -381,45 +443,13 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
                case AUDIT_EGID:
                case AUDIT_SGID:
                case AUDIT_FSGID:
-                       /* bit ops not implemented for gid comparisons */
-                       if (f->op == Audit_bitmask || f->op == Audit_bittest)
-                               goto exit_free;
-
                        f->gid = make_kgid(current_user_ns(), f->val);
                        if (!gid_valid(f->gid))
                                goto exit_free;
                        break;
-               case AUDIT_PID:
-               case AUDIT_PERS:
-               case AUDIT_MSGTYPE:
-               case AUDIT_PPID:
-               case AUDIT_DEVMAJOR:
-               case AUDIT_DEVMINOR:
-               case AUDIT_EXIT:
-               case AUDIT_SUCCESS:
-                       /* bit ops are only useful on syscall args */
-                       if (f->op == Audit_bitmask || f->op == Audit_bittest)
-                               goto exit_free;
-                       break;
-               case AUDIT_ARG0:
-               case AUDIT_ARG1:
-               case AUDIT_ARG2:
-               case AUDIT_ARG3:
-                       break;
-               /* arch is only allowed to be = or != */
                case AUDIT_ARCH:
-                       if (f->op != Audit_not_equal && f->op != Audit_equal)
-                               goto exit_free;
                        entry->rule.arch_f = f;
                        break;
-               case AUDIT_PERM:
-                       if (f->val & ~15)
-                               goto exit_free;
-                       break;
-               case AUDIT_FILETYPE:
-                       if (f->val & ~S_IFMT)
-                               goto exit_free;
-                       break;
                case AUDIT_INODE:
                        err = audit_to_inode(&entry->rule, f);
                        if (err)
@@ -477,18 +507,13 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                        goto exit_free;
 
                err = -EINVAL;
-
-               switch(f->type) {
+               switch (f->type) {
                case AUDIT_UID:
                case AUDIT_EUID:
                case AUDIT_SUID:
                case AUDIT_FSUID:
                case AUDIT_LOGINUID:
                case AUDIT_OBJ_UID:
-                       /* bit ops not implemented for uid comparisons */
-                       if (f->op == Audit_bitmask || f->op == Audit_bittest)
-                               goto exit_free;
-
                        f->uid = make_kuid(current_user_ns(), f->val);
                        if (!uid_valid(f->uid))
                                goto exit_free;
@@ -498,27 +523,10 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                case AUDIT_SGID:
                case AUDIT_FSGID:
                case AUDIT_OBJ_GID:
-                       /* bit ops not implemented for gid comparisons */
-                       if (f->op == Audit_bitmask || f->op == Audit_bittest)
-                               goto exit_free;
-
                        f->gid = make_kgid(current_user_ns(), f->val);
                        if (!gid_valid(f->gid))
                                goto exit_free;
                        break;
-               case AUDIT_PID:
-               case AUDIT_PERS:
-               case AUDIT_MSGTYPE:
-               case AUDIT_PPID:
-               case AUDIT_DEVMAJOR:
-               case AUDIT_DEVMINOR:
-               case AUDIT_EXIT:
-               case AUDIT_SUCCESS:
-               case AUDIT_ARG0:
-               case AUDIT_ARG1:
-               case AUDIT_ARG2:
-               case AUDIT_ARG3:
-                       break;
                case AUDIT_ARCH:
                        entry->rule.arch_f = f;
                        break;
@@ -589,20 +597,6 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                        entry->rule.buflen += f->val;
                        entry->rule.filterkey = str;
                        break;
-               case AUDIT_PERM:
-                       if (f->val & ~15)
-                               goto exit_free;
-                       break;
-               case AUDIT_FILETYPE:
-                       if (f->val & ~S_IFMT)
-                               goto exit_free;
-                       break;
-               case AUDIT_FIELD_COMPARE:
-                       if (f->val > AUDIT_MAX_FIELD_COMPARE)
-                               goto exit_free;
-                       break;
-               default:
-                       goto exit_free;
                }
        }