diff options
author | <dwmw2@shinybook.infradead.org> | 2005-04-29 16:08:28 +0100 |
---|---|---|
committer | <dwmw2@shinybook.infradead.org> | 2005-04-29 16:08:28 +0100 |
commit | 2fd6f58ba6efc82ea2c9c2630f7ff5ed9eeaf34a (patch) | |
tree | 87cf236a78ad242ae01f1b71c289131e6d1c0662 /kernel/auditsc.c | |
parent | ea3834d9fb348fb1144ad3affea22df933eaf62e (diff) | |
download | lwn-2fd6f58ba6efc82ea2c9c2630f7ff5ed9eeaf34a.tar.gz lwn-2fd6f58ba6efc82ea2c9c2630f7ff5ed9eeaf34a.zip |
[AUDIT] Don't allow ptrace to fool auditing, log arch of audited syscalls.
We were calling ptrace_notify() after auditing the syscall and arguments,
but the debugger could have _changed_ them before the syscall was actually
invoked. Reorder the calls to fix that.
While we're touching ever call to audit_syscall_entry(), we also make it
take an extra argument: the architecture of the syscall which was made,
because some architectures allow more than one type of syscall.
Also add an explicit success/failure flag to audit_syscall_exit(), for
the benefit of architectures which return that in a condition register
rather than only returning a single register.
Change type of syscall return value to 'long' not 'int'.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'kernel/auditsc.c')
-rw-r--r-- | kernel/auditsc.c | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 00e87ffff13b..77e92592de57 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -123,7 +123,7 @@ struct audit_context { int major; /* syscall number */ unsigned long argv[4]; /* syscall arguments */ int return_valid; /* return code is valid */ - int return_code;/* syscall return code */ + long return_code;/* syscall return code */ int auditable; /* 1 if record should be written */ int name_count; struct audit_names names[AUDIT_NAMES]; @@ -135,6 +135,7 @@ struct audit_context { uid_t uid, euid, suid, fsuid; gid_t gid, egid, sgid, fsgid; unsigned long personality; + int arch; #if AUDIT_DEBUG int put_count; @@ -348,6 +349,10 @@ static int audit_filter_rules(struct task_struct *tsk, case AUDIT_PERS: result = (tsk->personality == value); break; + case AUDIT_ARCH: + if (ctx) + result = (ctx->arch == value); + break; case AUDIT_EXIT: if (ctx && ctx->return_valid) @@ -355,7 +360,7 @@ static int audit_filter_rules(struct task_struct *tsk, break; case AUDIT_SUCCESS: if (ctx && ctx->return_valid) - result = (ctx->return_code >= 0); + result = (ctx->return_valid == AUDITSC_SUCCESS); break; case AUDIT_DEVMAJOR: if (ctx) { @@ -648,8 +653,11 @@ static void audit_log_exit(struct audit_context *context) audit_log_format(ab, "syscall=%d", context->major); if (context->personality != PER_LINUX) audit_log_format(ab, " per=%lx", context->personality); + audit_log_format(ab, " arch=%x", context->arch); if (context->return_valid) - audit_log_format(ab, " exit=%d", context->return_code); + audit_log_format(ab, " success=%s exit=%ld", + (context->return_valid==AUDITSC_SUCCESS)?"yes":"no", + context->return_code); audit_log_format(ab, " a0=%lx a1=%lx a2=%lx a3=%lx items=%d" " pid=%d loginuid=%d uid=%d gid=%d" @@ -773,7 +781,7 @@ static inline unsigned int audit_serial(void) * then the record will be written at syscall exit time (otherwise, it * will only be written if another part of the kernel requests that it * be written). */ -void audit_syscall_entry(struct task_struct *tsk, int major, +void audit_syscall_entry(struct task_struct *tsk, int arch, int major, unsigned long a1, unsigned long a2, unsigned long a3, unsigned long a4) { @@ -827,6 +835,7 @@ void audit_syscall_entry(struct task_struct *tsk, int major, if (!audit_enabled) return; + context->arch = arch; context->major = major; context->argv[0] = a1; context->argv[1] = a2; @@ -850,13 +859,13 @@ void audit_syscall_entry(struct task_struct *tsk, int major, * filtering, or because some other part of the kernel write an audit * message), then write out the syscall information. In call cases, * free the names stored from getname(). */ -void audit_syscall_exit(struct task_struct *tsk, int return_code) +void audit_syscall_exit(struct task_struct *tsk, int valid, long return_code) { struct audit_context *context; get_task_struct(tsk); task_lock(tsk); - context = audit_get_context(tsk, 1, return_code); + context = audit_get_context(tsk, valid, return_code); task_unlock(tsk); /* Not having a context here is ok, since the parent may have @@ -869,6 +878,7 @@ void audit_syscall_exit(struct task_struct *tsk, int return_code) context->in_syscall = 0; context->auditable = 0; + if (context->previous) { struct audit_context *new_context = context->previous; context->previous = NULL; |