Re: [PATCH] (1/2) new audit filter allows excluding messages by type (kernel)
by Dustin Kirkland
On 11/2/05, Steve Grubb <sgrubb(a)redhat.com> wrote:
> On Tuesday 01 November 2005 17:53, Dustin Kirkland wrote:
> > - Define a new function audit_filter_exclude() that takes a message type
> > as input and examines all rules in the filter. It returns '1' if the
> > message is to be excluded, and '0' otherwise.
>
> You should check that the list is empty and short circuit. This will be the
> case %99.99 of the time.
Ok. There's now a list_empty() check at the top of
audit_filter_exclude().
I also removed some unnecessary {} and fixed a couple of lines that were
>80 characters.
I duly note that there's an existing discussion as to whether this
filter belongs in the kernel or in userspace at all. But I'm keeping
the patch current with existing comments.
Updated patch here.
:-Dustin
diff -uprN linux-2.6.14-rc4-audit_ops/include/linux/audit.h
linux-2.6.14-rc4-audit_ops-exclude/include/linux/audit.h
--- linux-2.6.14-rc4-audit_ops/include/linux/audit.h 2005-10-26 16:12:42.000000000 -0500
+++ linux-2.6.14-rc4-audit_ops-exclude/include/linux/audit.h 2005-10-31 15:51:02.000000000 -0600
@@ -81,8 +81,9 @@
#define AUDIT_FILTER_ENTRY 0x02 /* Apply rule at syscall entry */
#define AUDIT_FILTER_WATCH 0x03 /* Apply rule to file system watches */
#define AUDIT_FILTER_EXIT 0x04 /* Apply rule at syscall exit */
+#define AUDIT_FILTER_EXCLUDE 0x05 /* Apply rule at audit_log_start */
-#define AUDIT_NR_FILTERS 5
+#define AUDIT_NR_FILTERS 6
#define AUDIT_FILTER_PREPEND 0x10 /* Prepend to front of list */
@@ -121,6 +122,7 @@
#define AUDIT_LOGINUID 9
#define AUDIT_PERS 10
#define AUDIT_ARCH 11
+#define AUDIT_MSGTYPE 12
/* These are ONLY useful when checking
* at syscall exit time (AUDIT_AT_EXIT). */
@@ -265,6 +267,7 @@ extern int audit_sockaddr(int len, void
extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt);
extern void audit_signal_info(int sig, struct task_struct *t);
extern int audit_filter_user(struct netlink_skb_parms *cb, int type);
+extern int audit_filter_exclude(int type);
#else
#define audit_alloc(t) ({ 0; })
#define audit_free(t) do { ; } while (0)
diff -uprN linux-2.6.14-rc4-audit_ops/kernel/audit.c linux-2.6.14-rc4-audit_ops-exclude/kernel/audit.c
--- linux-2.6.14-rc4-audit_ops/kernel/audit.c 2005-10-21 12:35:50.000000000 -0500
+++ linux-2.6.14-rc4-audit_ops-exclude/kernel/audit.c 2005-11-02 04:44:40.000000000 -0600
@@ -659,6 +659,9 @@ struct audit_buffer *audit_log_start(str
if (!audit_initialized)
return NULL;
+ if (unlikely(audit_filter_exclude(type)))
+ return NULL;
+
if (gfp_mask & __GFP_WAIT)
reserve = 0;
else
diff -uprN linux-2.6.14-rc4-audit_ops/kernel/auditsc.c linux-2.6.14-rc4-audit_ops-exclude/kernel/auditsc.c
--- linux-2.6.14-rc4-audit_ops/kernel/auditsc.c 2005-10-27 14:17:41.000000000 -0500
+++ linux-2.6.14-rc4-audit_ops-exclude/kernel/auditsc.c 2005-11-02 10:12:04.000000000 -0600
@@ -181,7 +181,8 @@ static struct list_head audit_filter_lis
LIST_HEAD_INIT(audit_filter_list[2]),
LIST_HEAD_INIT(audit_filter_list[3]),
LIST_HEAD_INIT(audit_filter_list[4]),
-#if AUDIT_NR_FILTERS != 5
+ LIST_HEAD_INIT(audit_filter_list[5]),
+#if AUDIT_NR_FILTERS != 6
#error Fix audit_filter_list initialiser
#endif
};
@@ -663,6 +664,36 @@ int audit_filter_user(struct netlink_skb
return ret; /* Audit by default */
}
+int audit_filter_exclude(int type)
+{
+ struct audit_entry *e;
+ int result = 0;
+
+ rcu_read_lock();
+ if (sizeof(list_empty(&audit_filter_list[AUDIT_FILTER_EXCLUDE])))
+ goto unlock_and_return;
+
+ list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_EXCLUDE],
+ list) {
+ struct audit_rule *rule = &e->rule;
+ int i;
+ for (i = 0; i < rule->field_count; i++) {
+ u32 field = rule->fields[i] & ~AUDIT_OPERATORS;
+ u32 op = rule->fields[i] & AUDIT_OPERATORS;
+ u32 value = rule->values[i];
+ if ( field == AUDIT_MSGTYPE ) {
+ result = audit_comparator(type, op, value);
+ if (!result)
+ goto unlock_and_return;
+ }
+ }
+ }
+unlock_and_return:
+ rcu_read_unlock();
+ return result;
+}
+
+
/* This should be called with task_lock() held. */
static inline struct audit_context *audit_get_context(struct task_struct *tsk,
int return_valid,
19 years, 1 month
Remotely logging audit rules.
by Stephen J. Smoogen
I got a development request to see how much work it would take to do.
Our policy wags want to have all object audit events (or whatever the
real term for that is...) to be sent both locally and remotely. The
reason is a supposed policy for checking the local logs against remote
logs to see if they have been tampered with and for being able to
train a SIM to look for events in the centralized logs.
My 5000 foot question is how would the best way to implement this be?
For the current RHEL 4 I would probably need some sort of tail -f xxx
| logger type script.
--
Stephen J Smoogen.
CSIRT/Linux System Administrator
19 years, 1 month
[PATCH] (2/2) new audit filter allows excluding messages by type (userspace)
by Dustin Kirkland
Userspace component to pass an exclude filter to and from the kernel.
- Teach userspace about the "exclude,???" filter
- Teach userspace about the "msgtype=???" field
- Look up the message type in the name-to-msg table if need be
STEVE:
The blob of code in audit_print_reply() might take some munging. This
patch is built on top of my operators patch, which you haven't released
yet. I taught the "auditctl -l" to process the "exclude" list rules
from the kernel for better debugging purposes. To do this, I had to
update audit_print_reply() to translate the operators to their symbols.
I'll gladly rework this part as soon as you have a release of audit with
the operator code in it.
But this should be enough to see what's going on here. Comments
welcome.
:-Dustin
diff -urpN audit-1.0.7-operators/lib/libaudit.c
audit-1.0.7-operators-exclude/lib/libaudit.c
--- audit-1.0.7-operators/lib/libaudit.c 2005-10-26 12:58:59.000000000 -0500
+++ audit-1.0.7-operators-exclude/lib/libaudit.c 2005-11-01 16:28:09.000000000 -0600
@@ -699,6 +699,17 @@ int audit_rule_fieldpair(struct audit_ru
}
}
break;
+ case AUDIT_MSGTYPE:
+ if (isdigit((char)*(v)))
+ rule->values[rule->field_count] =
+ strtol(v, NULL, 0);
+ else
+ if (audit_name_to_msg_type(v) > 0)
+ rule->values[rule->field_count] =
+ audit_name_to_msg_type(v);
+ else
+ return -8;
+ break;
case AUDIT_ARCH:
if (audit_syscalladded)
return -3;
/* This bitmask is used to validate user input. It represents all bits that
are currently used in an audit field constant understood by the kernel.
diff -urpN audit-1.0.7-operators/lib/lookup_table.c audit-1.0.7-operators-exclude/lib/lookup_table.c
--- audit-1.0.7-operators/lib/lookup_table.c 2005-10-20 17:28:40.000000000 -0500
+++ audit-1.0.7-operators-exclude/lib/lookup_table.c 2005-10-31 15:53:55.000000000 -0600
@@ -90,6 +90,7 @@ static struct transtab fieldtab[] = {
{ AUDIT_LOGINUID, "loginuid" },
{ AUDIT_PERS, "pers" },
{ AUDIT_ARCH, "arch" },
+ { AUDIT_MSGTYPE, "msgtype" },
{ AUDIT_DEVMAJOR, "devmajor" },
{ AUDIT_DEVMINOR, "devminor" },
@@ -104,11 +105,12 @@ static struct transtab fieldtab[] = {
#define AUDIT_FIELD_NAMES (sizeof(fieldtab)/sizeof(fieldtab[0]))
static struct transtab flagtab[] = {
- { AUDIT_FILTER_TASK, "task" },
- { AUDIT_FILTER_ENTRY, "entry" },
- { AUDIT_FILTER_EXIT, "exit" },
- { AUDIT_FILTER_USER, "user" },
- { AUDIT_FILTER_WATCH, "watch" }
+ { AUDIT_FILTER_TASK, "task" },
+ { AUDIT_FILTER_ENTRY, "entry" },
+ { AUDIT_FILTER_EXIT, "exit" },
+ { AUDIT_FILTER_USER, "user" },
+ { AUDIT_FILTER_WATCH, "watch" },
+ { AUDIT_FILTER_EXCLUDE, "exclude" }
};
#define AUDIT_FLAG_NAMES (sizeof(flagtab)/sizeof(flagtab[0]))
diff -urpN audit-1.0.7-operators/src/auditctl.c audit-1.0.7-operators-exclude/src/auditctl.c
--- audit-1.0.7-operators/src/auditctl.c 2005-10-20 17:28:03.000000000 -0500
+++ audit-1.0.7-operators-exclude/src/auditctl.c 2005-11-01 16:24:34.000000000 -0600
@@ -150,6 +150,8 @@ static int audit_rule_setup(const char *
*flags = AUDIT_FILTER_USER;
else if (strstr(opt, "watch"))
*flags = AUDIT_FILTER_WATCH;
+ else if (strstr(opt, "exclude"))
+ *flags = AUDIT_FILTER_EXCLUDE;
else
return 1;
if (strstr(opt, "never"))
@@ -569,6 +571,10 @@ static int setopt(int count, char *vars[
fprintf(stderr, "Field %s cannot be checked at syscall entry\n", optarg);
retval = -1;
break;
+ case -8:
+ fprintf(stderr, "-F unknown message type\n");
+ retval = -1;
+ break;
default:
retval = -1;
break;
@@ -1011,30 +1017,34 @@ static int audit_print_reply(struct audi
audit_flag_to_name((int)rep->rule->flags),
audit_action_to_name(rep->rule->action));
for (i = 0; i < rep->rule->field_count; i++) {
- int field = rep->rule->fields[i];
- int negated = 0;
-
- if (field & AUDIT_NEGATE) {
- field &= ~AUDIT_NEGATE;
- negated = 1;
- }
+ int field = rep->rule->fields[i] & ~AUDIT_OPERATORS & ~AUDIT_NEGATE;
+ int op = rep->rule->fields[i] & AUDIT_OPERATORS & ~AUDIT_NEGATE;
const char *name = audit_field_to_name(field);
if (name) {
if (strcmp(name, "arch") == 0) {
audit_elf =rep->rule->values[i];
printf(" %s%s%u", name,
- negated ? "!=" : "=",
+ audit_operator_to_symbol(op),
(unsigned)rep->rule->values[i]);
}
- else
+ else if (strcmp(name, "msgtype") == 0)
+ if (!audit_msg_type_to_name(rep->rule->values[i]))
+ printf(" %s%s%d", name,
+ audit_operator_to_symbol(op),
+ rep->rule->values[i]);
+ else
+ printf(" %s%s%s", name,
+ audit_operator_to_symbol(op),
+ audit_msg_type_to_name(rep->rule->values[i]));
+ else
printf(" %s%s%d", name,
- negated ? "!=" : "=",
+ audit_operator_to_symbol(op),
rep->rule->values[i]);
}
else
printf(" f%d%s%d", rep->rule->fields[i],
- negated ? "!=" : "=",
+ audit_operator_to_symbol(op),
rep->rule->values[i]);
if (rep->rule->values[i])
printf(" (0x%x)", rep->rule->values[i]);
19 years, 1 month
[PATCH] fix audit_rule_syscallbyname()
by Amy Griffis
Hello,
The audit_rule_syscallbyname() function in libaudit currently doesn't
work for any system calls other than "all". This is because it
depends on a previous setting of the audit_elf global variable.
This has been unnoticed so far because auditctl defines an audit_elf
global and sets it before calling this routine.
Arguably, libaudit shouldn't be using a global this way, but this
patch fixes the immediate problem.
Thanks,
Amy
diff -Nrup audit-1.0.8/lib/libaudit.c audit-1.0.8-new/lib/libaudit.c
--- audit-1.0.8/lib/libaudit.c 2005-10-17 13:40:22.000000000 -0400
+++ audit-1.0.8-new/lib/libaudit.c 2005-11-01 13:43:13.013425856 -0500
@@ -588,7 +588,10 @@ int audit_rule_syscallbyname(struct audi
rule->mask[i] = ~0;
return 0;
}
- machine = audit_elf_to_machine(audit_elf);
+ if (!audit_elf)
+ machine = audit_detect_machine();
+ else
+ machine = audit_elf_to_machine(audit_elf);
if (machine < 0)
return -2;
nr = audit_name_to_syscall(scall, machine);
19 years, 1 month