Freeing multiple contexts message
by Steve Grubb
Hi,
I think we need to change the message in audit_free_context(). It currently
says:
"audit(:%d): major=%d name_count=%d: freeing multiple contexts (%d)\n"
This does not really indicate to the casual user that they've encountered a
bug that needs to be reported. Is there a common method to flag kernel bugs
that gets a user's attention? BUG_ON? WARN_ON?
Also, does this message contain enough information for troubleshooting if
someone reports it? Should it contain the syscall number, task name, or is
anything else needed?
-Steve
19 years, 1 month
[2.6 patch] kernel/: small cleanups
by Adrian Bunk
This patch contains the following cleanups:
- make needlessly global functions static
- every file should include the headers containing the prototypes for
it's global functions
Signed-off-by: Adrian Bunk <bunk(a)stusta.de>
---
kernel/audit.c | 2 +-
kernel/irq/proc.c | 2 ++
kernel/rcutorture.c | 2 +-
kernel/timer.c | 1 +
4 files changed, 5 insertions(+), 2 deletions(-)
--- linux-2.6.14-rc5-mm1-full/kernel/timer.c.old 2005-10-30 02:27:36.000000000 +0200
+++ linux-2.6.14-rc5-mm1-full/kernel/timer.c 2005-10-30 02:27:56.000000000 +0200
@@ -33,6 +33,7 @@
#include <linux/posix-timers.h>
#include <linux/cpu.h>
#include <linux/syscalls.h>
+#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
--- linux-2.6.14-rc5-mm1-full/kernel/irq/proc.c.old 2005-10-30 02:31:31.000000000 +0200
+++ linux-2.6.14-rc5-mm1-full/kernel/irq/proc.c 2005-10-30 02:31:48.000000000 +0200
@@ -10,6 +10,8 @@
#include <linux/proc_fs.h>
#include <linux/interrupt.h>
+#include "internals.h"
+
static struct proc_dir_entry *root_irq_dir, *irq_dir[NR_IRQS];
#ifdef CONFIG_SMP
--- linux-2.6.14-rc5-mm1-full/kernel/audit.c.old 2005-10-30 02:33:08.000000000 +0200
+++ linux-2.6.14-rc5-mm1-full/kernel/audit.c 2005-10-30 02:33:15.000000000 +0200
@@ -272,7 +272,7 @@
return old;
}
-int kauditd_thread(void *dummy)
+static int kauditd_thread(void *dummy)
{
struct sk_buff *skb;
--- linux-2.6.14-rc5-mm1-full/kernel/rcutorture.c.old 2005-10-30 02:33:35.000000000 +0200
+++ linux-2.6.14-rc5-mm1-full/kernel/rcutorture.c 2005-10-30 02:33:53.000000000 +0200
@@ -99,7 +99,7 @@
/*
* Allocate an element from the rcu_tortures pool.
*/
-struct rcu_torture *
+static struct rcu_torture *
rcu_torture_alloc(void)
{
struct list_head *p;
19 years, 1 month
Audit log for user defines
by Call, Tom H
Hello,
Here in the defense industry we are very pleased that the current
production version of the audit daemon 1.0.3-6 for Enterprise 4 U2 now
has the functionality to capture user defined audit events ( such as,
auditctl -w /etc/passwd -k passwd -p wa ).
This audit capture ability is crucial to satisfy our auditing
requirements for the NISPOM Chapter 8, which we must do. Prior to this
we have had to rely on the third party product 'Snare' to capture audit
events on what the NISPOM calls 'Security Relevant Objects'. But as you
may know 'Snare' requires its own audit daemon, not a good thing for us
because it requires a modified kernel.
But back to the native audit daemon 1.0.3-6, what we have found is that
both the user defined audit events, using auditctl, and the default
audit events, coded in the audit daemon?, are both written to the same
log file /var/log/audit/audit.log by default. This combining of all
audit events into one log is not our preference because the audit events
required to satisfy NISPOM Chapter 8 are not the same requirements of
CAPP auditing. The CAPP default audit events are not at all needed for
NISPOM Chapter 8 and actually makes it harder to filter and manage the
audit.log.
What we would like to see added to audit package is the ability to log
the default CAPP audit events and the user defined audit events to
separate log files. We would be pleased if you would consider making
this change.
Thanks!
Tom Call
Lockheed Martin Missiles and Fire Control - Orlando, SCOC
desk(paged): (407)356-4959 pager: (407)981-8177
19 years, 1 month
Re: [PATCH] Audit filter rule operators (2/2)
by Dustin Kirkland
On 10/24/05, Steve Grubb <sgrubb(a)redhat.com> wrote:
> We need to go ahead and take the next 2 upper bits in the same patch and save
> those for future use. For now, if those bits are set, the kernel should
> reject the rule. To support this, we also need some code added to
> audit_add_rule to check that the operators is something the kernel
> understands.
On 10/24/05, Steve Grubb <sgrubb(a)redhat.com> wrote:
> So that future kernels can detect that the rule is trying to use an operator
> that it doesn't understand and send an error back to the user. For example,
> someone my be using kernel 2.6.25 with audit 3.0.
>
> I really don't care what they are used for, but we need ways for older kernels
> to reject commands from newer user space tools.
>
> I really think that we should be looking at all the undefined bits and
> checking that they are 0.
On 10/25/05, Amy Griffis <amy.griffis(a)hp.com> wrote:
> I think this may have been alluded to in another email, but we need to
> do comaptibility checking on rule insert, not during rule evaluation.
> So if AUDIT_NEGATE is set, clear it and set AUDIT_NOT_EQUAL. If no
> bits are set, set AUDIT_EQUAL. Doing so eliminates these two branches
> in fast-path code.
Ok, as per our subsequent discussions via email and IRC, I've actually
created a bitmask called AUDIT_UNUSED_BITS which is currently in sync
with the constants we now have defined. If we start #defining audit
message types > 2048, or start extending the operator bits further
right, this simply needs to be updated.
Then in the audit_add_rule() function, there's a call that checks to
make sure that each field value in the new rule is not using unsupported
bits. I think this should give the future compatibility check that
Steve has been asking for. Which means that the default: return
-EINVAL; in the audit_comparator() switch should be dead code, assuming
that AUDIT_UNUSED_BITS is in good working order.
Also near this rule insertion code, there's a new check for the
AUDIT_NEGATE bit being set. If it is, I unset it and make the operator
AUDIT_NOT_EQUAL. And if all of the the operator bits are 0's, then we
assume that it's an AUDIT_EQUAL operation. These five lines will be
needed for legacy support of older audit userspace that utilized
AUDIT_NEGATE and flagged AUDIT_EQUAL in such a manner.
On 10/24/05, Steve Grubb <sgrubb(a)redhat.com> wrote:
> Does this make sense? What does !< mean? I think AUDIT_NEGATE only makes sense
> in relation to AUDIT_EQUAL. It should be moved to that case if not eliminated
> outright.
You're absolutely right, Steve.
On 10/25/05, Amy Griffis <amy.griffis(a)hp.com> wrote:
> Here's another way to specify this that may be more readable and
> common in the kernel:
>
> #define AUDIT_LESS_THAN_OR_EQUAL AUDIT_EQUAL|AUDIT_LESS_THAN
Phenomenal suggestion, Amy. I've reworked them to look much nicer, I
think you'll see.
On 10/25/05, Amy Griffis <amy.griffis(a)hp.com> wrote:
> AUDIT_RANGE isn't needed at all, as you already have an implementation
> that can express that.
This is totally true, as well. I've been testing with some rather
complicated sets of rules that have in fact proven to operate as
expected in range fashion. I meant to remove this part of the patch but
I forgot as I was cleansing it before submission.
On 10/25/05, Amy Griffis <amy.griffis(a)hp.com> wrote:
> Many lines in this function are way over 80 chars -- see
> Documentation/CodingStyle Chapter 2.
I fixed all of these. Please check to make sure I've indented them in
an acceptable manner.
On 10/25/05, Amy Griffis <amy.griffis(a)hp.com> wrote:
> Or how about this?
>
> int rc = 0;
>
> if ((operator & AUDIT_EQUAL) && (left == right))
> rc = 1;
> else if ((operator & AUDIT_LESS_THAN) && (left < right))
> rc = 1;
> else if ((operator & AUDIT_GREATER_THAN) && (left > right))
> rc = 1;
Ok, so there's been a side thread of discussion among myself, Amy, and
Steve where we've created a test program that tests both algorithms and
we're seeing almost precisely identical performance of both algorithms
across several architectures. It seems that there's a very slight
advantage of my switch-based approach on ix86, x86_64, and ppc, though
the different is possibly attributable to other performance noise.
Amy's if-based algorithm seems to have an advantage on ia64 though we
don't yet have an explanation as to why, though her last email seemed to
indicated that with compiler optimization at -O2, the results were again
nearly identical. Thus, I think that the switch-based approach is
easier on the eyes and I'm putting it forward again as my suggestion.
Feel free to add your two cents here, and perhaps we should publish the
tests as well...
--
A couple of other changes...
- I've incorporated the use of audit_comparator() in
audit_filter_user_rules() as well.
- I've also left a bit of explanation in the comment just above the
defines of the AUDIT_* stuff--let me know if this is ridiculously
elementary for the audience, as I can gladly remove it.
Patch follows.
:-Dustin
diff -urpNbB linux-2.6.14-rc4/include/linux/audit.h
linux-2.6.14-rc4-audit_ops/include/linux/audit.h
--- linux-2.6.14-rc4/include/linux/audit.h 2005-10-19 09:40:27.000000000 -0500
+++ linux-2.6.14-rc4-audit_ops/include/linux/audit.h 2005-10-26 16:12:42.000000000 -0500
@@ -98,6 +98,13 @@
#define AUDIT_WORD(nr) ((__u32)((nr)/32))
#define AUDIT_BIT(nr) (1 << ((nr) - AUDIT_WORD(nr)*32))
+/* 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.
+ * If you are adding a new #define AUDIT_<whatever>, please ensure that
+ * AUDIT_UNUSED_BITS is updated if need be. */
+#define AUDIT_UNUSED_BITS 0x0FFFFC00
+
+
/* Rule fields */
/* These are useful when checking the
* task structure at task creation time
@@ -130,6 +137,26 @@
#define AUDIT_NEGATE 0x80000000
+/* These are the supported operators.
+ * 4 2 1
+ * = > <
+ * -------
+ * 0 0 0 0 nonsense
+ * 0 0 1 1 <
+ * 0 1 0 2 >
+ * 0 1 1 3 !=
+ * 1 0 0 4 =
+ * 1 0 1 5 <=
+ * 1 1 0 6 >=
+ * 1 1 1 7 all operators
+ */
+#define AUDIT_LESS_THAN 0x10000000
+#define AUDIT_GREATER_THAN 0x20000000
+#define AUDIT_NOT_EQUAL 0x30000000
+#define AUDIT_EQUAL 0x40000000
+#define AUDIT_LESS_THAN_OR_EQUAL (AUDIT_LESS_THAN|AUDIT_EQUAL)
+#define AUDIT_GREATER_THAN_OR_EQUAL (AUDIT_GREATER_THAN|AUDIT_EQUAL)
+#define AUDIT_OPERATORS (AUDIT_EQUAL|AUDIT_NOT_EQUAL)
/* Status symbols */
/* Mask values */
diff -urpNbB linux-2.6.14-rc4/kernel/auditsc.c linux-2.6.14-rc4-audit_ops/kernel/auditsc.c
--- linux-2.6.14-rc4/kernel/auditsc.c 2005-10-19 09:40:29.000000000 -0500
+++ linux-2.6.14-rc4-audit_ops/kernel/auditsc.c 2005-10-26 16:11:10.000000000 -0500
@@ -2,6 +2,7 @@
* Handles all system-call specific auditing features.
*
* Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
+ * Copyright (C) 2005 IBM Corporation
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -27,6 +28,9 @@
* this file -- see entry.S) is based on a GPL'd patch written by
* okir(a)suse.de and Copyright 2003 SuSE Linux AG.
*
+ * The support of additional filter rules compares (>, <, >=, <=) was
+ * added by Dustin Kirkland <dustin.kirkland(a)us.ibm.com>, 2005.
+ *
*/
#include <linux/init.h>
@@ -252,6 +256,7 @@ static inline int audit_add_rule(struct
struct list_head *list)
{
struct audit_entry *entry;
+ int i;
/* Do not use the _rcu iterator here, since this is the only
* addition routine. */
@@ -261,6 +266,16 @@ static inline int audit_add_rule(struct
}
}
+ for (i = 0; i < rule->field_count; i++) {
+ if (rule->fields[i] & AUDIT_UNUSED_BITS)
+ return -EINVAL;
+ if ( rule->fields[i] & AUDIT_NEGATE )
+ rule->fields[i] |= AUDIT_NOT_EQUAL;
+ else if ( (rule->fields[i] & AUDIT_OPERATORS) == 0 )
+ rule->fields[i] |= AUDIT_EQUAL;
+ rule->fields[i] &= (~AUDIT_NEGATE);
+ }
+
if (!(entry = kmalloc(sizeof(*entry), GFP_KERNEL)))
return -ENOMEM;
if (audit_copy_rule(&entry->rule, rule)) {
@@ -385,6 +400,27 @@ int audit_receive_filter(int type, int p
return err;
}
+static int audit_comparator(const u32 left, const u32 op, const u32 right)
+{
+ printk(KERN_ERR "DUSTIN: peforming (%d %x %d)\n", left, op, right);
+ switch (op) {
+ case AUDIT_EQUAL:
+ return (left == right);
+ case AUDIT_NOT_EQUAL:
+ return (left != right);
+ case AUDIT_LESS_THAN:
+ return (left < right);
+ case AUDIT_LESS_THAN_OR_EQUAL:
+ return (left <= right);
+ case AUDIT_GREATER_THAN:
+ return (left > right);
+ case AUDIT_GREATER_THAN_OR_EQUAL:
+ return (left >= right);
+ default:
+ return -EINVAL;
+ }
+}
+
/* Compare a task_struct with an audit_rule. Return 1 on match, 0
* otherwise. */
static int audit_filter_rules(struct task_struct *tsk,
@@ -395,62 +431,71 @@ static int audit_filter_rules(struct tas
int i, j;
for (i = 0; i < rule->field_count; i++) {
- u32 field = rule->fields[i] & ~AUDIT_NEGATE;
+ u32 field = rule->fields[i] & ~AUDIT_OPERATORS;
+ u32 op = rule->fields[i] & AUDIT_OPERATORS;
u32 value = rule->values[i];
int result = 0;
switch (field) {
case AUDIT_PID:
- result = (tsk->pid == value);
+ result = audit_comparator(tsk->pid, op, value);
break;
case AUDIT_UID:
- result = (tsk->uid == value);
+ result = audit_comparator(tsk->uid, op, value);
break;
case AUDIT_EUID:
- result = (tsk->euid == value);
+ result = audit_comparator(tsk->euid, op, value);
break;
case AUDIT_SUID:
- result = (tsk->suid == value);
+ result = audit_comparator(tsk->suid, op, value);
break;
case AUDIT_FSUID:
- result = (tsk->fsuid == value);
+ result = audit_comparator(tsk->fsuid, op, value);
break;
case AUDIT_GID:
- result = (tsk->gid == value);
+ result = audit_comparator(tsk->gid, op, value);
break;
case AUDIT_EGID:
- result = (tsk->egid == value);
+ result = audit_comparator(tsk->egid, op, value);
break;
case AUDIT_SGID:
- result = (tsk->sgid == value);
+ result = audit_comparator(tsk->sgid, op, value);
break;
case AUDIT_FSGID:
- result = (tsk->fsgid == value);
+ result = audit_comparator(tsk->fsgid, op, value);
break;
case AUDIT_PERS:
- result = (tsk->personality == value);
+ result = audit_comparator(tsk->personality, op, value);
break;
case AUDIT_ARCH:
if (ctx)
- result = (ctx->arch == value);
+ result = audit_comparator(ctx->arch, op, value);
break;
case AUDIT_EXIT:
if (ctx && ctx->return_valid)
- result = (ctx->return_code == value);
+ result = audit_comparator(ctx->return_code,
+ op, value);
break;
case AUDIT_SUCCESS:
if (ctx && ctx->return_valid) {
if (value)
- result = (ctx->return_valid == AUDITSC_SUCCESS);
+ result = audit_comparator(
+ ctx->return_valid,
+ op, AUDITSC_SUCCESS);
else
- result = (ctx->return_valid == AUDITSC_FAILURE);
+ result = audit_comparator(
+ ctx->return_valid, op,
+ AUDITSC_FAILURE);
}
break;
case AUDIT_DEVMAJOR:
if (ctx) {
for (j = 0; j < ctx->name_count; j++) {
- if (MAJOR(ctx->names[j].dev)==value) {
+ if ( audit_comparator(
+ MAJOR(ctx->names[j].dev),
+ op, value)
+ ) {
++result;
break;
}
@@ -460,7 +505,10 @@ static int audit_filter_rules(struct tas
case AUDIT_DEVMINOR:
if (ctx) {
for (j = 0; j < ctx->name_count; j++) {
- if (MINOR(ctx->names[j].dev)==value) {
+ if ( audit_comparator(
+ MINOR(ctx->names[j].dev),
+ op, value)
+ ) {
++result;
break;
}
@@ -470,7 +518,9 @@ static int audit_filter_rules(struct tas
case AUDIT_INODE:
if (ctx) {
for (j = 0; j < ctx->name_count; j++) {
- if (ctx->names[j].ino == value) {
+ if ( audit_comparator(
+ ctx->names[j].ino, op, value)
+ ) {
++result;
break;
}
@@ -480,19 +530,20 @@ static int audit_filter_rules(struct tas
case AUDIT_LOGINUID:
result = 0;
if (ctx)
- result = (ctx->loginuid == value);
+ result = audit_comparator(ctx->loginuid, op,
+ value);
break;
case AUDIT_ARG0:
case AUDIT_ARG1:
case AUDIT_ARG2:
case AUDIT_ARG3:
if (ctx)
- result = (ctx->argv[field-AUDIT_ARG0]==value);
+ result = audit_comparator(
+ ctx->argv[field-AUDIT_ARG0],
+ op, value);
break;
}
- if (rule->fields[i] & AUDIT_NEGATE)
- result = !result;
if (!result)
return 0;
}
@@ -563,27 +614,26 @@ static int audit_filter_user_rules(struc
int i;
for (i = 0; i < rule->field_count; i++) {
- u32 field = rule->fields[i] & ~AUDIT_NEGATE;
+ u32 field = rule->fields[i] & ~AUDIT_OPERATORS;
+ u32 op = rule->fields[i] & AUDIT_OPERATORS;
u32 value = rule->values[i];
int result = 0;
switch (field) {
case AUDIT_PID:
- result = (cb->creds.pid == value);
+ result = audit_comparator(cb->creds.pid, op, value);
break;
case AUDIT_UID:
- result = (cb->creds.uid == value);
+ result = audit_comparator(cb->creds.uid, op, value);
break;
case AUDIT_GID:
- result = (cb->creds.gid == value);
+ result = audit_comparator(cb->creds.gid, op, value);
break;
case AUDIT_LOGINUID:
- result = (cb->loginuid == value);
+ result = audit_comparator(cb->loginuid, op, value);
break;
}
- if (rule->fields[i] & AUDIT_NEGATE)
- result = !result;
if (!result)
return 0;
}
19 years, 1 month
[PATCH] Audit filter rule operators (2/2)
by Dustin Kirkland
This is the kernel space component of this patch.
This patch defines the bitmask values of each of the 6 comparators (and
includes a nice documentation chart explaning how they were chosen).
It also adds a new function, audit_comparator(left, op, right). This
function will perform the specified comparison (op, which defaults to
"==" for backward compatibility) between two values (left and right).
If the negate bit is on, it will negate whatever that result was. This
value is returned.
Hence, I was able to replace all of the "==" tests with the new
audit_comparator() function pretty cleanly.
I didn't add audit_comparator() to audit.h... Should I? Might this be
used elsewhere in the audit system?
Comments welcome. I've run this against gang of manual tests and it
seems to work very well :) I'll commence with LTP regression testing
first of next week.
:-Dustin
diff -urpbBN linux-2.6.14-rc4/include/linux/audit.h
linux-2.6.14-rc4-audit_ops/include/linux/audit.h
--- linux-2.6.14-rc4/include/linux/audit.h 2005-10-19 09:40:27.000000000 -0500
+++ linux-2.6.14-rc4-audit_ops/include/linux/audit.h 2005-10-21 18:05:43.000000000 -0500
@@ -128,8 +128,29 @@
#define AUDIT_ARG2 (AUDIT_ARG0+2)
#define AUDIT_ARG3 (AUDIT_ARG0+3)
-#define AUDIT_NEGATE 0x80000000
+/* These are the supported operators.
+ 4 2 1
+ > < =
+ -------
+ 0 0 0 0 undef
+ 0 0 1 1 =
+ 0 1 0 2 <
+ 0 1 1 3 <=
+ 1 0 0 4 >
+ 1 0 1 5 >=
+ 1 1 0 6 !=
+ 1 1 1 7 range
+ */
+#define AUDIT_OPERATORS 0xF0000000
+#define AUDIT_EQUAL 0x10000000
+#define AUDIT_LESS_THAN 0x20000000
+#define AUDIT_LESS_THAN_OR_EQUAL 0x30000000
+#define AUDIT_GREATER_THAN 0x40000000
+#define AUDIT_GREATER_THAN_OR_EQUAL 0x50000000
+#define AUDIT_NOT_EQUAL 0x60000000
+#define AUDIT_RANGE 0x70000000
+#define AUDIT_NEGATE 0x80000000
/* Status symbols */
/* Mask values */
diff -urpbBN linux-2.6.14-rc4/kernel/auditsc.c linux-2.6.14-rc4-audit_ops/kernel/auditsc.c
--- linux-2.6.14-rc4/kernel/auditsc.c 2005-10-19 09:40:29.000000000 -0500
+++ linux-2.6.14-rc4-audit_ops/kernel/auditsc.c 2005-10-21 18:08:32.000000000 -0500
@@ -385,6 +385,36 @@ int audit_receive_filter(int type, int p
return err;
}
+static int audit_comparator(const u32 left, const u32 operator, const u32 right)
+{
+ int rc;
+ switch (operator) {
+ case AUDIT_LESS_THAN:
+ rc = (left < right);
+ break;
+ case AUDIT_LESS_THAN_OR_EQUAL:
+ rc = (left <= right);
+ break;
+ case AUDIT_GREATER_THAN:
+ rc = (left > right);
+ break;
+ case AUDIT_GREATER_THAN_OR_EQUAL:
+ rc = (left >= right);
+ break;
+ case AUDIT_NOT_EQUAL:
+ rc = (left != right);
+ break;
+ case AUDIT_EQUAL:
+ default:
+ rc = (left == right);
+ break;
+ }
+ if ( operator & AUDIT_NEGATE )
+ return !rc;
+ else
+ return rc;
+}
+
/* Compare a task_struct with an audit_rule. Return 1 on match, 0
* otherwise. */
static int audit_filter_rules(struct task_struct *tsk,
@@ -395,62 +425,63 @@ static int audit_filter_rules(struct tas
int i, j;
for (i = 0; i < rule->field_count; i++) {
- u32 field = rule->fields[i] & ~AUDIT_NEGATE;
+ u32 field = rule->fields[i] & ~AUDIT_OPERATORS;
+ u32 op = rule->fields[i] & AUDIT_OPERATORS;
u32 value = rule->values[i];
int result = 0;
switch (field) {
case AUDIT_PID:
- result = (tsk->pid == value);
+ result = audit_comparator(tsk->pid, op, value);
break;
case AUDIT_UID:
- result = (tsk->uid == value);
+ result = audit_comparator(tsk->uid, op, value);
break;
case AUDIT_EUID:
- result = (tsk->euid == value);
+ result = audit_comparator(tsk->euid, op, value);
break;
case AUDIT_SUID:
- result = (tsk->suid == value);
+ result = audit_comparator(tsk->suid, op, value);
break;
case AUDIT_FSUID:
- result = (tsk->fsuid == value);
+ result = audit_comparator(tsk->fsuid, op, value);
break;
case AUDIT_GID:
- result = (tsk->gid == value);
+ result = audit_comparator(tsk->gid, op, value);
break;
case AUDIT_EGID:
- result = (tsk->egid == value);
+ result = audit_comparator(tsk->egid, op, value);
break;
case AUDIT_SGID:
- result = (tsk->sgid == value);
+ result = audit_comparator(tsk->sgid, op, value);
break;
case AUDIT_FSGID:
- result = (tsk->fsgid == value);
+ result = audit_comparator(tsk->fsgid, op, value);
break;
case AUDIT_PERS:
- result = (tsk->personality == value);
+ result = audit_comparator(tsk->personality, op, value);
break;
case AUDIT_ARCH:
if (ctx)
- result = (ctx->arch == value);
+ result = audit_comparator(ctx->arch, op, value);
break;
case AUDIT_EXIT:
if (ctx && ctx->return_valid)
- result = (ctx->return_code == value);
+ result = audit_comparator(ctx->return_code, op, value);
break;
case AUDIT_SUCCESS:
if (ctx && ctx->return_valid) {
if (value)
- result = (ctx->return_valid == AUDITSC_SUCCESS);
+ result = audit_comparator(ctx->return_valid, op, AUDITSC_SUCCESS);
else
- result = (ctx->return_valid == AUDITSC_FAILURE);
+ result = audit_comparator(ctx->return_valid, op, AUDITSC_FAILURE);
}
break;
case AUDIT_DEVMAJOR:
if (ctx) {
for (j = 0; j < ctx->name_count; j++) {
- if (MAJOR(ctx->names[j].dev)==value) {
+ if ( audit_comparator(MAJOR(ctx->names[j].dev), op, value) ) {
++result;
break;
}
@@ -460,7 +491,7 @@ static int audit_filter_rules(struct tas
case AUDIT_DEVMINOR:
if (ctx) {
for (j = 0; j < ctx->name_count; j++) {
- if (MINOR(ctx->names[j].dev)==value) {
+ if ( audit_comparator(MINOR(ctx->names[j].dev), op, value) ) {
++result;
break;
}
@@ -470,7 +501,7 @@ static int audit_filter_rules(struct tas
case AUDIT_INODE:
if (ctx) {
for (j = 0; j < ctx->name_count; j++) {
- if (ctx->names[j].ino == value) {
+ if ( audit_comparator(ctx->names[j].ino, op, value) ) {
++result;
break;
}
@@ -480,19 +511,17 @@ static int audit_filter_rules(struct tas
case AUDIT_LOGINUID:
result = 0;
if (ctx)
- result = (ctx->loginuid == value);
+ result = audit_comparator(ctx->loginuid, op, value);
break;
case AUDIT_ARG0:
case AUDIT_ARG1:
case AUDIT_ARG2:
case AUDIT_ARG3:
if (ctx)
- result = (ctx->argv[field-AUDIT_ARG0]==value);
+ result = audit_comparator(ctx->argv[field-AUDIT_ARG0], op, value);
break;
}
- if (rule->fields[i] & AUDIT_NEGATE)
- result = !result;
if (!result)
return 0;
}
19 years, 1 month
[PATCH] Audit filter rule operators (1/2)
by Dustin Kirkland
This is the user space component of this patch.
This patch basically modifies the manner in which the field/value pairs
are split. Previously, the code simply split on "=" and flipped a bit
if there was a "!" just before the "=".
I had to make this a bit smarter, and I think I did it cleanly using
strstr(). Each of the six operators (!=, >=, <=, =, >, <) are searched
for in the string until one "hits". Note that the 2-character
comparators are searched for first (for obvious reasons).
When there's a hit, the comparator bytes are overwritten with the null
byte to split the string, and the "f" and "v" (field and value,
respectively) pointers are set appropriately, as well as the "op"
variable, which is the bitmask of the corresponding comparator.
This op bitmask is OR'd with the field and netlink goes about passing
this information just as it previously did.
Note that I also constructed the symbol translation table, which is
useful to convert the operator bitmask constants back to their prettier
symbols (for error reporting as below).
My only concern is that *f and *v were const before, but now I'm
modifying them, overwriting the operator bytes. I suppose I could
strdup() this and work on that. Let me know if that's preferred.
Comments welcome.
:-Dustin
diff -urpN audit-1.0.7/lib/libaudit.c
audit-1.0.7-operators/lib/libaudit.c
--- audit-1.0.7/lib/libaudit.c 2005-10-17 12:40:22.000000000 -0500
+++ audit-1.0.7-operators/lib/libaudit.c 2005-10-21 11:37:31.000000000 -0500
@@ -615,26 +615,50 @@ int audit_rule_field(struct audit_rule *
int audit_rule_fieldpair(struct audit_rule *rule, const char *pair, int flags)
{
char buf[128];
- const char *f = pair;
- const char *v = strchr(pair, '=');
+ char *f = pair;
+ char *v;
+ int op;
int field;
int negated = 0;
int vlen;
-
+
+ /* 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';
+ *v++ = '\0';
+ op = AUDIT_GREATER_THAN_OR_EQUAL;
+ } else if ( v = strstr(pair, "<=") ) {
+ *v++ = '\0';
+ *v++ = '\0';
+ op = AUDIT_LESS_THAN_OR_EQUAL;
+ } else if ( v = strstr(pair, "=") ) {
+ *v++ = '\0';
+ op = AUDIT_EQUAL;
+ } else if ( v = strstr(pair, ">") ) {
+ *v++ = '\0';
+ op = AUDIT_GREATER_THAN;
+ } else if ( v = strstr(pair, "<") ) {
+ *v++ = '\0';
+ op = AUDIT_LESS_THAN;
+ }
+
if (!f || !v || f == v)
return -1;
- if (v > pair && v[-1] == '!')
- negated = 1;
-
- snprintf(buf, sizeof(buf), "%*.*s", (int)(v-f-negated),
- (int)(v-f-negated), f);
- audit_msg(LOG_DEBUG,"buf=%s\n", buf);
- if ((field = audit_name_to_field(buf)) < 0)
+ audit_msg(LOG_DEBUG,"buf=%s\n", f);
+ if ((field = audit_name_to_field(f)) < 0)
return -2;
- v++;
- audit_msg(LOG_DEBUG,"f%d%s%s\n", field, negated ? "!=" : "=", v);
- rule->fields[rule->field_count] = field | (negated ? AUDIT_NEGATE : 0);
+
+ audit_msg(LOG_DEBUG,"f%d%s%s\n", field, audit_operator_to_symbol(op), v);
+ rule->fields[rule->field_count] = field | op;
switch (field)
{
case AUDIT_UID:
diff -urpN audit-1.0.7/lib/lookup_table.c audit-1.0.7-operators/lib/lookup_table.c
--- audit-1.0.7/lib/lookup_table.c 2005-10-19 13:26:04.000000000 -0500
+++ audit-1.0.7-operators/lib/lookup_table.c 2005-10-20 17:28:40.000000000 -0500
@@ -220,6 +220,16 @@ static struct int_transtab elftab[] = {
};
#define AUDIT_ELF_NAMES (sizeof(elftab)/sizeof(elftab[0]))
+static struct transtab optab[] = {
+ { AUDIT_EQUAL, "=" },
+ { AUDIT_NOT_EQUAL, "!=" },
+ { AUDIT_GREATER_THAN, ">" },
+ { AUDIT_GREATER_THAN_OR_EQUAL, ">=" },
+ { AUDIT_LESS_THAN, "<" },
+ { AUDIT_LESS_THAN_OR_EQUAL, "<=" }
+};
+#define AUDIT_NUM_OPERATORS (sizeof(optab)/sizeof(optab[0]))
+
static int audit_lookup_name(struct transtab *table, int length,
const char *name)
{
@@ -367,3 +377,7 @@ int audit_elf_to_machine(unsigned int el
return -1;
}
+const char *audit_operator_to_symbol(int op)
+{
+ return audit_lookup_number(optab, AUDIT_NUM_OPERATORS, op);
+}
19 years, 1 month
audit 1.0.8 released
by Steve Grubb
Hello,
I've just released a new version of the audit daemon. It can be downloaded
from http://people.redhat.com/sgrubb/audit It will also be in rawhide
tomorrow. The Changelog is:
- Update man pages
- Add email alert for admin_space_left in auditd
- Aureport cleanups
- Add anomaly & response to anomaly reports to aureport
- Summary report runs by default in aureport
- Updated syscall number tables
This release represents the end of development for aureport. It is now in
maintenance mode. I found a couple minor problems with the syscall number
tables and corrected those. They are now updated with all the latest syscalls
in the 2.6.13 kernel. The man pages have been updated and hopefully improved.
Please let me know if there are any problems with this release.
Thanks,
-Steve
19 years, 1 month
Re: [PATCH] Audit filter rule operators (2/2)
by Dustin Kirkland
On 10/24/05, Steve Grubb <sgrubb(a)redhat.com> wrote:
> On Friday 21 October 2005 19:24, Dustin Kirkland wrote:
> > This patch defines the bitmask values of each of the 6 comparators (and
> > includes a nice documentation chart explaning how they were chosen).
>
> We need to go ahead and take the next 2 upper bits in the same patch and save
> those for future use. For now, if those bits are set, the kernel should
> reject the rule. To support this, we also need some code added to
> audit_add_rule to check that the operators is something the kernel
> understands.
I'm curious why we should seize these bits now? Why the magic number
'2'? Isn't it implied that the next N upper bits will be used for the
next agreed-upon useful purpose? What is the point in rejecting the
rule if those bits are set? The user should understand that if they're
running a kernel that doesn't understand the operations being passed to
it, it won't be able to do anything about it. What about the next two
bits beyond that? What if those are set? Do we just ignore them? For
that matter should we just split the u32 in half and reserve the upper
16 for special flags, and leave the lower 16 for constant enumerations?
I'm not against this, Steve. I'm just trying to understand the goal.
> > I didn't add audit_comparator() to audit.h... Should I? Might this be
> > used elsewhere in the audit system?
>
> Not unless you use it somewhere. Keep it local until the need arise to prevent
> name collisions.
Thanks, I was unclear on this.
> > diff -urpbBN linux-2.6.14-rc4/kernel/auditsc.c
> > linux-2.6.14-rc4-audit_ops/kernel/auditsc.c ---
> > linux-2.6.14-rc4/kernel/auditsc.c2005-10-19 09:40:29.000000000 -0500 +++
> > linux-2.6.14-rc4-audit_ops/kernel/auditsc.c2005-10-21 18:08:32.000000000
> > -0500 @@ -385,6 +385,36 @@ int audit_receive_filter(int type, int p
> > return err;
> > }
> >
> > +static int audit_comparator(const u32 left, const u32 operator, const u32
> > right) +{
> <snip>
> > +if ( operator & AUDIT_NEGATE )
> > +return !rc;
> > +else
> > +return rc;
> > +}
>
> Does this make sense? What does !< mean? I think AUDIT_NEGATE only makes sense
> in relation to AUDIT_EQUAL. It should be moved to that case if not eliminated
> outright.
Actually, I think the use of AUDIT_NEGATE should be deprecated all
together. As of this patch, we have two separate operators, one for "="
and one for "!=". AUDIT_NEGATE should never be used in future versions
of audit userspace.
On the other hand, we have to remain backward compatible, in the case
that the user has this patched kernel, but older audit userspace. In
that case, there was an implicit "=", and the AUDIT_NEGATE bit simply
negated the implied "=" when on.
Here's the reasoning I used for the code I previously submitted...
There is no longer an implicit "=", but instead a total of 6 operators
(including "=" and "!=" as separate operations).
I couldn't commandeer the existing AUDIT_NEGATE bit, so how best should
I deal with it logically and remain backward compatible?
It made the most sense to me to have the AUDIT_NEGATE bit simply negate
whatever the rest of the logic determined. In the one case where the
operation is "=", this was make it "!=", which preserves previous
functionality. In the rest of the cases, the table would read something
like this:
~(=) is !=
~(!=) is =
~(>) is <=
~(<) is >=
~(>=) is <
~(<=) is >
Which isn't terribly useful and in fact more confusing if you wrote code
in audit userspace to represent operators in such a way... But
logically, it is valid.
So we have to support AUDIT_NEGATE in so much as to maintain new kernel
compatibility with older audit userspace, though we can decree that the
AUDIT_NEGATE flag is not to be used anymore.
And as for interpreting AUDIT_NEGATE within the kernel, I think as long
as it's doing so in a logically valid manner and maintaining said
backward compatibility, the code should be acceptable.
:-Dustin
19 years, 1 month
Re: [PATCH] Audit filter rule operators (1/2)
by Dustin Kirkland
On 10/24/05, Steve Grubb <sgrubb(a)redhat.com> wrote:
> On Friday 21 October 2005 19:24, Dustin Kirkland wrote:
> > This is the user space component of this patch.
>
> Thanks. I'll merge this when I open the 1.1 series. That should be later this
> week.
Cool!
> > I had to make this a bit smarter, and I think I did it cleanly using
> > strstr(). Each of the six operators (!=, >=, <=, =, >, <) are searched
>
> Because of shell redirection, I wonder if we need to make another form of
> these. Like ".ne.", ".ge.", ".le.", ".eq.", ".gt.", ".lt." respectively.
> (Remember FORTRAN?)
It wouldn't be terribly difficult to add support for these in addition
to the symbols. Using the symbols, however, just means that you've got
to use double quotes, which doesn't seem like too much to ask to me.
But I'm fine with supporting the two-char-strings also, if you want.
I'll add that to the patch and test it if you're interested.
:-Dustin
19 years, 1 month
[PATCH] Audit filter rule operators (0/2)
by Dustin Kirkland
Hi-
Currently, audit only supports the "=" and "!=" operators in the -F
filter rules.
These two patches rework the support for "=" and "!=", and add support
for ">", ">=", "<", and "<=".
This turned out to be a pretty clean, and simply process. I ended up
using the high order bits of the "field", as suggested by Steve and Amy.
This allowed for no changes whatsoever to the netlink communications.
See the documentation within the patch in the include/linux/audit.h
area, where there is a table that explains the reasoning of the bitmask
assignments clearly.
There are two pieces to this patch.
The first is user space. The second is kernel space.
I'll briefly describe those changes in the following emails with the
code.
The interface looks something like this....
Audit all ipc messages by normal users
auditctl -a exit,always -S ipc -F "uid>=500"
Audit all opens by any user except for user 501:
auditctl -a exit,always -S open -F "uid>=0" -F "uid!=501"
and so on...
:-Dustin
19 years, 1 month