Discussion:
[patch] fix syscall speedup patch mips typo
Jason Baron
2006-03-03 16:03:26 UTC
Permalink
I think this one is vary obvious. oops.

thanks,

-Jason

--- audit-current/arch/mips/kernel/ptrace.c.bak 2006-03-03 10:46:51.000000000 -0500
+++ audit-current/arch/mips/kernel/ptrace.c 2006-03-03 10:55:46.000000000 -0500
@@ -468,7 +468,7 @@ static inline int audit_arch(void)
*/
asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
{
- if (audit_invoke_exit && entryexit)
+ if (audit_invoke_exit() && entryexit)
audit_syscall_exit(current, AUDITSC_RESULT(regs->regs[2]),
regs->regs[2]);

@@ -492,7 +492,7 @@ asmlinkage void do_syscall_trace(struct
current->exit_code = 0;
}
out:
- if (audit_invoke_entry && !entryexit)
+ if (audit_invoke_entry() && !entryexit)
audit_syscall_entry(current, audit_arch(), regs->regs[2],
regs->regs[4], regs->regs[5],
regs->regs[6], regs->regs[7]);
Alexander Viro
2006-03-03 16:40:14 UTC
Permalink
Post by Jason Baron
I think this one is vary obvious. oops.
Applied and pushed. I still think that this reduction of overhead makes
it interesting enough to get -mm testing directly. I _can_ take it
out to separate branch easily (it's the very end of audit.b2), but...
Steve Grubb
2006-03-04 13:40:20 UTC
Permalink
Applied and pushed.  I still think that this reduction of overhead makes
it interesting enough to get -mm testing directly.  I _can_ take it
out to separate branch easily (it's the very end of audit.b2), but...
Al, but the issue is that we have not verified if this adversely affects the
audit system in any way. We need to build it in a test kernel so that
regression tests can be run.

-Steve
Steve Grubb
2006-03-04 13:46:38 UTC
Permalink
Post by Jason Baron
I think this one is vary obvious. oops.
Ummm...your patch has never been posted to the linux-audit mail list yet. We
need to have the full patch posted so people can review it.

Thanks,
-Steve
Jason Baron
2006-03-06 15:32:01 UTC
Permalink
Post by Steve Grubb
Post by Jason Baron
I think this one is vary obvious. oops.
Ummm...your patch has never been posted to the linux-audit mail list yet. We
need to have the full patch posted so people can review it.
Thanks,
-Steve
Patch is below. The idea behind this patch is based on a suggestion from
Steve Grubb to not call 'audit_syscall_entry' and 'audit_syscall_exit' if
there are no audit rules loaded. This is problematic for the case where
audit_log() is called in the middle of a system call (since we don't have
the entry parameters). We address this issue by creating a partial system
call record for this case, which contains the system call data that is
available at exit time. The patch shows a 30% performance increase for the
case where no rules are loaded on testing system calls in a tight loop.

thanks,

-Jason


diff-tree 7f3c303e61f8b545ccae8d71aff79a04f9d34c07 (from 86ce1392578d50fe9e46887de9c2dcba03c187e8)
tree e9b042fdd42b089d33be2ce33537c555403aef50
parent 86ce1392578d50fe9e46887de9c2dcba03c187e8
author Jason Baron <***@redhat.com> 1141250157 -0500
committer Al Viro <***@zeniv.linux.org.uk> 1141312115 -0500

[PATCH] wrapping audit_syscall_exit()
Post by Steve Grubb
Post by Jason Baron
that was to make the inlines in audit.h work. if you have another way to
do it, i'd be more than happy to do it that way.
Maybe we could put invoke_audit at the top of the structure and document in
the struct that it must be the first item or things break. Then you could do
+static inline int invoke_audit_entry(void)
+{
+ int *invoke_audit = (int *)current->audit_context;
+ if (likely(!invoke_audit)
+ return 0;
+ return ( *invoke_audit = n_audit_rules );
+}
This will let the inlines work and keep the encapsulation of audit context to
auditsc.c. Albeit that we need documentation since its a gentleman's
agreement that the first entry in the structure has to be invoke_audit.
-Steve
ok. the patch below is against audit-current and should address these
concerns. I have not tested the audit partial path yet, though. thanks.

[AV: fixed race in audit_add_rule]

Signed-off-by: Al Viro <***@zeniv.linux.org.uk>

diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
index 5c1fb6a..4caeee9 100644
--- a/arch/i386/kernel/ptrace.c
+++ b/arch/i386/kernel/ptrace.c
@@ -670,9 +670,11 @@ int do_syscall_trace(struct pt_regs *reg
secure_computing(regs->orig_eax);

if (unlikely(current->audit_context)) {
- if (entryexit)
- audit_syscall_exit(current, AUDITSC_RESULT(regs->eax),
- regs->eax);
+ if (entryexit) {
+ if (audit_invoke_exit())
+ audit_syscall_exit(current, AUDITSC_RESULT(regs->eax),
+ regs->eax);
+ }
/* Debug traps, when using PTRACE_SINGLESTEP, must be sent only
* on the syscall exit path. Normally, when TIF_SYSCALL_AUDIT is
* not used, entry.S will call us only on syscall exit, not
@@ -719,14 +721,14 @@ int do_syscall_trace(struct pt_regs *reg
}
ret = is_sysemu;
out:
- if (unlikely(current->audit_context) && !entryexit)
+ if (audit_invoke_entry() && !entryexit)
audit_syscall_entry(current, AUDIT_ARCH_I386, regs->orig_eax,
- regs->ebx, regs->ecx, regs->edx, regs->esi);
+ regs->ebx, regs->ecx, regs->edx, regs->esi);
if (ret == 0)
return 0;

regs->orig_eax = -1; /* force skip of syscall restarting */
- if (unlikely(current->audit_context))
+ if (audit_invoke_exit())
audit_syscall_exit(current, AUDITSC_RESULT(regs->eax),
regs->eax);
return 1;
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
index 9887c87..bc3fdc0 100644
--- a/arch/ia64/kernel/ptrace.c
+++ b/arch/ia64/kernel/ptrace.c
@@ -1632,7 +1632,7 @@ syscall_trace_enter (long arg0, long arg
&& (current->ptrace & PT_PTRACED))
syscall_trace();

- if (unlikely(current->audit_context)) {
+ if (audit_invoke_entry()) {
long syscall;
int arch;

@@ -1656,7 +1656,7 @@ syscall_trace_leave (long arg0, long arg
long arg4, long arg5, long arg6, long arg7,
struct pt_regs regs)
{
- if (unlikely(current->audit_context)) {
+ if (audit_invoke_exit()) {
int success = AUDITSC_RESULT(regs.r10);
long result = regs.r8;

diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index f838b36..ddeec87 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -468,7 +468,7 @@ static inline int audit_arch(void)
*/
asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
{
- if (unlikely(current->audit_context) && entryexit)
+ if (audit_invoke_exit && entryexit)
audit_syscall_exit(current, AUDITSC_RESULT(regs->regs[2]),
regs->regs[2]);

@@ -492,7 +492,7 @@ asmlinkage void do_syscall_trace(struct
current->exit_code = 0;
}
out:
- if (unlikely(current->audit_context) && !entryexit)
+ if (audit_invoke_entry && !entryexit)
audit_syscall_entry(current, audit_arch(), regs->regs[2],
regs->regs[4], regs->regs[5],
regs->regs[6], regs->regs[7]);
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 400793c..068d114 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -537,16 +537,16 @@ void do_syscall_trace_enter(struct pt_re
&& (current->ptrace & PT_PTRACED))
do_syscall_trace();

- if (unlikely(current->audit_context))
+ if (audit_invoke_entry())
audit_syscall_entry(current,
#ifdef CONFIG_PPC32
- AUDIT_ARCH_PPC,
+ AUDIT_ARCH_PPC,
#else
- test_thread_flag(TIF_32BIT)?AUDIT_ARCH_PPC:AUDIT_ARCH_PPC64,
+ test_thread_flag(TIF_32BIT)?AUDIT_ARCH_PPC:AUDIT_ARCH_PPC64,
#endif
- regs->gpr[0],
- regs->gpr[3], regs->gpr[4],
- regs->gpr[5], regs->gpr[6]);
+ regs->gpr[0],
+ regs->gpr[3], regs->gpr[4],
+ regs->gpr[5], regs->gpr[6]);
}

void do_syscall_trace_leave(struct pt_regs *regs)
@@ -555,10 +555,10 @@ void do_syscall_trace_leave(struct pt_re
secure_computing(regs->gpr[0]);
#endif

- if (unlikely(current->audit_context))
+ if (audit_invoke_exit())
audit_syscall_exit(current,
- (regs->ccr&0x1000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
- regs->result);
+ (regs->ccr&0x1000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
+ regs->result);

if ((test_thread_flag(TIF_SYSCALL_TRACE)
#ifdef CONFIG_PPC64
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 37dfe33..a7e94f4 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -733,7 +733,7 @@ out:
asmlinkage void
syscall_trace(struct pt_regs *regs, int entryexit)
{
- if (unlikely(current->audit_context) && entryexit)
+ if (audit_invoke_exit() && entryexit)
audit_syscall_exit(current, AUDITSC_RESULT(regs->gprs[2]), regs->gprs[2]);

if (!test_thread_flag(TIF_SYSCALL_TRACE))
@@ -760,7 +760,7 @@ syscall_trace(struct pt_regs *regs, int
current->exit_code = 0;
}
out:
- if (unlikely(current->audit_context) && !entryexit)
+ if (audit_invoke_entry() && !entryexit)
audit_syscall_entry(current,
test_thread_flag(TIF_31BIT)?AUDIT_ARCH_S390:AUDIT_ARCH_S390X,
regs->gprs[2], regs->orig_gpr2, regs->gprs[3],
diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c
index 3f9746f..5516f2c 100644
--- a/arch/sparc64/kernel/ptrace.c
+++ b/arch/sparc64/kernel/ptrace.c
@@ -620,7 +620,7 @@ asmlinkage void syscall_trace(struct pt_
/* do the secure computing check first */
secure_computing(regs->u_regs[UREG_G1]);

- if (unlikely(current->audit_context) && syscall_exit_p) {
+ if (audit_invoke_exit() && syscall_exit_p) {
unsigned long tstate = regs->tstate;
int result = AUDITSC_SUCCESS;

@@ -650,7 +650,7 @@ asmlinkage void syscall_trace(struct pt_
}

out:
- if (unlikely(current->audit_context) && !syscall_exit_p)
+ if (audit_invoke_entry() && !syscall_exit_p)
audit_syscall_entry(current,
(test_thread_flag(TIF_32BIT) ?
AUDIT_ARCH_SPARC :
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 98e0939..26dde51 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -267,19 +267,19 @@ void syscall_trace(union uml_pt_regs *re
int is_singlestep = (current->ptrace & PT_DTRACE) && entryexit;
int tracesysgood;

- if (unlikely(current->audit_context)) {
- if (!entryexit)
+ if (!entryexit)
+ if(audit_invoke_entry())
audit_syscall_entry(current,
- HOST_AUDIT_ARCH,
- UPT_SYSCALL_NR(regs),
- UPT_SYSCALL_ARG1(regs),
- UPT_SYSCALL_ARG2(regs),
- UPT_SYSCALL_ARG3(regs),
- UPT_SYSCALL_ARG4(regs));
- else audit_syscall_exit(current,
- AUDITSC_RESULT(UPT_SYSCALL_RET(regs)),
- UPT_SYSCALL_RET(regs));
- }
+ HOST_AUDIT_ARCH,
+ UPT_SYSCALL_NR(regs),
+ UPT_SYSCALL_ARG1(regs),
+ UPT_SYSCALL_ARG2(regs),
+ UPT_SYSCALL_ARG3(regs),
+ UPT_SYSCALL_ARG4(regs));
+ else if (audit_invoke_exit())
+ audit_syscall_exit(current,
+ AUDITSC_RESULT(UPT_SYSCALL_RET(regs)),
+ UPT_SYSCALL_RET(regs));

/* Fake a debug trap */
if (is_singlestep)
diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
index 5320562..c669c78 100644
--- a/arch/x86_64/kernel/ptrace.c
+++ b/arch/x86_64/kernel/ptrace.c
@@ -603,24 +603,24 @@ asmlinkage void syscall_trace_enter(stru
&& (current->ptrace & PT_PTRACED))
syscall_trace(regs);

- if (unlikely(current->audit_context)) {
+ if (audit_invoke_entry()) {
if (test_thread_flag(TIF_IA32)) {
audit_syscall_entry(current, AUDIT_ARCH_I386,
- regs->orig_rax,
- regs->rbx, regs->rcx,
- regs->rdx, regs->rsi);
+ regs->orig_rax,
+ regs->rbx, regs->rcx,
+ regs->rdx, regs->rsi);
} else {
audit_syscall_entry(current, AUDIT_ARCH_X86_64,
- regs->orig_rax,
- regs->rdi, regs->rsi,
- regs->rdx, regs->r10);
+ regs->orig_rax,
+ regs->rdi, regs->rsi,
+ regs->rdx, regs->r10);
}
}
}

asmlinkage void syscall_trace_leave(struct pt_regs *regs)
{
- if (unlikely(current->audit_context))
+ if (audit_invoke_exit())
audit_syscall_exit(current, AUDITSC_RESULT(regs->rax), regs->rax);

if ((test_thread_flag(TIF_SYSCALL_TRACE)
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 1c47c59..5443dbb 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -83,6 +83,7 @@
#define AUDIT_CONFIG_CHANGE 1305 /* Audit system configuration change */
#define AUDIT_SOCKADDR 1306 /* sockaddr copied as syscall arg */
#define AUDIT_CWD 1307 /* Current working directory */
+#define AUDIT_SYSCALL_PARTIAL 1310 /* Partial syscall event */

#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */
#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */
@@ -320,6 +321,20 @@ 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_set_macxattr(const char *name);
+extern int audit_n_rules;
+static inline int audit_invoke_entry(void)
+{
+ if (likely(!current->audit_context))
+ return 0;
+ return (*((int *)current->audit_context) = audit_n_rules);
+}
+
+static inline int audit_invoke_exit(void)
+{
+ if (likely(!current->audit_context))
+ return 0;
+ return (*(int *)current->audit_context);
+}
#else
#define audit_alloc(t) ({ 0; })
#define audit_free(t) do { ; } while (0)
@@ -339,6 +354,9 @@ extern int audit_set_macxattr(const char
#define audit_avc_path(dentry, mnt) ({ 0; })
#define audit_signal_info(s,t) do { ; } while (0)
#define audit_set_macxattr(n) do { ; } while (0)
+#define audit_n_rules 0
+#define audit_invoke_entry() ({ 0; })
+#define audit_invoke_exit() ({ 0; })
#endif

#ifdef CONFIG_AUDIT
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index fbdd19c..aeaba84 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -334,6 +334,7 @@ static inline int audit_add_rule(struct
struct list_head *list)
{
struct audit_entry *e;
+ int dont_count = 0;

/* Do not use the _rcu iterator here, since this is the only
* addition routine. */
@@ -342,11 +343,17 @@ static inline int audit_add_rule(struct
return -EEXIST;
}

+ /* If either of these, don't count towards total */
+ if (entry->rule.listnr == AUDIT_FILTER_USER ||
+ entry->rule.listnr == AUDIT_FILTER_TYPE)
+ dont_count = 1;
if (entry->rule.flags & AUDIT_FILTER_PREPEND) {
list_add_rcu(&entry->list, list);
} else {
list_add_tail_rcu(&entry->list, list);
}
+ if (!dont_count)
+ audit_n_rules++;

return 0;
}
@@ -363,7 +370,11 @@ static inline int audit_del_rule(struct
list_for_each_entry(e, list, list) {
if (!audit_compare_rule(&entry->rule, &e->rule)) {
list_del_rcu(&e->list);
+ if (entry->rule.listnr == AUDIT_FILTER_USER ||
+ entry->rule.listnr == AUDIT_FILTER_TYPE)
+ audit_n_rules++;
call_rcu(&e->rcu, audit_free_rule_rcu);
+ audit_n_rules--;
return 0;
}
}
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index c317ef4..efbcae5 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -75,6 +75,9 @@ extern int audit_enabled;
* path_lookup. */
#define AUDIT_NAMES_RESERVED 7

+/* number of audit rules */
+int audit_n_rules;
+
/* When fs/namei.c:getname() is called, we store the pointer in name and
* we don't let putname() free it (instead we free all of the saved
* pointers at syscall exit time).
@@ -129,6 +132,9 @@ struct audit_aux_data_path {

/* The per-task audit context. */
struct audit_context {
+ int invoke_audit; /* 1 if we should do syscall auditing, important:
+ implementation relies on this item being the
+ first one in the data structure */
int in_syscall; /* 1 if task is in a syscall */
enum audit_state state;
unsigned int serial; /* serial number for record */
@@ -576,11 +582,14 @@ static void audit_log_exit(struct audit_
struct audit_aux_data *aux;
const char *tty;

- ab = audit_log_start(context, gfp_mask, AUDIT_SYSCALL);
+ ab = audit_log_start(context, gfp_mask,
+ context->in_syscall ? AUDIT_SYSCALL: AUDIT_SYSCALL_PARTIAL);
if (!ab)
return; /* audit_panic has been called */
- audit_log_format(ab, "arch=%x syscall=%d",
- context->arch, context->major);
+ if (context->in_syscall) {
+ audit_log_format(ab, "arch=%x syscall=%d",
+ context->arch, context->major);
+ }
if (context->personality != PER_LINUX)
audit_log_format(ab, " per=%lx", context->personality);
if (context->return_valid)
@@ -591,22 +600,38 @@ static void audit_log_exit(struct audit_
tty = current->signal->tty->name;
else
tty = "(none)";
- audit_log_format(ab,
- " a0=%lx a1=%lx a2=%lx a3=%lx items=%d"
- " pid=%d auid=%u uid=%u gid=%u"
- " euid=%u suid=%u fsuid=%u"
- " egid=%u sgid=%u fsgid=%u tty=%s",
- context->argv[0],
- context->argv[1],
- context->argv[2],
- context->argv[3],
- context->name_count,
- context->pid,
- context->loginuid,
- context->uid,
- context->gid,
- context->euid, context->suid, context->fsuid,
- context->egid, context->sgid, context->fsgid, tty);
+ if (context->in_syscall) {
+ audit_log_format(ab,
+ " a0=%lx a1=%lx a2=%lx a3=%lx items=%d"
+ " pid=%d auid=%u uid=%u gid=%u"
+ " euid=%u suid=%u fsuid=%u"
+ " egid=%u sgid=%u fsgid=%u tty=%s",
+ context->argv[0],
+ context->argv[1],
+ context->argv[2],
+ context->argv[3],
+ context->name_count,
+ context->pid,
+ context->loginuid,
+ context->uid,
+ context->gid,
+ context->euid, context->suid, context->fsuid,
+ context->egid, context->sgid, context->fsgid, tty);
+ } else {
+ audit_log_format(ab,
+ " items=%d"
+ " pid=%d auid=%u uid=%u gid=%u"
+ " euid=%u suid=%u fsuid=%u"
+ " egid=%u sgid=%u fsgid=%u tty=%s",
+ context->name_count,
+ context->pid,
+ context->loginuid,
+ context->uid,
+ context->gid,
+ context->euid, context->suid, context->fsuid,
+ context->egid, context->sgid, context->fsgid, tty);
+ }
+
audit_log_task_info(ab, gfp_mask);
audit_log_end(ab);

@@ -834,7 +859,7 @@ void audit_syscall_exit(struct task_stru
if (likely(!context))
goto out;

- if (context->in_syscall && context->auditable)
+ if (context->auditable)
audit_log_exit(context, GFP_KERNEL);

context->in_syscall = 0;
@@ -1110,6 +1135,7 @@ void auditsc_get_stamp(struct audit_cont
t->tv_nsec = ctx->ctime.tv_nsec;
*serial = ctx->serial;
ctx->auditable = 1;
+ ctx->invoke_audit = 1;
}

/**
Steve Grubb
2006-03-15 14:23:49 UTC
Permalink
The idea behind this patch is based on a suggestion to not call
'audit_syscall_entry' and 'audit_syscall_exit' if there are no audit rules
loaded.
We are starting to get problem reports with this patch. It appears that
nothing sets ctime when the event is started via an avc. The patch below
takes a stab at fixing this. Does it look correct?

-Steve


diff -urp linux-2.6.15.x86_64.orig/kernel/auditsc.c linux-2.6.15.x86_64/kernel/auditsc.c
--- linux-2.6.15.x86_64.orig/kernel/auditsc.c 2006-03-15 09:09:25.000000000 -0500
+++ linux-2.6.15.x86_64/kernel/auditsc.c 2006-03-15 09:07:22.000000000 -0500
@@ -1136,6 +1136,8 @@ void auditsc_get_stamp(struct audit_cont
{
if (!ctx->serial)
ctx->serial = audit_serial();
+ if (!ctx->ctime.tv_sec)
+ ctx->ctime = CURRENT_TIME;
t->tv_sec = ctx->ctime.tv_sec;
t->tv_nsec = ctx->ctime.tv_nsec;
*serial = ctx->serial;
Linda Knippers
2006-03-15 16:58:01 UTC
Permalink
Hi Steve,
Post by Steve Grubb
We are starting to get problem reports with this patch. It appears that
nothing sets ctime when the event is started via an avc. The patch below
takes a stab at fixing this. Does it look correct?
I'm seeing this on my system running the .12 kernel and the 1.1.4 tools.
I'm seeing more than just the zero time and a bunch of SOCKETCALL
messages. I also get a message of type UNKNOWN, more AVCs with the
same serial number and then the serial number increments and I get
a bunch more stuff. See below. What's type 1310?

-- ljk

type=USER_START msg=audit(1142413321.732:665): user pid=6451 uid=0
auid=0 msg='PAM: session open acct=root : exe="/usr/sbin/crond"
(hostname=?, addr=?, terminal=cron res=success)'
type=CRED_ACQ msg=audit(1142413321.732:666): user pid=6451 uid=0 auid=0
msg='PAM: setcred acct=root : exe="/usr/sbin/crond" (hostname=?, addr=?,
terminal=cron res=success)'
type=AVC msg=audit(0.000:667): avc: denied { read } for pid=6764
comm="perl" name="resolv.conf" dev=dm-0 ino=4523009
scontext=system_u:system_r:logwatch_t:s0-s15:c0.c255
tcontext=system_u:object_r:net_conf_t:s0 tclass=file
type=UNKNOWN[1310] msg=audit(0.000:667): success=yes exit=3 items=0
pid=6764 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0
tty=(none) comm="perl" exe="/usr/bin/perl"
subj=system_u:system_r:logwatch_t:s0-s15:c0.c255
type=SOCKADDR msg=audit(0.000:667):
saddr=01002F7661722F72756E2F6E7363642F736F636B6574000000000000000029895600B4F75F00E4C6750948E18EBF3F7B500008C075098070830910A5770929895600F0AB8709F0AB870970688709BD785600A8CF8409B0CF840908000000B4F75F0058B179097300000048E08EBF
type=SOCKETCALL msg=audit(0.000:667): nargs=3 a0=3 a1=bf8edf6e a2=6e
type=SOCKETCALL msg=audit(0.000:667): nargs=3 a0=1 a1=1 a2=0
type=SOCKADDR msg=audit(0.000:667):
saddr=01002F7661722F72756E2F6E7363642F736F636B6574006E5B0000000000000000002051AF0010000000201686091000000008C0750926A47709180000002C51AF00F43FAF002051AF002816860988DE8EBF6980A300FF7F0000281686090500000058DE8EBF10EA5C0020000000
type=SOCKETCALL msg=audit(0.000:667): nargs=3 a0=3 a1=bf8edde6 a2=6e
type=SOCKETCALL msg=audit(0.000:667): nargs=3 a0=1 a1=1 a2=0

(lots of stuff deleted..then more things with the same serial number)

type=AVC msg=audit(0.000:667): avc: denied { write } for pid=6764
comm="perl" laddr=16.116.96.237 lport=32773 faddr=16.64.64.51 fport=53
scontext=system_u:system_r:logwatch_t:s0-s15:c0.c255
tcontext=system_u:system_r:logwatch_t:s0-s15:c0.c255 tclass=udp_socket
type=AVC msg=audit(0.000:667): avc: denied { udp_send } for pid=6764
comm="perl" saddr=16.116.96.237 src=32773 daddr=16.64.64.51 dest=53
netif=eth0 scontext=system_u:system_r:logwatch_t:s0-s15:c0.c255
tcontext=system_u:object_r:netif_t:s0-s15:c0.c255 tclass=netif
type=AVC msg=audit(0.000:667): avc: denied { udp_send } for pid=6764
comm="perl" saddr=16.116.96.237 src=32773 daddr=16.64.64.51 dest=53
netif=eth0 scontext=system_u:system_r:logwatch_t:s0-s15:c0.c255
tcontext=system_u:object_r:node_t:s0-s15:c0.c255 tclass=node
type=AVC msg=audit(0.000:667): avc: denied { send_msg } for pid=6764
comm="perl" saddr=16.116.96.237 src=32773 daddr=16.64.64.51 dest=53
netif=eth0 scontext=system_u:system_r:logwatch_t:s0-s15:c0.c255
tcontext=system_u:object_r:dns_port_t:s0 tclass=udp_socket
type=AVC msg=audit(0.000:667): avc: denied { sendto } for pid=6764
comm="perl" scontext=system_u:system_r:logwatch_t:s0-s15:c0.c255
tcontext=system_u:object_r:unlabeled_t:s15:c0.c255 tclass=association
type=UNKNOWN[1310] msg=audit(0.000:667): success=yes exit=45 items=0
pid=6764 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0
tty=(none) comm="perl" exe="/usr/bin/perl"
subj=system_u:system_r:logwatch_t:s0-s15:c0.c255
type=SOCKETCALL msg=audit(0.000:667): nargs=4 a0=3 a1=bf8ed730 a2=2d a3=0
type=AVC msg=audit(0.000:668): avc: denied { udp_recv } for pid=6443
comm="floaters" saddr=16.64.64.51 src=53 daddr=16.116.96.237 dest=32773
netif=eth0 scontext=system_u:system_r:logwatch_t:s0-s15:c0.c255
tcontext=system_u:object_r:netif_t:s0-s15:c0.c255 tclass=netif
Steve Grubb
2006-03-15 17:09:55 UTC
Permalink
Post by Linda Knippers
I also get a message of type UNKNOWN, more AVCs with the
same serial number and then the serial number increments and I get
a bunch more stuff.  See below.  What's type 1310?
SYSCALL_PARTIAL. audit 1.1.5 knows what that is.

I'm seeing the something similar and was just talking with Jason about it. We
are still mulling over what's really happening. Is it stacking contexts or
something weird happening on output.

On my system, I had a hald avc message repeat 5 times. It was nothing to do
with socketcall. The trick to recreating the problem seems to be not having
audit rules loaded and letting normal system avcs do their thing.

-Steve
V***@vt.edu
2006-03-15 17:15:31 UTC
Permalink
Post by Steve Grubb
On my system, I had a hald avc message repeat 5 times. It was nothing to do
with socketcall. The trick to recreating the problem seems to be not having
audit rules loaded and letting normal system avcs do their thing.
Yep, that would be my config - /etc/audit.rules and /etc/auditd.conf are
as shipped in the RPM (audit-1.1.5-1).
Linda Knippers
2006-03-15 17:39:20 UTC
Permalink
Post by Steve Grubb
SYSCALL_PARTIAL. audit 1.1.5 knows what that is.
When is a SYSCALL_PARTIAL emitted, vs a SYSCALL?

-- ljk
Steve Grubb
2006-03-15 18:13:58 UTC
Permalink
Post by Linda Knippers
When is a SYSCALL_PARTIAL emitted, vs a SYSCALL?
Whenever there are no audit rules loaded and an AVC message is triggered. We
just grab what's readily available which means we don't have the arch,
syscall, or args. Everything else should be there.

-Steve
Linda Knippers
2006-03-15 19:31:13 UTC
Permalink
Post by Steve Grubb
Post by Linda Knippers
When is a SYSCALL_PARTIAL emitted, vs a SYSCALL?
Whenever there are no audit rules loaded and an AVC message is triggered. We
just grab what's readily available which means we don't have the arch,
syscall, or args. Everything else should be there.
I don't understand why this record is a good idea. It seems to
duplicate alot of information that is already in the AVC message
and if someone wanted the syscall to be audited, they'd audit it.

type=AVC msg=audit(0.000:45): avc: denied { search } for pid=1690
comm="sh" name="/" dev=devpts ino=1
scontext=system_u:system_r:insmod_t:s0-s15:c0.c255
tcontext=system_u:object_r:devpts_t:s15:c0.c255 tclass=dir
type=UNKNOWN[1310] msg=audit(0.000:45): success=yes exit=3 items=0
pid=1690 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0
fsgid=0 tty=(none) comm="sh" exe="/bin/bash"
subj=system_u:system_r:insmod_t:s0-s15:c0.c255

The only value I can see in the second record is that it tells me I'm
in permissive mode because the syscall succeeded, but I don't think
that's a good enough reason to have the record.

-- ljk
Linda Knippers
2006-03-15 19:43:39 UTC
Permalink
Post by Steve Grubb
Post by Linda Knippers
When is a SYSCALL_PARTIAL emitted, vs a SYSCALL?
Whenever there are no audit rules loaded and an AVC message is
triggered. We just grab what's readily available which means we don't
have the arch, syscall, or args. Everything else should be there.
I also don't understand how this is related to improving performance
when there are no audit rules. It seems like it doubles the cost of
an AVC message.

-- ljk
Steve Grubb
2006-03-15 19:55:28 UTC
Permalink
Post by Linda Knippers
I also don't understand how this is related to improving performance
when there are no audit rules.  It seems like it doubles the cost of
an AVC message.
The cost is not in the hot path. That's the key. The speedup is measurable.

-Steve
Steve Grubb
2006-03-15 19:54:10 UTC
Permalink
Post by Linda Knippers
I don't understand why this record is a good idea.
Because it gives you extra information to search on. Suppose you wanted to see
any failed log messages for auid 501. Without the partial record, you won't
have the information for ausearch to key on.

-Steve
Linda Knippers
2006-03-15 20:04:33 UTC
Permalink
Post by Steve Grubb
Post by Linda Knippers
I don't understand why this record is a good idea.
Because it gives you extra information to search on. Suppose you wanted to see
any failed log messages for auid 501. Without the partial record, you won't
have the information for ausearch to key on.
Considering all the information that's duplicated, it seems like a
pretty heavyweight way to get the auid, and going back to Jason's
original mail, this doesn't seem to be the reason it was added.
Post by Steve Grubb
Patch is below. The idea behind this patch is based on a suggestion from
Steve Grubb to not call 'audit_syscall_entry' and 'audit_syscall_exit' if
there are no audit rules loaded. This is problematic for the case where
audit_log() is called in the middle of a system call (since we don't have
the entry parameters). We address this issue by creating a partial system
call record for this case, which contains the system call data that is
available at exit time.
I can understand wanting to optimize the code when there are no audit
rules (although one could optimize it by disabling audit) but the fact
that it created a problem for which the partial record is a solution
makes me question the approach.

-- ljk
Steve Grubb
2006-03-15 20:14:49 UTC
Permalink
Post by Linda Knippers
Considering all the information that's duplicated, it seems like a
pretty heavyweight way to get the auid,
Linda, this is not heavyweight. This is providing as much information as is
available to keep the record as close as possible to what we had before.
Post by Linda Knippers
and going back to Jason's original mail, this doesn't seem to be the reason
it was added.
Linda, regardless of what the email says, that was the reason. I was there. :)
Post by Linda Knippers
I can understand wanting to optimize the code when there are no audit
rules (although one could optimize it by disabling audit)
No because then you lose the avc messages going to the audit system.

-Steve
Stephen Smalley
2006-03-15 20:26:55 UTC
Permalink
Post by Steve Grubb
Post by Linda Knippers
I can understand wanting to optimize the code when there are no audit
rules (although one could optimize it by disabling audit)
No because then you lose the avc messages going to the audit system.
You should be able to disable syscall auditing while leaving the base
audit framework enabled, so you'd still get avc messages, just no
syscall audit messages. It used to work that way, don't know for
certain for the current situation. In fact, unless you enabled syscall
auditing via audit=1 or auditctl, it used to be the case that you would
only get avc messages.
--
Stephen Smalley
National Security Agency
Linda Knippers
2006-03-15 20:37:16 UTC
Permalink
Post by Stephen Smalley
Post by Steve Grubb
Post by Linda Knippers
I can understand wanting to optimize the code when there are no audit
rules (although one could optimize it by disabling audit)
No because then you lose the avc messages going to the audit system.
You should be able to disable syscall auditing while leaving the base
audit framework enabled, so you'd still get avc messages, just no
syscall audit messages. It used to work that way, don't know for
certain for the current situation. In fact, unless you enabled syscall
auditing via audit=1 or auditctl, it used to be the case that you would
only get avc messages.
When I disable syscall auditing via auditctl, I get the avc messages
in the audit log, but I also occasionally get the partial record, which
shows up for me as UNKNOWN because my user-space tools are old.

type=AVC msg=audit(1142454769.018:874): avc: denied { read } for
pid=23886 comm="lpq" name="lpoptions" dev=dm-0 ino=4523611
scontext=system_u:system_r:initrc_t:s15:c0.c255
tcontext=root:object_r:cupsd_etc_t:s0 tclass=file
type=AVC msg=audit(0.000:765): avc: denied { use } for pid=9321
comm="bash" name="3" dev=devpts ino=5
scontext=system_u:system_r:initrc_t:s15:c0.c255
tcontext=system_u:system_r:initrc_t:s0-s15:c0.c255 tclass=fd
type=UNKNOWN[1310] msg=audit(0.000:765): success=yes exit=1 items=0
pid=9321 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0
fsgid=0 tty=pts3 comm="bash" exe="/bin/bash"
subj=system_u:system_r:initrc_t:s15:c0.c255
type=AVC_PATH msg=audit(0.000:765): path="/dev/pts/3"

When we get a partial record, the timestamp and serial number are wrong.

-- ljk
Steve Grubb
2006-03-15 20:52:44 UTC
Permalink
Post by Linda Knippers
When we get a partial record, the timestamp and serial number are wrong.
Right, the patch I sent this morning fixes the one case. This is the kind of
bugs that I wanted to find via cert tests. We need to simply fix the bug. If
we dropped the partial record, that would still not solve the problem.

-Steve
Stephen Smalley
2006-03-15 20:24:54 UTC
Permalink
Post by Steve Grubb
Post by Linda Knippers
I don't understand why this record is a good idea.
Because it gives you extra information to search on. Suppose you wanted to see
any failed log messages for auid 501. Without the partial record, you won't
have the information for ausearch to key on.
So perhaps that information should be added to the avc messages? auid
is easy enough. We'd still lose exe=, paths, etc, but this entire
scenario only occurs when there are no audit rules at all, right, so for
any evaluated system, we would still have the full syscall audit records
emitted since they would have audit rules?
--
Stephen Smalley
National Security Agency
Steve Grubb
2006-03-15 20:27:41 UTC
Permalink
Post by Stephen Smalley
So perhaps that information should be added to the avc messages?
But then when people are using the audit system and have rules, we have
duplicated information. The way it is, we only have 2 pieces of duplicated
information, comm & subj. But we have that duplication under normal
circumstances, too.
Post by Stephen Smalley
we would still have the full syscall audit records emitted since they would
have audit rules?
That is true.

-Steve
Amy Griffis
2006-03-15 20:05:25 UTC
Permalink
Hi Jason,
Post by Jason Baron
Patch is below. The idea behind this patch is based on a suggestion from
Steve Grubb to not call 'audit_syscall_entry' and 'audit_syscall_exit' if
there are no audit rules loaded. This is problematic for the case where
audit_log() is called in the middle of a system call (since we don't have
the entry parameters). We address this issue by creating a partial system
call record for this case, which contains the system call data that is
available at exit time. The patch shows a 30% performance increase for the
case where no rules are loaded on testing system calls in a tight loop.
For your baseline measurement, was syscall auditing enabled or
disabled?

Thanks,
Amy
Jason Baron
2006-03-15 20:36:42 UTC
Permalink
Post by Amy Griffis
Hi Jason,
Post by Jason Baron
Patch is below. The idea behind this patch is based on a suggestion from
Steve Grubb to not call 'audit_syscall_entry' and 'audit_syscall_exit' if
there are no audit rules loaded. This is problematic for the case where
audit_log() is called in the middle of a system call (since we don't have
the entry parameters). We address this issue by creating a partial system
call record for this case, which contains the system call data that is
available at exit time. The patch shows a 30% performance increase for the
case where no rules are loaded on testing system calls in a tight loop.
For your baseline measurement, was syscall auditing enabled or
disabled?
the baseline is audit enabled (ie audit_enabled=1) with no rules and no
speedup patch. This was compared with audit enabled with no rules but with
the speedup patch.

-Jason
Amy Griffis
2006-03-15 20:33:29 UTC
Permalink
Post by Jason Baron
Post by Amy Griffis
Hi Jason,
Post by Jason Baron
Patch is below. The idea behind this patch is based on a suggestion from
Steve Grubb to not call 'audit_syscall_entry' and 'audit_syscall_exit' if
there are no audit rules loaded. This is problematic for the case where
audit_log() is called in the middle of a system call (since we don't have
the entry parameters). We address this issue by creating a partial system
call record for this case, which contains the system call data that is
available at exit time. The patch shows a 30% performance increase for the
case where no rules are loaded on testing system calls in a tight loop.
For your baseline measurement, was syscall auditing enabled or
disabled?
the baseline is audit enabled (ie audit_enabled=1) with no rules and no
speedup patch. This was compared with audit enabled with no rules but with
the speedup patch.
I would be interested seeing numbers for audit_enabled=0 versus
audit_enabled=1 with speedup patch (both cases having no rules).

Why can't a user just disable syscall auditing if they aren't
interested in adding rules?

Thanks,
Amy
Steve Grubb
2006-03-15 20:39:46 UTC
Permalink
Post by Amy Griffis
Why can't a user just disable syscall auditing if they aren't
interested in adding rules?
because then the avc messages go to syslog.

-Steve
Jason Baron
2006-03-15 20:58:49 UTC
Permalink
Post by Steve Grubb
Post by Amy Griffis
Why can't a user just disable syscall auditing if they aren't
interested in adding rules?
because then the avc messages go to syslog.
hmmm, couldn't auditd keep track of the number of rules and enable or
disable syscall auditing as appropriate?

-Jason
Steve Grubb
2006-03-15 21:02:23 UTC
Permalink
Post by Jason Baron
couldn't auditd keep track of the number of rules and enable or
disable syscall auditing as appropriate?
The simple answer is no.

-Steve
Linda Knippers
2006-03-15 22:45:28 UTC
Permalink
Post by Steve Grubb
Post by Jason Baron
couldn't auditd keep track of the number of rules and enable or
disable syscall auditing as appropriate?
The simple answer is no.
What's the not-so-simple answer? That sounds like an interesting idea.

-- ljk
Amy Griffis
2006-03-15 20:50:39 UTC
Permalink
Post by Steve Grubb
Post by Amy Griffis
Why can't a user just disable syscall auditing if they aren't
interested in adding rules?
because then the avc messages go to syslog.
Nothing should depend on syscall auditing. That is the way this audit
system was designed. If something is depending on it now, then it is
broken and needs to be fixed.

We don't need multiple ways to disable syscall auditing.

Amy
Amy Griffis
2006-03-16 17:52:01 UTC
Permalink
Hello,

There have been several concerns raised about this patch, so I did
some digging to find out what's really happening here.
Post by Jason Baron
Patch is below. The idea behind this patch is based on a suggestion
from Steve Grubb to not call 'audit_syscall_entry' and
'audit_syscall_exit' if there are no audit rules loaded. This is
problematic for the case where audit_log() is called in the middle
of a system call (since we don't have the entry parameters).
First, there are several problems with the AUDIT_SYSCALL_PARTIAL
record. It is true that audit_log() may be called in the middle of a
syscall, but it does not depend on the entry parameters or anything
else in the audit_context.

The check that results in an AUDIT_SYSCALL_PARTIAL record was added in
audit_log_exit(), which is quite different from an audit_log() call.
In addition to being called on syscall exit, audit_log_exit() is
called when a task is destroyed or in the error path of
copy_process(). The idea being that if we've marked that we want to
log a record and we don't make it to syscall exit, we can still log
the record at that point.

So, how do we determine that we want to log a record? One way is
through filtering, if any rules match something in the audit_context.
The other way is through audit_get_stamp() which is called as part of
audit_log(). When audit_get_stamp() is called, it determines the
timestamp and serial number for the record based on the existence of
an audit_context. If there is no audit_context, it generates a new
timestamp and serial number. If the audit_context exists, it uses the
context's timestamp and serial number so all records generated in a
given syscall will have the same identifiers. In the latter case, it
also marks that we want to generate an audit record.

This is interesting because if you have audit_enabled=1, you will
always get an AUDIT_SYSCALL record for any syscall during which a
record was logged outside of audit (e.g. SELinux). If you have
audit_enabled=0, you get only the externally generated records.

This patch avoids the record that would be generated on syscall exit,
but then emits it as AUDIT_SYSCALL_PARTIAL when the task exits.
Previously, these contents would be logged on every syscall exit, and
would only be logged on task exit in the case that it happened prior
to syscall exit.

As a user, you need to decide if you want the syscall records or not.
If you want them, then you need to pay the performance penalty for
collecting their information and logging them when they are triggered.
This mechanism of trying to eliminate some of their necessary
processing and then logging them at incorrect times is just bogus.
The audit_enabled flag was created to turn off the overhead of
creating syscall records. That is the mechanism that should be used
to achieve the 30% performance gain.

When you set audit_enabled=0, what will your log records look like?

For one, you won't see the syscall records discussed above, and I
would argue that users only interested in records generated by SELinux
don't care about these. The other difference is that calls to
audit_get_loginuid() will return -1 since there is no audit_context.
As audit_get_loginuid() is called from other places besides SELinux,
the real solution is to extract audit's preserving of the loginuid
from the syscall auditing functionality. This would allow a user with
no audit rules to set audit_enabled=0 and see the same SELinux records
as they currently do with audit_enabled=1, while achieving the 30%
performance improvement.

Allowing a user to set audit_enabled manually gives them the
flexibility to determine whether they want to see the extra syscall
records mentioned above. If we determined that a user with no rules
doesn't want to see *any* syscall records, it wouldn't be difficult
for the kernel to automatically set audit_enabled=0 when there are no
rules, and turn it back on when a rule is added.

Additionally, David Woodhouse did some work to separate the filtering
for userspace messages (AUDIT_USER, etc.) from the syscall filtering.
This patch is currently in the audit git tree. By simply removing the
check for audit_enabled in audit_receive_msg(), we can allow userspace
to send messages, including AUDIT_USER_AVC messages, when syscall
auditing is disabled.

The justification for this patch (mostly discussed offlist) was that
many users are only interested in using audit to log records from
SELinux but don't want to incur the performance penalty of syscall
auditing. Fixing the loginuid and allowing userspace messages in the
absence of syscall auditing should cover their requirements and allow
them to simply turn syscall auditing off.

Regards,
Amy
Stephen Smalley
2006-03-16 18:22:10 UTC
Permalink
Post by Amy Griffis
The justification for this patch (mostly discussed offlist) was that
many users are only interested in using audit to log records from
SELinux but don't want to incur the performance penalty of syscall
auditing. Fixing the loginuid and allowing userspace messages in the
absence of syscall auditing should cover their requirements and allow
them to simply turn syscall auditing off.
This makes more sense to me. Further, it seems like someone should be
working on making the syscall audit processing more efficient so that
people aren't driven to disabling syscall auditing just because it is so
costly. Optimizing only for the users who don't need/want syscall
auditing ensures that it will always remain a niche feature with a small
user community.
--
Stephen Smalley
National Security Agency
Jason Baron
2006-03-16 18:29:19 UTC
Permalink
Post by Amy Griffis
Hello,
There have been several concerns raised about this patch, so I did
some digging to find out what's really happening here.
Post by Jason Baron
Patch is below. The idea behind this patch is based on a suggestion
from Steve Grubb to not call 'audit_syscall_entry' and
'audit_syscall_exit' if there are no audit rules loaded. This is
problematic for the case where audit_log() is called in the middle
of a system call (since we don't have the entry parameters).
First, there are several problems with the AUDIT_SYSCALL_PARTIAL
record. It is true that audit_log() may be called in the middle of a
syscall, but it does not depend on the entry parameters or anything
else in the audit_context.
The check that results in an AUDIT_SYSCALL_PARTIAL record was added in
audit_log_exit(), which is quite different from an audit_log() call.
In addition to being called on syscall exit, audit_log_exit() is
called when a task is destroyed or in the error path of
copy_process(). The idea being that if we've marked that we want to
log a record and we don't make it to syscall exit, we can still log
the record at that point.
So, how do we determine that we want to log a record? One way is
through filtering, if any rules match something in the audit_context.
The other way is through audit_get_stamp() which is called as part of
audit_log(). When audit_get_stamp() is called, it determines the
timestamp and serial number for the record based on the existence of
an audit_context. If there is no audit_context, it generates a new
timestamp and serial number. If the audit_context exists, it uses the
context's timestamp and serial number so all records generated in a
given syscall will have the same identifiers. In the latter case, it
also marks that we want to generate an audit record.
This is interesting because if you have audit_enabled=1, you will
always get an AUDIT_SYSCALL record for any syscall during which a
record was logged outside of audit (e.g. SELinux). If you have
audit_enabled=0, you get only the externally generated records.
This patch avoids the record that would be generated on syscall exit,
but then emits it as AUDIT_SYSCALL_PARTIAL when the task exits.
Previously, these contents would be logged on every syscall exit, and
would only be logged on task exit in the case that it happened prior
to syscall exit.
This is bug in the implementation then...i had intended to to have syscall
partials only emitted at syscall exit time, when say after selinux created
an avc message. Is this hard to fix?
Post by Amy Griffis
The justification for this patch (mostly discussed offlist) was that
many users are only interested in using audit to log records from
SELinux but don't want to incur the performance penalty of syscall
auditing. Fixing the loginuid and allowing userspace messages in the
absence of syscall auditing should cover their requirements and allow
them to simply turn syscall auditing off.
right, this is the the crux of the issue, whether or not the syscall
'partial' provides value for selinux or some other subsystem. If yes, then
the patch might be a good idea.

thanks,

-Jason
Stephen Smalley
2006-03-16 18:33:32 UTC
Permalink
Post by Jason Baron
right, this is the the crux of the issue, whether or not the syscall
'partial' provides value for selinux or some other subsystem. If yes, then
the patch might be a good idea.
Better to just a) allow people to cleanly disable syscall auditing
without impacting anything else if they don't want it at all, and b)
optimize the actual syscall audit processing so that it doesn't impose
such an overhead that people feel compelled to disable it.
--
Stephen Smalley
National Security Agency
Steve Grubb
2006-03-16 19:46:47 UTC
Permalink
Hi,

I think some people are misunderstanding what this patch is doing. The basic
idea is that 99.999% of the people that use the audit system are running it
to collect avc messages. When they do that, there is a performance hit that
some people do not like.

We did some profiling to see where the kernel is spending its time. It turns
out that the allocating of a context on every syscall is eating up clock
cycles. It would do this regardless of any audit rules being loaded or not.
So, if there are no audit rules loaded, why go into audit_syscall_entry at
all? The patch is supposed to look to see if there are any audit rules loaded
and avoid all that overhead if not. This is the typical setup for most people
that are using targeted policy.

So, we looked at what would be missing if we did this. Basically, if we avoid
audit_syscall_entry, syscall, arch, and args would not get collected. So, it
would be dishonest to to put 0 into syscall or arg0. Someone somewhere would
say the audit system is putting bogus information into syscall records. The
idea was to create a new record type that does not have those fields in it at
all.

We measured the results and its a big win. However, there is a bug in the
implementation. I had a feeling there might be a bug or two since this is a
change in what we are going and announced for people to help look for
problems.

The patch is supposed to:

1) avoid syscall entry when there are no audit rules loaded that would
potentially lead to a syscall event.
2) emit a partial syscall record whenever a full syscall record would have
been emitted but there are no audit rules loaded. (Meaning we didn't collect
entry information.)

If it doesn't do that, there's a bug in the code. We fix it, life goes on.

Does this explanation help understand what we are trying to achieve?

-Steve
Amy Griffis
2006-03-17 00:28:54 UTC
Permalink
Post by Jason Baron
Post by Amy Griffis
This patch avoids the record that would be generated on syscall exit,
but then emits it as AUDIT_SYSCALL_PARTIAL when the task exits.
Previously, these contents would be logged on every syscall exit, and
would only be logged on task exit in the case that it happened prior
to syscall exit.
This is bug in the implementation then...i had intended to to have
syscall partials only emitted at syscall exit time, when say after
selinux created an avc message. Is this hard to fix?
I see now that it works as you describe. I had missed the
significance of the invoke_audit field in the audit_context.
Post by Jason Baron
We did some profiling to see where the kernel is spending its time.
It turns out that the allocating of a context on every syscall is
eating up clock cycles.
On what architecture(s) did you do your profiling? The audit context
is always allocated on task creation, and will only be allocated
(again) in syscall entry in special circumstances. Per the comment in
audit_syscall_entry(), this only happens on architectures that make
system calls in kernel_thread via the entry.S interface instead of
with direct calls.
Post by Jason Baron
So, we looked at what would be missing if we did this. Basically, if
we avoid audit_syscall_entry, syscall, arch, and args would not get
collected. So, it would be dishonest to to put 0 into syscall or
arg0. Someone somewhere would say the audit system is putting bogus
information into syscall records. The idea was to create a new
record type that does not have those fields in it at all.
Of what value is a syscall record if it doesn't give you the syscall
number?

The audit system has set of defined states that determine its
activities around context collection, filtering, and logging. This
patch attempts to circumvent that set of states in a dubious manner to
meet a questionable requirement. This is precisely the kind of code
that makes audit non-intuitive, fragile, and unpopular in the linux
kernel.
Post by Jason Baron
The basic idea is that 99.999% of the people that use the audit
system are running it to collect avc messages. When they do that,
there is a performance hit that some people do not like.
Those people can set audit_enabled=0, problem solved. Steve, please
provide evidence of users needing avc messages with partial syscall
records, and which information in the syscall record is required.
There's no point in a patch for a non-existent requirement.

Regards,
Amy

Loading...