On Wednesday 28 September 2005 15:47, Steve Grubb wrote:
Hello,
Dustin and I were talking about how to represent some new operators for
writing audit rules. I am interested in seeing >, <, and range added at a
minimum. The question came up as to how to fit this into the existing
audit_rule structure. This is what we currently have:
struct audit_rule { /* for AUDIT_LIST, AUDIT_ADD, and AUDIT_DEL */
__u32 flags; /* AUDIT_PER_{TASK,CALL}, AUDIT_PREPEND */
__u32 action; /* AUDIT_NEVER, AUDIT_POSSIBLE, AUDIT_ALWAYS */
__u32 field_count;
__u32 mask[AUDIT_BITMASK_SIZE];
__u32 fields[AUDIT_MAX_FIELDS];
__u32 values[AUDIT_MAX_FIELDS];
};
The fields member currently uses the msb to determine whether its = or !=.
#define AUDIT_NEGATE 0x80000000
I was wondering if we should go ahead and map the other operators into the
other high bits. We are currently only using the lower 4 bits of the u32 word
so we have plenty of room. We have to do this in a way that is backward
compatible for old kernels. Any ideas? Any preferred bit patterns?
Also, we have the issue of needing to send 2 values for a range operator. How
should we make the kernel understand this? Or should we create a new message
type for adding, listing, and deleting rules that we can expand the idea of
operators for and use the current one for legacy compatibility?
Need some ideas from the kernel hackers....
-Steve
--
Linux-audit mailing list
Linux-audit(a)redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit
You could add a zero-sized array at the bottom like, so:
struct op_t {
char op[2];
}
struct audit_rule { /* for AUDIT_LIST, AUDIT_ADD, and AUDIT_DEL */
__u32 flags; /* AUDIT_PER_{TASK,CALL}, AUDIT_PREPEND */
__u32 action; /* AUDIT_NEVER, AUDIT_POSSIBLE, AUDIT_ALWAYS */
__u32 field_count;
__u32 mask[AUDIT_BITMASK_SIZE];
__u32 fields[AUDIT_MAX_FIELDS];
__u32 values[AUDIT_MAX_FIELDS];
struct op_t operator[0];
};
Then you iterate over field count to get each operator corresponding to the value.
Haha, I wrote this number... which is nice and ugly to convey the point... but, I do think
using
the high bits is probably a good approach to stick with...
-tim
#include <stdio.h>
#include <errno.h>
#define OP_LESS ((char[2]){'<', ' '})
#define OP_LESS_EQUAL ((char[2]){'<', '='})
struct op_t {
char op[2];
};
struct compare_t {
struct op_t ops[0];
};
int main(void)
{
int i;
struct op_t op_one;
struct op_t op_two;
struct op_t this_op;
struct compare_t *c;
op_one.op[0] = '<';
op_one.op[1] = ' ';
op_two.op[0] = '<';
op_two.op[1] = '=';
c = (struct compare_t *)malloc(sizeof(*c) + (2 * sizeof(struct op_t)));
if (!c) {
perror("malloc");
exit(errno);
}
c->ops[0] = op_one;
c->ops[1] = op_two;
for (i = 0; i < 2; i++) {
this_op = c->ops[i];
if (!memcmp(this_op.op, OP_LESS, 2))
printf("Less than\n");
if (!memcmp(this_op.op, OP_LESS_EQUAL, 2))
printf("Less than or equal\n");
}
free(c);
return 0;
}