bk://linux-audit.bkbits.net/audit-2.6-mm peterm@redhat.com|ChangeSet|20050325152315|26919 peterm # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/03/27 16:31:35-08:00 akpm@bix.(none) # Merge bk://linux-audit.bkbits.net/audit-2.6-mm # into bix.(none):/usr/src/bk-audit # # kernel/auditsc.c # 2005/03/27 16:31:31-08:00 akpm@bix.(none) +0 -0 # Auto merged # # include/linux/audit.h # 2005/03/27 16:31:31-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/mips/kernel/ptrace.c # 2005/03/27 16:31:31-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/03/25 15:23:15+00:00 peterm@redhat.com # [AUDIT] Avoid using %*.*s format strings. # # They don't seem to work correctly (investigation ongoing), but we don't # actually need to do it anyway. # # Patch from Peter Martuccelli # Signed-off-by: David Woodhouse # # kernel/audit.c # 2005/03/25 15:22:55+00:00 peterm@redhat.com +2 -2 # The corruption I was able to track down was in the kernel, this patch # will fix the problem, (the problem I saw was corrupted avc messages # which always started with 118 leading white spaces). This is not a # final patch as I still need to determine what the issue is with printk. # The "%*.*s" format specifier is not popular in the kernel, iirc it is # only used in a few routines, which include the audit and avc routines. # # ChangeSet # 2005/03/25 13:59:08+00:00 sgrubb@redhat.com # [AUDIT] Fix signedness of 'serial' in various routines. # # Attached is a patch that corrects a signed/unsigned warning. I also noticed # that we needlessly init serial to 0. That only needs to occur if the kernel # was compiled without the audit system. # # -Steve Grubb # # Signed-off-by: David Woodhouse # # kernel/auditsc.c # 2005/03/25 13:58:45+00:00 sgrubb@redhat.com +1 -1 # Fix 'serial' argument of audit_get_stamp() to be unsigned. # # kernel/audit.c # 2005/03/25 13:58:45+00:00 sgrubb@redhat.com +4 -2 # Fix 'serial' to be unsigned in audit_log_start() # # include/linux/audit.h # 2005/03/25 13:58:45+00:00 sgrubb@redhat.com +1 -1 # Fix 'serial' arg of audit_get_stamp() to be unsigned. # # ChangeSet # 2005/03/25 13:53:36+00:00 dwmw2@shinybook.infradead.org # [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 # # kernel/auditsc.c # 2005/03/25 13:53:15+00:00 dwmw2@shinybook.infradead.org +16 -6 # Report syscall arch, modify AUDIT_SUCCESS condition. # # include/linux/audit.h # 2005/03/25 13:53:15+00:00 dwmw2@shinybook.infradead.org +44 -4 # Add AUDIT_ARCH and its definitions # Add arch to audit_syscall_entry() # Add success/failure to audit_syscall_exit() # # arch/x86_64/kernel/ptrace.c # 2005/03/25 13:53:15+00:00 dwmw2@shinybook.infradead.org +8 -5 # Reorder audit w.r.t ptrace, provide arch and success. # # arch/s390/kernel/ptrace.c # 2005/03/25 13:53:15+00:00 dwmw2@shinybook.infradead.org +11 -10 # Reorder audit w.r.t ptrace, provide arch and success. # # arch/ppc64/kernel/ptrace.c # 2005/03/25 13:53:15+00:00 dwmw2@shinybook.infradead.org +10 -6 # Reorder audit w.r.t ptrace, provide arch and success. # # arch/mips/kernel/ptrace.c # 2005/03/25 13:53:15+00:00 dwmw2@shinybook.infradead.org +28 -10 # Reorder audit w.r.t ptrace, provide arch and success. # # arch/ia64/kernel/ptrace.c # 2005/03/25 13:53:14+00:00 dwmw2@shinybook.infradead.org +13 -8 # Reorder audit w.r.t ptrace, provide arch and success. # # arch/i386/kernel/ptrace.c # 2005/03/25 13:53:14+00:00 dwmw2@shinybook.infradead.org +9 -10 # Reorder audit w.r.t ptrace, provide arch and success. # # ChangeSet # 2005/03/23 13:24:26-08:00 akpm@bix.(none) # Merge bk://linux-audit.bkbits.net/audit-2.6-mm # into bix.(none):/usr/src/bk-audit # # fs/namei.c # 2005/03/23 13:24:21-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/03/23 11:19:51+00:00 pmeda@akamai.com # namei: add audit_inode to all branches in path_lookup # # Main change is in path_lookup: added a goto to do audit_inode # instead of return statement, when emul_lookup_dentry for root # is successful. The existing code does audit_inode only when # lookup is done in normal root or cwd. # # Other changes: Some lookup routines are returning zero on success, # and some are returning zero on failure. I documented the related # function signatures in this code path, so that one can glance over # abstract functions without understanding the entire code. # # Signed-off-by: Prasanna Meda # Signed-off-by: David Woodhouse # # fs/namei.c # 2005/03/23 11:19:33+00:00 pmeda@akamai.com +12 -8 # namei: add audit_inode to all branches in path_lookup # # Main change is in path_lookup: added a goto to do audit_inode # instead of return statement, when emul_lookup_dentry for root # is successful. The existing code does audit_inode only when # lookup is done in normal root or cwd. # # Other changes: Some lookup routines are returning zero on success, # and some are returning zero on failure. I documented the related # function signatures in this code path, so that one can glance over # abstract functions without understanding the entire code. # # ChangeSet # 2005/03/19 09:19:30+00:00 akpm@osdl.org # audit_log_untrustedstring() warning fix # # kernel/audit.c: In function `audit_log_untrustedstring': # kernel/audit.c:736: warning: comparison is always false due to limited range of data type # # Signed-off-by: Andrew Morton # Signed-off-by: David Woodhouse # # kernel/audit.c # 2005/03/19 09:19:07+00:00 akpm@osdl.org +1 -1 # kernel/audit.c: In function `audit_log_untrustedstring': # kernel/audit.c:736: warning: comparison is always false due to limited range of data type # # ChangeSet # 2005/03/18 11:50:08-08:00 akpm@bix.(none) # Merge bk://linux-audit.bkbits.net/audit-2.6-mm # into bix.(none):/usr/src/bk-audit # # kernel/auditsc.c # 2005/03/18 11:50:03-08:00 akpm@bix.(none) +0 -0 # Auto merged # # include/linux/fs.h # 2005/03/18 11:50:03-08:00 akpm@bix.(none) +0 -0 # Auto merged # # include/linux/audit.h # 2005/03/18 11:50:03-08:00 akpm@bix.(none) +0 -0 # Auto merged # # fs/proc/base.c # 2005/03/18 11:50:03-08:00 akpm@bix.(none) +0 -0 # Auto merged # # fs/namei.c # 2005/03/18 11:50:03-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/um/kernel/ptrace.c # 2005/03/18 11:50:03-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/mips/kernel/ptrace.c # 2005/03/18 11:50:03-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/03/18 15:37:50+00:00 dwmw2@shinybook.infradead.org # AUDIT: Avoid log pollution by untrusted strings. # # We log strings from userspace, such as arguments to open(). These could # be formatted to contain \n followed by fake audit log entries. Provide # a function for logging such strings, which gives a hex dump when the # string contains anything but basic printable ASCII characters. Use it # for logging filenames. # # Signed-off-by: David Woodhouse # # kernel/auditsc.c # 2005/03/18 15:37:33+00:00 dwmw2@shinybook.infradead.org +4 -3 # Use audit_log_untrustedstring() for logging names. # # kernel/audit.c # 2005/03/18 15:37:33+00:00 dwmw2@shinybook.infradead.org +23 -0 # Add audit_log_hex() and audit_log_untrustedstring() # # include/linux/audit.h # 2005/03/18 15:37:33+00:00 dwmw2@shinybook.infradead.org +7 -1 # Add definitions of audit_log_hex() and audit_log_untrustedstring() # # ChangeSet # 2005/03/17 16:20:18-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-audit # # kernel/auditsc.c # 2005/03/17 16:20:14-08:00 akpm@bix.(none) +0 -0 # Auto merged # # include/linux/fs.h # 2005/03/17 16:20:14-08:00 akpm@bix.(none) +0 -0 # Auto merged # # include/linux/audit.h # 2005/03/17 16:20:14-08:00 akpm@bix.(none) +0 -0 # Auto merged # # fs/proc/base.c # 2005/03/17 16:20:14-08:00 akpm@bix.(none) +0 -0 # Auto merged # # fs/namei.c # 2005/03/17 16:20:14-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/um/kernel/ptrace.c # 2005/03/17 16:20:14-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/mips/kernel/ptrace.c # 2005/03/17 16:20:13-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/03/17 13:10:52+00:00 dwmw2@shinybook.infradead.org # Merge # # fs/proc/base.c # 2005/03/17 13:10:39+00:00 dwmw2@shinybook.infradead.org +0 -0 # SCCS merged # # kernel/auditsc.c # 2005/03/17 13:07:53+00:00 dwmw2@shinybook.infradead.org +0 -0 # Auto merged # # include/linux/fs.h # 2005/03/17 13:07:53+00:00 dwmw2@shinybook.infradead.org +0 -0 # Auto merged # # include/linux/audit.h # 2005/03/17 13:07:53+00:00 dwmw2@shinybook.infradead.org +0 -0 # Auto merged # # fs/namei.c # 2005/03/17 13:07:53+00:00 dwmw2@shinybook.infradead.org +0 -0 # Auto merged # # arch/um/kernel/ptrace.c # 2005/03/17 13:07:52+00:00 dwmw2@shinybook.infradead.org +0 -0 # Auto merged # # arch/mips/kernel/ptrace.c # 2005/03/17 13:07:52+00:00 dwmw2@shinybook.infradead.org +0 -0 # Auto merged # # ChangeSet # 2005/03/15 23:46:54-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-audit # # fs/proc/base.c # 2005/03/15 23:46:49-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/03/12 12:49:23-08:00 akpm@bix.(none) # Merge bk://linux-audit.bkbits.net/audit-2.6-mm # into bix.(none):/usr/src/bk-audit # # include/linux/audit.h # 2005/03/12 12:49:19-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/03/12 12:48:02-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-audit # # include/linux/audit.h # 2005/03/12 12:47:57-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/03/10 17:50:49-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-audit # # fs/namei.c # 2005/03/10 17:50:44-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/03/10 12:59:07-08:00 akpm@bix.(none) # Merge # # fs/proc/base.c # 2005/03/10 12:59:05-08:00 akpm@bix.(none) +0 -0 # SCCS merged # # kernel/auditsc.c # 2005/03/10 12:53:45-08:00 akpm@bix.(none) +0 -0 # Auto merged # # include/linux/fs.h # 2005/03/10 12:53:45-08:00 akpm@bix.(none) +0 -0 # Auto merged # # fs/namei.c # 2005/03/10 12:53:45-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/um/kernel/ptrace.c # 2005/03/10 12:53:45-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/mips/kernel/ptrace.c # 2005/03/10 12:53:45-08:00 akpm@bix.(none) +0 -0 # Auto merged # diff -Nru a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c --- a/arch/i386/kernel/ptrace.c 2005-03-30 17:09:27 -08:00 +++ b/arch/i386/kernel/ptrace.c 2005-03-30 17:09:27 -08:00 @@ -682,24 +682,18 @@ /* do the secure computing check first */ secure_computing(regs->orig_eax); - if (unlikely(current->audit_context)) { - if (!entryexit) - audit_syscall_entry(current, regs->orig_eax, - regs->ebx, regs->ecx, - regs->edx, regs->esi); - else - audit_syscall_exit(current, regs->eax); - } + if (unlikely(current->audit_context) && entryexit) + audit_syscall_exit(current, AUDITSC_RESULT(regs->eax), regs->eax); if (!(current->ptrace & PT_PTRACED)) - return; + goto out; /* Fake a debug trap */ if (test_thread_flag(TIF_SINGLESTEP)) send_sigtrap(current, regs, 0); if (!test_thread_flag(TIF_SYSCALL_TRACE)) - return; + goto out; /* the 0x80 provides a way for the tracing parent to distinguish between a syscall stop and SIGTRAP delivery */ @@ -714,4 +708,9 @@ send_sig(current->exit_code, current, 1); current->exit_code = 0; } + out: + if (unlikely(current->audit_context) && !entryexit) + audit_syscall_entry(current, AUDIT_ARCH_I386, regs->orig_eax, + regs->ebx, regs->ecx, regs->edx, regs->esi); + } diff -Nru a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c --- a/arch/ia64/kernel/ptrace.c 2005-03-30 17:09:27 -08:00 +++ b/arch/ia64/kernel/ptrace.c 2005-03-30 17:09:27 -08:00 @@ -1595,20 +1595,25 @@ long arg4, long arg5, long arg6, long arg7, struct pt_regs regs) { - long syscall; + if (test_thread_flag(TIF_SYSCALL_TRACE) + && (current->ptrace & PT_PTRACED)) + syscall_trace(); if (unlikely(current->audit_context)) { - if (IS_IA32_PROCESS(®s)) + long syscall; + int arch; + + if (IS_IA32_PROCESS(®s)) { syscall = regs.r1; - else + arch = AUDIT_ARCH_I386; + } else { syscall = regs.r15; + arch = AUDIT_ARCH_IA64; + } - audit_syscall_entry(current, syscall, arg0, arg1, arg2, arg3); + audit_syscall_entry(current, arch, syscall, arg0, arg1, arg2, arg3); } - if (test_thread_flag(TIF_SYSCALL_TRACE) - && (current->ptrace & PT_PTRACED)) - syscall_trace(); } /* "asmlinkage" so the input arguments are preserved... */ @@ -1619,7 +1624,7 @@ struct pt_regs regs) { if (unlikely(current->audit_context)) - audit_syscall_exit(current, regs.r8); + audit_syscall_exit(current, AUDITSC_RESULT(regs.r10), regs.r8); if (test_thread_flag(TIF_SYSCALL_TRACE) && (current->ptrace & PT_PTRACED)) diff -Nru a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c --- a/arch/mips/kernel/ptrace.c 2005-03-30 17:09:27 -08:00 +++ b/arch/mips/kernel/ptrace.c 2005-03-30 17:09:27 -08:00 @@ -301,25 +301,38 @@ return ret; } +static inline int audit_arch() +{ +#ifdef CONFIG_CPU_LITTLE_ENDIAN +#ifdef CONFIG_MIPS64 + if (!(current->thread.mflags & MF_32BIT_REGS)) + return AUDIT_ARCH_MIPSEL64; +#endif /* MIPS64 */ + return AUDIT_ARCH_MIPSEL; + +#else /* big endian... */ +#ifdef CONFIG_MIPS64 + if (!(current->thread.mflags & MF_32BIT_REGS)) + return AUDIT_ARCH_MIPS64; +#endif /* MIPS64 */ + return AUDIT_ARCH_MIPS; + +#endif /* endian */ +} + /* * Notification of system call entry/exit * - triggered by current->work.syscall_trace */ asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit) { - if (unlikely(current->audit_context)) { - if (!entryexit) - audit_syscall_entry(current, regs->regs[2], - regs->regs[4], regs->regs[5], - regs->regs[6], regs->regs[7]); - else - audit_syscall_exit(current, regs->regs[2]); - } + if (unlikely(current->audit_context) && entryexit) + audit_syscall_exit(current, AUDITSC_RESULT(regs->regs[2]), regs->regs[2]); if (!test_thread_flag(TIF_SYSCALL_TRACE)) - return; + goto out; if (!(current->ptrace & PT_PTRACED)) - return; + goto out; /* The 0x80 provides a way for the tracing parent to distinguish between a syscall stop and SIGTRAP delivery */ @@ -335,4 +348,9 @@ send_sig(current->exit_code, current, 1); current->exit_code = 0; } + out: + if (unlikely(current->audit_context) && !entryexit) + audit_syscall_entry(current, audit_arch(), regs->regs[2], + regs->regs[4], regs->regs[5], + regs->regs[6], regs->regs[7]); } diff -Nru a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c --- a/arch/ppc64/kernel/ptrace.c 2005-03-30 17:09:27 -08:00 +++ b/arch/ppc64/kernel/ptrace.c 2005-03-30 17:09:27 -08:00 @@ -303,20 +303,24 @@ void do_syscall_trace_enter(struct pt_regs *regs) { - if (unlikely(current->audit_context)) - audit_syscall_entry(current, regs->gpr[0], - regs->gpr[3], regs->gpr[4], - regs->gpr[5], regs->gpr[6]); - if (test_thread_flag(TIF_SYSCALL_TRACE) && (current->ptrace & PT_PTRACED)) do_syscall_trace(); + + if (unlikely(current->audit_context)) + audit_syscall_entry(current, + test_thread_flag(TIF_32BIT)?AUDIT_ARCH_PPC:AUDIT_ARCH_PPC64, + regs->gpr[0], + regs->gpr[3], regs->gpr[4], + regs->gpr[5], regs->gpr[6]); } void do_syscall_trace_leave(struct pt_regs *regs) { if (unlikely(current->audit_context)) - audit_syscall_exit(current, regs->result); + audit_syscall_exit(current, + (regs->ccr&0x1000)?AUDITSC_FAILURE:AUDITSC_SUCCESS, + regs->result); if ((test_thread_flag(TIF_SYSCALL_TRACE) || test_thread_flag(TIF_SINGLESTEP)) diff -Nru a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c --- a/arch/s390/kernel/ptrace.c 2005-03-30 17:09:27 -08:00 +++ b/arch/s390/kernel/ptrace.c 2005-03-30 17:09:27 -08:00 @@ -711,18 +711,13 @@ asmlinkage void syscall_trace(struct pt_regs *regs, int entryexit) { - if (unlikely(current->audit_context)) { - if (!entryexit) - audit_syscall_entry(current, regs->gprs[2], - regs->orig_gpr2, regs->gprs[3], - regs->gprs[4], regs->gprs[5]); - else - audit_syscall_exit(current, regs->gprs[2]); - } + if (unlikely(current->audit_context) && entryexit) + audit_syscall_exit(current, AUDITSC_RESULT(regs->gprs[2]), regs->gprs[2]); + if (!test_thread_flag(TIF_SYSCALL_TRACE)) - return; + goto out; if (!(current->ptrace & PT_PTRACED)) - return; + goto out; ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); @@ -735,4 +730,10 @@ send_sig(current->exit_code, current, 1); current->exit_code = 0; } + out: + if (unlikely(current->audit_context) && !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], + regs->gprs[4], regs->gprs[5]); } diff -Nru a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c --- a/arch/x86_64/kernel/ptrace.c 2005-03-30 17:09:27 -08:00 +++ b/arch/x86_64/kernel/ptrace.c 2005-03-30 17:09:27 -08:00 @@ -520,25 +520,28 @@ } } +#define audit_arch() (test_thread_flag(TIF_IA32) ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64) + asmlinkage void syscall_trace_enter(struct pt_regs *regs) { /* do the secure computing check first */ secure_computing(regs->orig_rax); + if (test_thread_flag(TIF_SYSCALL_TRACE) + && (current->ptrace & PT_PTRACED)) + syscall_trace(regs); + if (unlikely(current->audit_context)) - audit_syscall_entry(current, regs->orig_rax, + audit_syscall_entry(current, audit_arch(), regs->orig_rax, regs->rdi, regs->rsi, regs->rdx, regs->r10); - if (test_thread_flag(TIF_SYSCALL_TRACE) - && (current->ptrace & PT_PTRACED)) - syscall_trace(regs); } asmlinkage void syscall_trace_leave(struct pt_regs *regs) { if (unlikely(current->audit_context)) - audit_syscall_exit(current, regs->rax); + audit_syscall_exit(current, AUDITSC_RESULT(regs->rax), regs->rax); if ((test_thread_flag(TIF_SYSCALL_TRACE) || test_thread_flag(TIF_SINGLESTEP)) diff -Nru a/fs/namei.c b/fs/namei.c --- a/fs/namei.c 2005-03-30 17:09:27 -08:00 +++ b/fs/namei.c 2005-03-30 17:09:27 -08:00 @@ -686,11 +686,11 @@ /* * Name resolution. + * This is the basic name resolution function, turning a pathname into + * the final dentry. We expect 'base' to be positive and a directory. * - * This is the basic name resolution function, turning a pathname - * into the final dentry. - * - * We expect 'base' to be positive and a directory. + * Returns 0 and nd will have valid dentry and mnt on success. + * Returns error and drops reference to input namei data on failure. */ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) { @@ -929,8 +929,10 @@ return link_path_walk(name, nd); } -/* SMP-safe */ -/* returns 1 if everything is done */ +/* + * SMP-safe: Returns 1 and nd will have valid dentry and mnt, if + * everything is done. Returns 0 and drops input nd, if lookup failed; + */ static int __emul_lookup_dentry(const char *name, struct nameidata *nd) { if (path_walk(name, nd)) @@ -994,9 +996,10 @@ } } +/* Returns 0 and nd will be valid on success; Retuns error, otherwise. */ int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata *nd) { - int retval; + int retval = 0; nd->last_type = LAST_ROOT; /* if there are only slashes... */ nd->flags = flags; @@ -1009,7 +1012,7 @@ nd->dentry = dget(current->fs->altroot); read_unlock(¤t->fs->lock); if (__emul_lookup_dentry(name,nd)) - return 0; + goto out; /* found in altroot */ read_lock(¤t->fs->lock); } nd->mnt = mntget(current->fs->rootmnt); @@ -1021,6 +1024,7 @@ read_unlock(¤t->fs->lock); current->total_link_count = 0; retval = link_path_walk(name, nd); +out: if (unlikely(current->audit_context && nd && nd->dentry && nd->dentry->d_inode)) audit_inode(name, nd->dentry->d_inode); diff -Nru a/include/linux/audit.h b/include/linux/audit.h --- a/include/linux/audit.h 2005-03-30 17:09:27 -08:00 +++ b/include/linux/audit.h 2005-03-30 17:09:27 -08:00 @@ -24,6 +24,9 @@ #ifndef _LINUX_AUDIT_H_ #define _LINUX_AUDIT_H_ +#include +#include + /* Request and reply types */ #define AUDIT_GET 1000 /* Get status */ #define AUDIT_SET 1001 /* Set status (enable/disable/auditd) */ @@ -67,6 +70,7 @@ #define AUDIT_FSGID 8 #define AUDIT_LOGINUID 9 #define AUDIT_PERS 10 +#define AUDIT_ARCH 11 /* These are ONLY useful when checking * at syscall exit time (AUDIT_AT_EXIT). */ @@ -96,6 +100,38 @@ #define AUDIT_FAIL_PRINTK 1 #define AUDIT_FAIL_PANIC 2 +/* distinguish syscall tables */ +#define __AUDIT_ARCH_64BIT 0x80000000 +#define __AUDIT_ARCH_LE 0x40000000 +#define AUDIT_ARCH_ALPHA (EM_ALPHA|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) +#define AUDIT_ARCH_ARM (EM_ARM|__AUDIT_ARCH_LE) +#define AUDIT_ARCH_ARMEB (EM_ARM) +#define AUDIT_ARCH_CRIS (EM_CRIS|__AUDIT_ARCH_LE) +#define AUDIT_ARCH_FRV (EM_FRV) +#define AUDIT_ARCH_H8300 (EM_H8_300) +#define AUDIT_ARCH_I386 (EM_386|__AUDIT_ARCH_LE) +#define AUDIT_ARCH_IA64 (EM_IA_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) +#define AUDIT_ARCH_M32R (EM_M32R) +#define AUDIT_ARCH_M68K (EM_68K) +#define AUDIT_ARCH_MIPS (EM_MIPS) +#define AUDIT_ARCH_MIPSEL (EM_MIPS|__AUDIT_ARCH_LE) +#define AUDIT_ARCH_MIPS64 (EM_MIPS|__AUDIT_ARCH_64BIT) +#define AUDIT_ARCH_MIPSEL64 (EM_MIPS|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) +#define AUDIT_ARCH_PARISC (EM_PARISC) +#define AUDIT_ARCH_PARISC64 (EM_PARISC|__AUDIT_ARCH_64BIT) +#define AUDIT_ARCH_PPC (EM_PPC) +#define AUDIT_ARCH_PPC64 (EM_PPC64|__AUDIT_ARCH_64BIT) +#define AUDIT_ARCH_S390 (EM_S390) +#define AUDIT_ARCH_S390X (EM_S390|__AUDIT_ARCH_64BIT) +#define AUDIT_ARCH_SH (EM_SH) +#define AUDIT_ARCH_SHEL (EM_SH|__AUDIT_ARCH_LE) +#define AUDIT_ARCH_SH64 (EM_SH|__AUDIT_ARCH_64BIT) +#define AUDIT_ARCH_SHEL64 (EM_SH|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) +#define AUDIT_ARCH_SPARC (EM_SPARC) +#define AUDIT_ARCH_SPARC64 (EM_SPARC64|__AUDIT_ARCH_64BIT) +#define AUDIT_ARCH_V850 (EM_V850|__AUDIT_ARCH_LE) +#define AUDIT_ARCH_X86_64 (EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) + #ifndef __KERNEL__ struct audit_message { struct nlmsghdr nlh; @@ -129,15 +165,19 @@ struct audit_context; struct inode; +#define AUDITSC_INVALID 0 +#define AUDITSC_SUCCESS 1 +#define AUDITSC_FAILURE 2 +#define AUDITSC_RESULT(x) ( ((long)(x))<0?AUDITSC_FAILURE:AUDITSC_SUCCESS ) #ifdef CONFIG_AUDITSYSCALL /* These are defined in auditsc.c */ /* Public API */ extern int audit_alloc(struct task_struct *task); extern void audit_free(struct task_struct *task); -extern void audit_syscall_entry(struct task_struct *task, +extern void audit_syscall_entry(struct task_struct *task, int arch, int major, unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3); -extern void audit_syscall_exit(struct task_struct *task, int return_code); +extern void audit_syscall_exit(struct task_struct *task, int failed, long return_code); extern void audit_getname(const char *name); extern void audit_putname(const char *name); extern void audit_inode(const char *name, const struct inode *inode); @@ -146,15 +186,15 @@ extern int audit_receive_filter(int type, int pid, int uid, int seq, void *data); extern void audit_get_stamp(struct audit_context *ctx, - struct timespec *t, int *serial); + struct timespec *t, unsigned int *serial); extern int audit_set_loginuid(struct audit_context *ctx, uid_t loginuid); extern uid_t audit_get_loginuid(struct audit_context *ctx); extern int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode); #else #define audit_alloc(t) ({ 0; }) #define audit_free(t) do { ; } while (0) -#define audit_syscall_entry(t,a,b,c,d,e) do { ; } while (0) -#define audit_syscall_exit(t,r) do { ; } while (0) +#define audit_syscall_entry(t,ta,a,b,c,d,e) do { ; } while (0) +#define audit_syscall_exit(t,f,r) do { ; } while (0) #define audit_getname(n) do { ; } while (0) #define audit_putname(n) do { ; } while (0) #define audit_inode(n,i) do { ; } while (0) @@ -174,11 +214,15 @@ const char *fmt, ...) __attribute__((format(printf,2,3))); extern void audit_log_end(struct audit_buffer *ab); +extern void audit_log_hex(struct audit_buffer *ab, + const unsigned char *buf, + size_t len); +extern void audit_log_untrustedstring(struct audit_buffer *ab, + const char *string); extern void audit_log_d_path(struct audit_buffer *ab, const char *prefix, struct dentry *dentry, struct vfsmount *vfsmnt); - /* Private API (for auditsc.c only) */ extern void audit_send_reply(int pid, int seq, int type, int done, int multi, @@ -190,6 +234,8 @@ #define audit_log_vformat(b,f,a) do { ; } while (0) #define audit_log_format(b,f,...) do { ; } while (0) #define audit_log_end(b) do { ; } while (0) +#define audit_log_hex(a,b,l) do { ; } while (0) +#define audit_log_untrustedstring(a,s) do { ; } while (0) #define audit_log_d_path(b,p,d,v) do { ; } while (0) #endif #endif diff -Nru a/kernel/audit.c b/kernel/audit.c --- a/kernel/audit.c 2005-03-30 17:09:27 -08:00 +++ b/kernel/audit.c 2005-03-30 17:09:27 -08:00 @@ -540,8 +540,8 @@ if (!audit_pid) { /* No daemon */ int offset = ab->nlh ? NLMSG_SPACE(0) : 0; int len = skb->len - offset; - printk(KERN_ERR "%*.*s\n", - len, len, skb->data + offset); + skb->data[offset + len] = '\0'; + printk(KERN_ERR "%s\n", skb->data + offset); } kfree_skb(skb); ab->nlh = NULL; @@ -620,7 +620,7 @@ struct audit_buffer *ab = NULL; unsigned long flags; struct timespec t; - int serial = 0; + unsigned int serial; if (!audit_initialized) return NULL; @@ -669,8 +669,10 @@ audit_get_stamp(ab->ctx, &t, &serial); else #endif + { t = CURRENT_TIME; - + serial = 0; + } audit_log_format(ab, "audit(%lu.%03lu:%u): ", t.tv_sec, t.tv_nsec/1000000, serial); return ab; @@ -719,6 +721,29 @@ audit_log_vformat(ab, fmt, args); va_end(args); } + +void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf, size_t len) +{ + int i; + + for (i=0; i 0x7f) { + audit_log_hex(ab, string, strlen(string)); + return; + } + p++; + } + audit_log_format(ab, "\"%s\"", string); +} + /* This is a helper-function to print the d_path without using a static * buffer or allocating another buffer in addition to the one in diff -Nru a/kernel/auditsc.c b/kernel/auditsc.c --- a/kernel/auditsc.c 2005-03-30 17:09:27 -08:00 +++ b/kernel/auditsc.c 2005-03-30 17:09:27 -08:00 @@ -123,7 +123,7 @@ 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 @@ 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 @@ 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 @@ 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) { @@ -621,8 +626,11 @@ 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" @@ -668,9 +676,10 @@ if (!ab) continue; /* audit_panic has been called */ audit_log_format(ab, "item=%d", i); - if (context->names[i].name) - audit_log_format(ab, " name=%s", - context->names[i].name); + if (context->names[i].name) { + audit_log_format(ab, " name="); + audit_log_untrustedstring(ab, context->names[i].name); + } if (context->names[i].ino != (unsigned long)-1) audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#o" " uid=%d gid=%d rdev=%02x:%02x", @@ -744,7 +753,7 @@ * 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) { @@ -798,6 +807,7 @@ if (!audit_enabled) return; + context->arch = arch; context->major = major; context->argv[0] = a1; context->argv[1] = a2; @@ -821,13 +831,13 @@ * 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 @@ -840,6 +850,7 @@ context->in_syscall = 0; context->auditable = 0; + if (context->previous) { struct audit_context *new_context = context->previous; context->previous = NULL; @@ -953,7 +964,7 @@ } void audit_get_stamp(struct audit_context *ctx, - struct timespec *t, int *serial) + struct timespec *t, unsigned int *serial) { if (ctx) { t->tv_sec = ctx->ctime.tv_sec;