On Wednesday, December 14, 2011 08:18:30 PM Peter Moody wrote: > > Testing has revealed a couple of bugs in this. Fixing these and > > testing some more now. > > Ok, this should be the last one. I was apparently a little more tired > riding the shuttle home than I thought I was. The patch last night was > missing a break and a number of the AUDIT_COMPARE_* fields were plain > wrong. > > This one tests good to me though.
This patch + some changes and additions has been applied. https://fedorahosted.org/audit/changeset/642 If I could go back in time, I would have suggested using a bitmap for left and right side so we could avoid the big switch/case constructs. But it works fine the way it is. :) -Steve > Signed-off-by: Peter Moody <[email protected]> > --- > trunk/auparse/typetab.h | 2 + > trunk/lib/errormsg.h | 7 +- > trunk/lib/fieldtab.h | 3 + > trunk/lib/libaudit.c | 303 > +++++++++++++++++++++++++++++++++++++++++++ trunk/lib/libaudit.h | > 2 + > trunk/src/auditctl.c | 19 +++- > trunk/src/ausearch-report.c | 1 + > 7 files changed, 334 insertions(+), 3 deletions(-) > > diff --git a/trunk/auparse/typetab.h b/trunk/auparse/typetab.h > index 746573c..cf13f4d 100644 > --- a/trunk/auparse/typetab.h > +++ b/trunk/auparse/typetab.h > @@ -32,6 +32,8 @@ _S(AUPARSE_TYPE_UID, "iuid" ) > _S(AUPARSE_TYPE_UID, "id" ) > _S(AUPARSE_TYPE_UID, "inode_uid" ) > _S(AUPARSE_TYPE_UID, "sauid" ) > +_S(AUPARSE_TYPE_UID, "obj_uid" ) > +_S(AUPARSE_TYPE_UID, "obj_gid" ) > _S(AUPARSE_TYPE_GID, "gid" ) > _S(AUPARSE_TYPE_GID, "egid" ) > _S(AUPARSE_TYPE_GID, "sgid" ) > diff --git a/trunk/lib/errormsg.h b/trunk/lib/errormsg.h > index fd6b1c0..a7bc61d 100644 > --- a/trunk/lib/errormsg.h > +++ b/trunk/lib/errormsg.h > @@ -54,5 +54,10 @@ static const struct msg_tab err_msgtab[] = { > { -19, 0, "Key field needs a watch or syscall given prior to it" > }, { -20, 2, "-F missing value after operation for" }, > { -21, 2, "-F value should be number for" }, > - { -22, 2, "-F missing field name before operator for" } > + { -22, 2, "-F missing field name before operator for" }, > + { -23, 2, "-C missng operation for "}, > + { -24, 2, "-C missing field name before operator for" }, > + { -25, 2, "-C missing value after operation for "}, > + { -26, 2, "-C unknown field:" }, > + { -27, 2, "-C unknown right hand value for comparison with:" }, > }; > diff --git a/trunk/lib/fieldtab.h b/trunk/lib/fieldtab.h > index ad95814..c0432cc 100644 > --- a/trunk/lib/fieldtab.h > +++ b/trunk/lib/fieldtab.h > @@ -55,6 +55,8 @@ _S(AUDIT_WATCH, "path" ) > _S(AUDIT_PERM, "perm" ) > _S(AUDIT_DIR, "dir" ) > _S(AUDIT_FILETYPE, "filetype" ) > +_S(AUDIT_OBJ_UID, "obj_uid" ) > +_S(AUDIT_OBJ_GID, "obj_gid" ) > > _S(AUDIT_ARG0, "a0" ) > _S(AUDIT_ARG1, "a1" ) > @@ -63,3 +65,4 @@ _S(AUDIT_ARG3, "a3" ) > > _S(AUDIT_FILTERKEY, "key" ) > > +_S(AUDIT_FIELD_COMPARE, "field_compare" ) > diff --git a/trunk/lib/libaudit.c b/trunk/lib/libaudit.c > index 9a5070c..b179b5c 100644 > --- a/trunk/lib/libaudit.c > +++ b/trunk/lib/libaudit.c > @@ -783,6 +783,307 @@ int audit_rule_syscallbyname_data(struct > audit_rule_data *rule, > } > hidden_def(audit_rule_syscallbyname_data) > > +int audit_rule_interfield_fieldpair_data(struct audit_rule_data **rulep, > + const char *pair, > + int flags) { > + const char *f = pair; > + char *v; > + int op; > + int field1, field2; > + int vlen; > + int offset; > + struct audit_rule_data *rule = *rulep; > + > + if (f == NULL) > + return -1; > + > + /* look for 2-char operators first > + then look for 1-char operators afterwards > + when found, null out the bytes under the operators to split > + and set value pointer just past operator bytes > + */ > + if ( (v = strstr(pair, "!=")) ) { > + *v++ = '\0'; > + *v++ = '\0'; > + op = AUDIT_NOT_EQUAL; > + } else if ( (v = strstr(pair, "=")) ) { > + *v++ = '\0'; > + op = AUDIT_EQUAL; > + } else { > + return -13; > + } > + > + if (v == NULL) > + return -23; > + > + if (*f == 0) > + return -24; > + > + if (*v == 0) > + return -25; > + > + if ((field1 = audit_name_to_field(f)) < 0) > + return -26; > + > + if ((field2 = audit_name_to_field(v)) < 0) > + return -27; > + > + /* Exclude filter can be used only with MSGTYPE field */ > + if (flags == AUDIT_FILTER_EXCLUDE && field1 != AUDIT_MSGTYPE) > + return -12; > + > + // It should always be AUDIT_FIELD_COMPARE > + rule->fields[rule->field_count] = AUDIT_FIELD_COMPARE; > + rule->fieldflags[rule->field_count] = op; > + /* oh god, so many permutations */ > + switch (field1) > + { > + /* UID comparison */ > + case AUDIT_EUID: > + switch(field2) { > + case AUDIT_LOGINUID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_AUID_TO_EUID; > + break; > + case AUDIT_FSUID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_EUID_TO_FSUID; > + break; > + case AUDIT_OBJ_UID: > + rule->values[rule->field_count] = AUDIT_COMPARE_EUID_TO_OBJ_UID; > + break; > + case AUDIT_SUID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_EUID_TO_SUID; > + break; > + case AUDIT_UID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_UID_TO_EUID; > + break; > + default: > + return -1; > + } > + break; > + case AUDIT_FSUID: > + switch(field2) { > + case AUDIT_LOGINUID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_AUID_TO_FSUID; > + break; > + case AUDIT_EUID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_EUID_TO_FSUID; > + break; > + case AUDIT_OBJ_UID: > + rule->values[rule->field_count] = AUDIT_COMPARE_FSUID_TO_OBJ_UID; > + break; > + case AUDIT_SUID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_SUID_TO_FSUID; > + break; > + case AUDIT_UID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_UID_TO_FSUID; > + break; > + default: > + return -1; > + } > + break; > + case AUDIT_LOGINUID: > + switch(field2) { > + case AUDIT_EUID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_AUID_TO_EUID; > + break; > + case AUDIT_FSUID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_AUID_TO_FSUID; > + break; > + case AUDIT_OBJ_UID: > + rule->values[rule->field_count] = AUDIT_COMPARE_AUID_TO_OBJ_UID; > + break; > + case AUDIT_SUID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_AUID_TO_SUID; > + break; > + case AUDIT_UID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_UID_TO_AUID; > + break; > + default: > + return -1; > + } > + break; > + case AUDIT_SUID: > + switch(field2) { > + case AUDIT_LOGINUID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_AUID_TO_SUID; > + break; > + case AUDIT_EUID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_EUID_TO_SUID; > + break; > + case AUDIT_FSUID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_SUID_TO_FSUID; > + break; > + case AUDIT_OBJ_UID: > + rule->values[rule->field_count] = AUDIT_COMPARE_SUID_TO_OBJ_UID; > + break; > + case AUDIT_UID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_UID_TO_SUID; > + break; > + default: > + return -1; > + } > + break; > + case AUDIT_OBJ_UID: > + switch(field2) { > + case AUDIT_LOGINUID: > + rule->values[rule->field_count] = AUDIT_COMPARE_AUID_TO_OBJ_UID; > + break; > + case AUDIT_EUID: > + rule->values[rule->field_count] = AUDIT_COMPARE_EUID_TO_OBJ_UID; > + break; > + case AUDIT_FSUID: > + rule->values[rule->field_count] = AUDIT_COMPARE_FSUID_TO_OBJ_UID; > + break; > + case AUDIT_UID: > + rule->values[rule->field_count] = AUDIT_COMPARE_UID_TO_OBJ_UID; > + break; > + case AUDIT_SUID: > + rule->values[rule->field_count] = AUDIT_COMPARE_SUID_TO_OBJ_UID; > + break; > + default: > + return -1; > + } > + break; > + case AUDIT_UID: > + switch(field2) { > + case AUDIT_LOGINUID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_UID_TO_AUID; > + break; > + case AUDIT_EUID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_UID_TO_EUID; > + break; > + case AUDIT_FSUID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_UID_TO_FSUID; > + break; > + case AUDIT_OBJ_UID: > + rule->values[rule->field_count] = AUDIT_COMPARE_UID_TO_OBJ_UID; > + break; > + case AUDIT_SUID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_UID_TO_SUID; > + break; > + default: > + return -1; > + } > + break; > + > + /* GID comparisons */ > + case AUDIT_EGID: > + switch(field2) { > + case AUDIT_FSGID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_EGID_TO_FSGID; > + break; > + case AUDIT_GID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_GID_TO_EGID; > + break; > + case AUDIT_OBJ_GID: > + rule->values[rule->field_count] = AUDIT_COMPARE_EGID_TO_OBJ_GID; > + break; > + case AUDIT_SGID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_EGID_TO_SGID; > + break; > + default: > + return -1; > + } > + break; > + case AUDIT_FSGID: > + switch(field2) { > + case AUDIT_SGID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_SGID_TO_FSGID; > + break; > + case AUDIT_GID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_GID_TO_FSGID; > + break; > + case AUDIT_OBJ_GID: > + rule->values[rule->field_count] = AUDIT_COMPARE_FSGID_TO_OBJ_GID; > + break; > + case AUDIT_EGID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_EGID_TO_FSGID; > + break; > + default: > + return -1; > + } > + break; > + case AUDIT_GID: > + switch(field2) { > + case AUDIT_EGID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_GID_TO_EGID; > + break; > + case AUDIT_FSGID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_GID_TO_FSGID; > + break; > + case AUDIT_OBJ_GID: > + rule->values[rule->field_count] = AUDIT_COMPARE_GID_TO_OBJ_GID; > + break; > + case AUDIT_SGID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_GID_TO_SGID; > + break; > + default: > + return -1; > + } > + break; > + case AUDIT_OBJ_GID: > + switch(field2) { > + case AUDIT_EGID: > + rule->values[rule->field_count] = AUDIT_COMPARE_EGID_TO_OBJ_GID; > + break; > + case AUDIT_FSGID: > + rule->values[rule->field_count] = AUDIT_COMPARE_FSGID_TO_OBJ_GID; > + break; > + case AUDIT_GID: > + rule->values[rule->field_count] = AUDIT_COMPARE_GID_TO_OBJ_GID; > + break; > + case AUDIT_SGID: > + rule->values[rule->field_count] = AUDIT_COMPARE_SGID_TO_OBJ_GID; > + break; > + default: > + return -1; > + } > + break; > + case AUDIT_SGID: > + switch(field2) { > + case AUDIT_FSGID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_SGID_TO_FSGID; > + break; > + case AUDIT_GID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_GID_TO_SGID; > + break; > + case AUDIT_OBJ_GID: > + rule->values[rule->field_count] = AUDIT_COMPARE_SGID_TO_OBJ_GID; > + break; > + case AUDIT_EGID: > + rule->values[rule->field_count] = > AUDIT_COMPARE_EGID_TO_SGID; > + break; > + default: > + return -1; > + } > + break; > + /* fallthrough */ > + default: > + if (field1 == AUDIT_INODE) { > + if (!(op == AUDIT_NOT_EQUAL || > + op == AUDIT_EQUAL)) > + return -13; > + } > + > + if (field1 == AUDIT_PPID && !(flags == AUDIT_FILTER_EXIT > + || flags == AUDIT_FILTER_ENTRY)) > + return -17; > + > + if (!isdigit((char)*(v))) > + return -21; > + > + if (field1 == AUDIT_INODE) > + rule->values[rule->field_count] = > + strtoul(v, NULL, 0); > + else > + rule->values[rule->field_count] = > + strtol(v, NULL, 0); > + break; > + } > + rule->field_count++; > + return 0; > +} > + > int audit_rule_fieldpair_data(struct audit_rule_data **rulep, const char > *pair, int flags) > { > @@ -857,6 +1158,8 @@ int audit_rule_fieldpair_data(struct > audit_rule_data **rulep, const char *pair, > case AUDIT_SUID: > case AUDIT_FSUID: > case AUDIT_LOGINUID: > + case AUDIT_OBJ_UID: > + case AUDIT_OBJ_GID: > // Do positive & negative separate for 32 bit systems > vlen = strlen(v); > if (isdigit((char)*(v))) > diff --git a/trunk/lib/libaudit.h b/trunk/lib/libaudit.h > index 8feaa39..911bce4 100644 > --- a/trunk/lib/libaudit.h > +++ b/trunk/lib/libaudit.h > @@ -428,6 +428,8 @@ extern int audit_rule_syscallbyname_data(struct > audit_rule_data *rule, > * adding new fields */ > extern int audit_rule_fieldpair_data(struct audit_rule_data **rulep, > const char *pair, int flags); > +extern int audit_rule_interfield_fieldpair_data(struct audit_rule_data > **rulep, + const char *pair, int flags); > extern void audit_rule_free_data(struct audit_rule_data *rule); > > #ifdef __cplusplus > diff --git a/trunk/src/auditctl.c b/trunk/src/auditctl.c > index 34b7935..d7ec998 100644 > --- a/trunk/src/auditctl.c > +++ b/trunk/src/auditctl.c > @@ -482,7 +482,7 @@ static int setopt(int count, int lineno, char *vars[]) > keylen = AUDIT_MAX_KEY_LEN; > > while ((retval >= 0) && (c = getopt(count, vars, > - "hislDvte:f:r:b:a:A:d:S:F:m:R:w:W:k:p:q:")) != EOF) { > + "hislDvtC:e:f:r:b:a:A:d:S:F:m:R:w:W:k:p:q:")) != EOF) { > int flags = AUDIT_FILTER_UNSET; > rc = 10; // Init to something impossible to see if unused. > switch (c) { > @@ -731,7 +731,6 @@ static int setopt(int count, int lineno, char *vars[]) > retval = -1; > break; > } > - > rc = audit_rule_fieldpair_data(&rule_new,optarg,flags); > if (rc != 0) { > audit_number_to_errmsg(rc, optarg); > @@ -743,6 +742,22 @@ static int setopt(int count, int lineno, char *vars[]) > } > > break; > + case 'C': > + if (add != AUDIT_FILTER_UNSET) > + flags = add & AUDIT_FILTER_MASK; > + else if (del != AUDIT_FILTER_UNSET) > + flags = del & AUDIT_FILTER_MASK; > + > + rc = audit_rule_interfield_fieldpair_data(&rule_new, optarg, > flags); > + if (rc != 0) { > + audit_number_to_errmsg(rc, optarg); > + retval = -1; > + } else { > + if (rule_new->fields[rule_new->field_count - 1] == > + AUDIT_PERM) > + audit_permadded = 1; > + } > + break; > case 'm': > if (count > 3) { > fprintf(stderr, > diff --git a/trunk/src/ausearch-report.c b/trunk/src/ausearch-report.c > index d50c732..62e1ae0 100644 > --- a/trunk/src/ausearch-report.c > +++ b/trunk/src/ausearch-report.c > @@ -333,6 +333,7 @@ static struct nv_pair typetab[] = { > {T_UID, "id"}, > {T_UID, "inode_uid"}, > {T_UID, "sauid"}, > + {T_UID, "obj_uid"}, > {T_GID, "gid"}, > {T_GID, "egid"}, > {T_GID, "sgid"}, -- Linux-audit mailing list [email protected] https://www.redhat.com/mailman/listinfo/linux-audit
