* test patch for auditctl inter-field comparisons on euid/uid, egid/gid
@ 2011-12-11 19:09 Peter Moody
2011-12-12 14:40 ` Steve Grubb
0 siblings, 1 reply; 11+ messages in thread
From: Peter Moody @ 2011-12-11 19:09 UTC (permalink / raw)
To: linux-audit
[-- Attachment #1.1: Type: text/plain, Size: 9158 bytes --]
This patch extends Eric's test patch from 11/17 (
http://www.redhat.com/archives/linux-audit/2011-November/msg00045.html).
This turns -C into a long opt with similar syntax to -F.
This allows uid/euid and gid/egid to be compared, like
auditctl -a exit,always -F arch=b64 -C 'euid!=uid' -S execve -F 'euid!=0'
-F 'success=1'
which would audit on someone executing a setuid binary if the binary isn't
setuid root.
You can also check for writes to overly permissive files like
auditctl -a exit,always -F arch=b64 -C 'obj_uid!=uid' -F 'uid!=0' -F
'dir=/home/' -F 'success=1' -S open -F 'a2&=2'
This functionality is helpful in detecting user compromises across a shared
fleet; eg, attacker finds a world-writable shell script
(/home/victim/.bashrc, it's happened...) and inserts "cp /bin/bash /tmp/;
chmod 7777 /tmp/bash". After victim executes this, attacker executes
/tmp/bash -p and becomes victim.
One strange thing related to this patch: auditd seems to be reporting
success for a normal user process (gklrellm) opening /proc/meminfo (mode
444) O_RDWR, and I don't see how this is possible. eg:
type=SYSCALL msg=audit(1323540255.146:97): arch=c000003e syscall=2
success=yes exit=13 a0=4b1972 a1=0 a2=1b6 a3=0 items=1 ppid=1704 pid=1797
auid=11532 uid=11532 gid=5000 euid=11532 suid=11532 fsuid=11532 egid=5000
sgid=5000 fsgid=5000 tty=(none) ses=1 comm="gkrellm" exe="/usr/bin/gkrellm"
key="permissive"
type=CWD msg=audit(1323540255.146:97): cwd="/home/pmoody"
type=PATH msg=audit(1323540255.146:97): item=0 name="/proc/meminfo" inode=
4026532008 dev=00:03 mode=0100444 ouid=0 ogid=0 rdev=00:00
hopefully someone with more auditd internal knowledge can explain what's
going on.
auditctl -l doesn't know how to report this yet; if this patch is generally
acceptable, I can try to fix that and update the manpage, etc.
Signed-off-by: Peter Moody <pmoody@google.com>
---
trunk/auparse/typetab.h | 1 +
trunk/lib/fieldtab.h | 1 +
trunk/lib/libaudit.c | 144
+++++++++++++++++++++++++++++++++++++++++++
trunk/lib/libaudit.h | 2 +
trunk/src/auditctl.c | 19 +++++-
trunk/src/ausearch-report.c | 1 +
6 files changed, 166 insertions(+), 2 deletions(-)
diff --git a/trunk/auparse/typetab.h b/trunk/auparse/typetab.h
index 746573c..3e6c6d1 100644
--- a/trunk/auparse/typetab.h
+++ b/trunk/auparse/typetab.h
@@ -32,6 +32,7 @@ _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_GID, "gid" )
_S(AUPARSE_TYPE_GID, "egid" )
_S(AUPARSE_TYPE_GID, "sgid" )
diff --git a/trunk/lib/fieldtab.h b/trunk/lib/fieldtab.h
index ad95814..e053df6 100644
--- a/trunk/lib/fieldtab.h
+++ b/trunk/lib/fieldtab.h
@@ -55,6 +55,7 @@ _S(AUDIT_WATCH, "path" )
_S(AUDIT_PERM, "perm" )
_S(AUDIT_DIR, "dir" )
_S(AUDIT_FILETYPE, "filetype" )
+_S(AUDIT_OBJ_UID, "obj_uid" )
_S(AUDIT_ARG0, "a0" )
_S(AUDIT_ARG1, "a1" )
diff --git a/trunk/lib/libaudit.c b/trunk/lib/libaudit.c
index 9a5070c..b10f984 100644
--- a/trunk/lib/libaudit.c
+++ b/trunk/lib/libaudit.c
@@ -783,6 +783,148 @@ 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 {
+ fprintf(stderr, "only =, != comparisons are allowed in interfield\n");
+ return -1;
+ }
+
+ if (v == NULL)
+ return -1;
+
+ if (*f == 0)
+ return -22;
+
+ if (*v == 0)
+ return -20;
+
+ if ((field1 = audit_name_to_field(f)) < 0)
+ return -2;
+
+ if ((field2 = audit_name_to_field(v)) < 0)
+ return -2;
+
+ /* 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;
+ switch (field1)
+ {
+ case AUDIT_UID:
+ switch(field2) {
+ case AUDIT_EUID:
+ rule->values[rule->field_count] = AUDIT_COMPARE_UID_TO_EUID;
+ break;
+ case AUDIT_OBJ_UID:
+ rule->values[rule->field_count] = AUDIT_COMPARE_UID_TO_OBJ_UID;
+ break;
+ default:
+ return -1;
+ }
+ break;
+ case AUDIT_EUID:
+ switch(field2) {
+ case AUDIT_UID:
+ rule->values[rule->field_count] = AUDIT_COMPARE_UID_TO_EUID;
+ break;
+ default:
+ return -1;
+ }
+ break;
+ case AUDIT_OBJ_UID:
+ switch(field2) {
+ case AUDIT_UID:
+ rule->values[rule->field_count] = AUDIT_COMPARE_UID_TO_OBJ_UID;
+ break;
+ default:
+ return -1;
+ }
+ break;
+ case AUDIT_OBJ_GID:
+ switch(field2) {
+ case AUDIT_GID:
+ rule->values[rule->field_count] = AUDIT_COMPARE_GID_TO_OBJ_GID;
+ 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_OBJ_GID:
+ rule->values[rule->field_count] = AUDIT_COMPARE_GID_TO_OBJ_GID;
+ break;
+ default:
+ return -1;
+ }
+ break;
+ case AUDIT_EGID:
+ switch(field2) {
+ case AUDIT_OBJ_GID:
+ rule->values[rule->field_count] = AUDIT_COMPARE_GID_TO_EGID;
+ 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 +999,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"},
--
1.7.3.1
--
Peter Moody Google 1.650.253.7306
Security Engineer pgp:0xC3410038
[-- Attachment #1.2: Type: text/html, Size: 25379 bytes --]
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: test patch for auditctl inter-field comparisons on euid/uid, egid/gid
2011-12-11 19:09 test patch for auditctl inter-field comparisons on euid/uid, egid/gid Peter Moody
@ 2011-12-12 14:40 ` Steve Grubb
2011-12-12 16:40 ` Peter Moody
0 siblings, 1 reply; 11+ messages in thread
From: Steve Grubb @ 2011-12-12 14:40 UTC (permalink / raw)
To: linux-audit
On Sunday, December 11, 2011 02:09:27 PM Peter Moody wrote:
> This patch extends Eric's test patch from 11/17 (
> http://www.redhat.com/archives/linux-audit/2011-November/msg00045.html).
> This turns -C into a long opt with similar syntax to -F.
Thanks.
> One strange thing related to this patch: auditd seems to be reporting
> success for a normal user process (gklrellm) opening /proc/meminfo (mode
> 444) O_RDWR, and I don't see how this is possible. eg:
>
> type=SYSCALL msg=audit(1323540255.146:97): arch=c000003e syscall=2
> success=yes exit=13 a0=4b1972 a1=0 a2=1b6 a3=0 items=1 ppid=1704 pid=1797
> auid=11532 uid=11532 gid=5000 euid=11532 suid=11532 fsuid=11532 egid=5000
> sgid=5000 fsgid=5000 tty=(none) ses=1 comm="gkrellm" exe="/usr/bin/gkrellm"
> key="permissive"
> type=CWD msg=audit(1323540255.146:97): cwd="/home/pmoody"
> type=PATH msg=audit(1323540255.146:97): item=0 name="/proc/meminfo" inode=
> 4026532008 dev=00:03 mode=0100444 ouid=0 ogid=0 rdev=00:00
>
> hopefully someone with more auditd internal knowledge can explain what's
> going on.
Simple, int open(const char *pathname, int flags, mode_t mode);
So, we want to look at a1's contents. Its a zero. So, let's look that up in
/usr/include/asm-generic/fcntl.h:
#define O_RDONLY 00000000
#define O_WRONLY 00000001
#define O_RDWR 00000002
So, it would appear open is called with O_RDONLY, which is allowed by the
permissions 0444.
> auditctl -l doesn't know how to report this yet; if this patch is generally
> acceptable, I can try to fix that and update the manpage, etc.
Yes, auditctl -l will have to be updated. If you want to do that, it would be
helpful. Also, see the comments on the other patch in case it affects this one.
-Steve
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: test patch for auditctl inter-field comparisons on euid/uid, egid/gid
2011-12-12 14:40 ` Steve Grubb
@ 2011-12-12 16:40 ` Peter Moody
2011-12-14 1:38 ` Peter Moody
0 siblings, 1 reply; 11+ messages in thread
From: Peter Moody @ 2011-12-12 16:40 UTC (permalink / raw)
To: Steve Grubb; +Cc: linux-audit
[-- Attachment #1.1: Type: text/plain, Size: 2336 bytes --]
On Mon, Dec 12, 2011 at 6:40 AM, Steve Grubb <sgrubb@redhat.com> wrote:
> On Sunday, December 11, 2011 02:09:27 PM Peter Moody wrote:
> > This patch extends Eric's test patch from 11/17 (
> > http://www.redhat.com/archives/linux-audit/2011-November/msg00045.html).
> > This turns -C into a long opt with similar syntax to -F.
>
> Thanks.
>
> > One strange thing related to this patch: auditd seems to be reporting
> > success for a normal user process (gklrellm) opening /proc/meminfo (mode
> > 444) O_RDWR, and I don't see how this is possible. eg:
> >
> > type=SYSCALL msg=audit(1323540255.146:97): arch=c000003e syscall=2
> > success=yes exit=13 a0=4b1972 a1=0 a2=1b6 a3=0 items=1 ppid=1704 pid=1797
> > auid=11532 uid=11532 gid=5000 euid=11532 suid=11532 fsuid=11532 egid=5000
> > sgid=5000 fsgid=5000 tty=(none) ses=1 comm="gkrellm"
> exe="/usr/bin/gkrellm"
> > key="permissive"
> > type=CWD msg=audit(1323540255.146:97): cwd="/home/pmoody"
> > type=PATH msg=audit(1323540255.146:97): item=0 name="/proc/meminfo"
> inode=
> > 4026532008 dev=00:03 mode=0100444 ouid=0 ogid=0 rdev=00:00
> >
> > hopefully someone with more auditd internal knowledge can explain what's
> > going on.
>
> Simple, int open(const char *pathname, int flags, mode_t mode);
>
> So, we want to look at a1's contents.
d'oh, of course. I keep thinking it's a2 for some reason.
> Its a zero. So, let's look that up in
> /usr/include/asm-generic/fcntl.h:
>
> #define O_RDONLY 00000000
> #define O_WRONLY 00000001
> #define O_RDWR 00000002
>
> So, it would appear open is called with O_RDONLY, which is allowed by the
> permissions 0444.
>
>
> > auditctl -l doesn't know how to report this yet; if this patch is
> generally
> > acceptable, I can try to fix that and update the manpage, etc.
>
> Yes, auditctl -l will have to be updated. If you want to do that, it would
> be
> helpful. Also, see the comments on the other patch in case it affects this
> one.
>
It will and I'll update this.
This only supports != and = because those were the only two that really
seemed like meaningful tests for these fields; do you think this should
support <, <=, >, >= as well (I'm assuming that bitmasks wouldn't make
sense at all)
Cheers,
peter
> -Steve
>
--
Peter Moody Google 1.650.253.7306
Security Engineer pgp:0xC3410038
[-- Attachment #1.2: Type: text/html, Size: 3587 bytes --]
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: test patch for auditctl inter-field comparisons on euid/uid, egid/gid
2011-12-12 16:40 ` Peter Moody
@ 2011-12-14 1:38 ` Peter Moody
2011-12-15 0:16 ` Peter Moody
0 siblings, 1 reply; 11+ messages in thread
From: Peter Moody @ 2011-12-14 1:38 UTC (permalink / raw)
To: Steve Grubb; +Cc: linux-audit
Here's the updated version, now supporting all of the interfield
comparisons from
https://www.redhat.com/archives/linux-audit/2011-December/msg00018.html
auditctl -l doesn't report the comparison filters correctly. I'll look
more into this.
Signed-off-by: Peter Moody <pmoody@google.com>
---
trunk/auparse/typetab.h | 2 +
trunk/lib/errormsg.h | 7 +-
trunk/lib/fieldtab.h | 3 +
trunk/lib/libaudit.c | 302 +++++++++++++++++++++++++++++++++++++++++++
trunk/lib/libaudit.h | 2 +
trunk/src/auditctl.c | 19 +++-
trunk/src/ausearch-report.c | 1 +
7 files changed, 333 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..0fce075 100644
--- a/trunk/lib/libaudit.c
+++ b/trunk/lib/libaudit.c
@@ -783,6 +783,306 @@ 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_EUID;
+ break;
+ case AUDIT_EUID:
+ rule->values[rule->field_count] = AUDIT_COMPARE_EUID_TO_SUID;
+ 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_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;
+ }
+ case AUDIT_SUID:
+ switch(field2) {
+ case AUDIT_LOGINUID:
+ rule->values[rule->field_count] = AUDIT_COMPARE_AUID_TO_EUID;
+ 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_EUID_TO_FSUID;
+ break;
+ case AUDIT_OBJ_UID:
+ rule->values[rule->field_count] = AUDIT_COMPARE_EUID_TO_OBJ_UID;
+ break;
+ case AUDIT_UID:
+ rule->values[rule->field_count] = AUDIT_COMPARE_UID_TO_EUID;
+ 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_EGID;
+ 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 +1157,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"},
--
1.7.3.1
--
Peter Moody Google 1.650.253.7306
Security Engineer pgp:0xC3410038
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: test patch for auditctl inter-field comparisons on euid/uid, egid/gid
2011-12-14 1:38 ` Peter Moody
@ 2011-12-15 0:16 ` Peter Moody
2011-12-15 1:18 ` Peter Moody
0 siblings, 1 reply; 11+ messages in thread
From: Peter Moody @ 2011-12-15 0:16 UTC (permalink / raw)
To: Steve Grubb; +Cc: linux-audit
On Tue, Dec 13, 2011 at 5:38 PM, Peter Moody <pmoody@google.com> wrote:
> Here's the updated version, now supporting all of the interfield
> comparisons from
> https://www.redhat.com/archives/linux-audit/2011-December/msg00018.html
>
> auditctl -l doesn't report the comparison filters correctly. I'll look
> more into this.
Testing has revealed a couple of bugs in this. Fixing these and
testing some more now.
Cheers,
peter
--
Peter Moody Google 1.650.253.7306
Security Engineer pgp:0xC3410038
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: test patch for auditctl inter-field comparisons on euid/uid, egid/gid
2011-12-15 0:16 ` Peter Moody
@ 2011-12-15 1:18 ` Peter Moody
2011-12-15 6:55 ` Stephen Quinney
2012-02-28 23:07 ` Steve Grubb
0 siblings, 2 replies; 11+ messages in thread
From: Peter Moody @ 2011-12-15 1:18 UTC (permalink / raw)
To: Steve Grubb; +Cc: linux-audit
> 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.
Signed-off-by: Peter Moody <pmoody@google.com>
---
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"},
--
1.7.3.1
--
Peter Moody Google 1.650.253.7306
Security Engineer pgp:0xC3410038
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: test patch for auditctl inter-field comparisons on euid/uid, egid/gid
2011-12-15 1:18 ` Peter Moody
@ 2011-12-15 6:55 ` Stephen Quinney
2011-12-15 13:36 ` Steve Grubb
2012-02-28 23:07 ` Steve Grubb
1 sibling, 1 reply; 11+ messages in thread
From: Stephen Quinney @ 2011-12-15 6:55 UTC (permalink / raw)
To: Peter Moody; +Cc: linux-audit
On Wed, Dec 14, 2011 at 05:18:30PM -0800, Peter Moody wrote:
> 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" )
I don't know the code particularly well but from reading the patch it
strikes me that in this chunk "obj_gid" should probably be
AUPARSE_TYPE_GID rather than AUPARSE_TYPE_UID.
Stephen Quinney
--
The University of Edinburgh is a charitable body, registered in
Scotland, with registration number SC005336.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: test patch for auditctl inter-field comparisons on euid/uid, egid/gid
2011-12-15 6:55 ` Stephen Quinney
@ 2011-12-15 13:36 ` Steve Grubb
2011-12-16 23:34 ` Peter Moody
0 siblings, 1 reply; 11+ messages in thread
From: Steve Grubb @ 2011-12-15 13:36 UTC (permalink / raw)
To: Stephen Quinney; +Cc: linux-audit
On Thursday, December 15, 2011 01:55:53 AM Stephen Quinney wrote:
> On Wed, Dec 14, 2011 at 05:18:30PM -0800, Peter Moody wrote:
> > 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" )
>
> I don't know the code particularly well but from reading the patch it
> strikes me that in this chunk "obj_gid" should probably be
> AUPARSE_TYPE_GID rather than AUPARSE_TYPE_UID.
Yeah, good catch. I can fix this when I apply the patch to svn. No need to re-
send unless there is something else needing fixing as well.
-Steve
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: test patch for auditctl inter-field comparisons on euid/uid, egid/gid
2011-12-15 13:36 ` Steve Grubb
@ 2011-12-16 23:34 ` Peter Moody
0 siblings, 0 replies; 11+ messages in thread
From: Peter Moody @ 2011-12-16 23:34 UTC (permalink / raw)
To: Steve Grubb; +Cc: linux-audit
On Thu, Dec 15, 2011 at 5:36 AM, Steve Grubb <sgrubb@redhat.com> wrote:
>
> Yeah, good catch. I can fix this when I apply the patch to svn. No need to re-
> send unless there is something else needing fixing as well.
I've got a sort of hacky way of getting -l to work.
In order to use fieldtab.h and audit_field_to_name, I had to move the
AUDIT_COMPARE_* defines to be unique WRT to the other audit fields in
include/linux/audit.h. Then I can add the AUDIT_COMPARE_* definitions
to fieldtab.h like:
_S(AUDIT_COMPARE_UID_TO_OBJ_UID, "uid,obj_uid" )
...
_S(AUDIT_COMPARE_SGID_TO_FSGID, "sgid,fsgid" )
then auditctl -l splits on the ','. This does mean that no matter what
order comparisons are entered on the command line, they'll only ever
be displayed in the order in which they appear in fieldtab.h
Does this sound reasonable? I can send my patches along if it does.
Cheers,
peter
--
Peter Moody Google 1.650.253.7306
Security Engineer pgp:0xC3410038
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: test patch for auditctl inter-field comparisons on euid/uid, egid/gid
2011-12-15 1:18 ` Peter Moody
2011-12-15 6:55 ` Stephen Quinney
@ 2012-02-28 23:07 ` Steve Grubb
2012-02-28 23:12 ` Peter Moody
1 sibling, 1 reply; 11+ messages in thread
From: Steve Grubb @ 2012-02-28 23:07 UTC (permalink / raw)
To: Peter Moody; +Cc: linux-audit
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 <pmoody@google.com>
> ---
> 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"},
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: test patch for auditctl inter-field comparisons on euid/uid, egid/gid
2012-02-28 23:07 ` Steve Grubb
@ 2012-02-28 23:12 ` Peter Moody
0 siblings, 0 replies; 11+ messages in thread
From: Peter Moody @ 2012-02-28 23:12 UTC (permalink / raw)
To: Steve Grubb; +Cc: linux-audit
On Tue, Feb 28, 2012 at 3:07 PM, Steve Grubb <sgrubb@redhat.com> wrote:
> 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
Excellent, I was just about ask about this.
> 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. :)
ah, good point. oh well, thanks for applying it.
--
Peter Moody Google 1.650.253.7306
Security Engineer pgp:0xC3410038
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2012-02-28 23:12 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-12-11 19:09 test patch for auditctl inter-field comparisons on euid/uid, egid/gid Peter Moody
2011-12-12 14:40 ` Steve Grubb
2011-12-12 16:40 ` Peter Moody
2011-12-14 1:38 ` Peter Moody
2011-12-15 0:16 ` Peter Moody
2011-12-15 1:18 ` Peter Moody
2011-12-15 6:55 ` Stephen Quinney
2011-12-15 13:36 ` Steve Grubb
2011-12-16 23:34 ` Peter Moody
2012-02-28 23:07 ` Steve Grubb
2012-02-28 23:12 ` Peter Moody
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox