Signed-off-by: Andrew Morton --- 25-akpm/arch/i386/kernel/ptrace.c | 19 +++++------ 25-akpm/arch/ia64/kernel/fsys.S | 5 ++- 25-akpm/arch/ia64/kernel/ptrace.c | 21 +++++++----- 25-akpm/arch/ia64/kernel/signal.c | 3 + 25-akpm/arch/mips/kernel/ptrace.c | 38 ++++++++++++++++------ 25-akpm/arch/ppc64/kernel/ptrace.c | 16 ++++++--- 25-akpm/arch/s390/kernel/ptrace.c | 21 ++++++------ 25-akpm/arch/x86_64/kernel/ptrace.c | 13 ++++--- 25-akpm/fs/namei.c | 20 +++++++----- 25-akpm/include/linux/audit.h | 60 +++++++++++++++++++++++++++++++----- 25-akpm/kernel/audit.c | 37 ++++++++++++++++++---- 25-akpm/kernel/auditsc.c | 33 +++++++++++++------ 12 files changed, 203 insertions(+), 83 deletions(-) diff -puN arch/i386/kernel/ptrace.c~bk-audit arch/i386/kernel/ptrace.c --- 25/arch/i386/kernel/ptrace.c~bk-audit 2005-04-04 18:53:40.000000000 -0700 +++ 25-akpm/arch/i386/kernel/ptrace.c 2005-04-04 18:53:40.000000000 -0700 @@ -682,24 +682,18 @@ void do_syscall_trace(struct pt_regs *re /* 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 @@ void do_syscall_trace(struct pt_regs *re 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 -puN arch/ia64/kernel/fsys.S~bk-audit arch/ia64/kernel/fsys.S --- 25/arch/ia64/kernel/fsys.S~bk-audit 2005-04-04 18:53:40.000000000 -0700 +++ 25-akpm/arch/ia64/kernel/fsys.S 2005-04-04 18:54:01.000000000 -0700 @@ -633,7 +633,10 @@ GLOBAL_ENTRY(fsys_bubble_down) nop.i 0 ;; ssm psr.i // M2 we're on kernel stacks now, reenable irqs - tbit.z p8,p0=r3,TIF_SYSCALL_TRACE // I0 + and r3=_TIF_SYSCALL_TRACEAUDIT,r3 + ;; + cmp.eq p8,p0=r3,r0 + (p10) br.cond.spnt.many ia64_ret_from_syscall // B return if bad call-frame or r15 is a NaT nop.m 0 diff -puN arch/ia64/kernel/ptrace.c~bk-audit arch/ia64/kernel/ptrace.c --- 25/arch/ia64/kernel/ptrace.c~bk-audit 2005-04-04 18:53:40.000000000 -0700 +++ 25-akpm/arch/ia64/kernel/ptrace.c 2005-04-04 18:53:40.000000000 -0700 @@ -1595,20 +1595,25 @@ syscall_trace_enter (long arg0, long arg 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 @@ syscall_trace_leave (long arg0, long arg 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 -puN arch/ia64/kernel/signal.c~bk-audit arch/ia64/kernel/signal.c --- 25/arch/ia64/kernel/signal.c~bk-audit 2005-04-04 18:53:40.000000000 -0700 +++ 25-akpm/arch/ia64/kernel/signal.c 2005-04-04 18:53:40.000000000 -0700 @@ -224,7 +224,8 @@ ia64_rt_sigreturn (struct sigscratch *sc * could be corrupted. */ retval = (long) &ia64_leave_kernel; - if (test_thread_flag(TIF_SYSCALL_TRACE)) + if (test_thread_flag(TIF_SYSCALL_TRACE) + || test_thread_flag(TIF_SYSCALL_AUDIT)) /* * strace expects to be notified after sigreturn returns even though the * context to which we return may not be in the middle of a syscall. diff -puN arch/mips/kernel/ptrace.c~bk-audit arch/mips/kernel/ptrace.c --- 25/arch/mips/kernel/ptrace.c~bk-audit 2005-04-04 18:53:40.000000000 -0700 +++ 25-akpm/arch/mips/kernel/ptrace.c 2005-04-04 18:53:40.000000000 -0700 @@ -301,25 +301,38 @@ out: return ret; } +static inline int audit_arch(void) +{ +#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 @@ asmlinkage void do_syscall_trace(struct 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 -puN arch/ppc64/kernel/ptrace.c~bk-audit arch/ppc64/kernel/ptrace.c --- 25/arch/ppc64/kernel/ptrace.c~bk-audit 2005-04-04 18:53:40.000000000 -0700 +++ 25-akpm/arch/ppc64/kernel/ptrace.c 2005-04-04 18:53:40.000000000 -0700 @@ -304,14 +304,16 @@ static void do_syscall_trace(void) 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) @@ -319,7 +321,9 @@ void do_syscall_trace_leave(struct pt_re secure_computing(regs->gpr[0]); 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 -puN arch/s390/kernel/ptrace.c~bk-audit arch/s390/kernel/ptrace.c --- 25/arch/s390/kernel/ptrace.c~bk-audit 2005-04-04 18:53:40.000000000 -0700 +++ 25-akpm/arch/s390/kernel/ptrace.c 2005-04-04 18:53:40.000000000 -0700 @@ -711,18 +711,13 @@ out: 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 @@ syscall_trace(struct pt_regs *regs, int 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 -puN arch/x86_64/kernel/ptrace.c~bk-audit arch/x86_64/kernel/ptrace.c --- 25/arch/x86_64/kernel/ptrace.c~bk-audit 2005-04-04 18:53:40.000000000 -0700 +++ 25-akpm/arch/x86_64/kernel/ptrace.c 2005-04-04 18:53:40.000000000 -0700 @@ -520,25 +520,28 @@ static void syscall_trace(struct pt_regs } } +#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 -puN fs/namei.c~bk-audit fs/namei.c --- 25/fs/namei.c~bk-audit 2005-04-04 18:53:40.000000000 -0700 +++ 25-akpm/fs/namei.c 2005-04-04 18:53:40.000000000 -0700 @@ -686,11 +686,11 @@ fail: /* * 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 @@ int fastcall path_walk(const char * name 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 @@ set_it: } } +/* 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 @@ int fastcall path_lookup(const char *nam 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 @@ int fastcall path_lookup(const char *nam 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 -puN include/linux/audit.h~bk-audit include/linux/audit.h --- 25/include/linux/audit.h~bk-audit 2005-04-04 18:53:40.000000000 -0700 +++ 25-akpm/include/linux/audit.h 2005-04-04 18:53:40.000000000 -0700 @@ -1,4 +1,4 @@ -/* audit.h -- Auditing support -*- linux-c -*- +/* audit.h -- Auditing support * * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina. * All Rights Reserved. @@ -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_buffer; 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 void audit_inode(const char *name 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 @@ extern void audit_log_format(struct 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 @@ extern void audit_log_lost(const ch #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 -puN kernel/audit.c~bk-audit kernel/audit.c --- 25/kernel/audit.c~bk-audit 2005-04-04 18:53:40.000000000 -0700 +++ 25-akpm/kernel/audit.c 2005-04-04 18:53:40.000000000 -0700 @@ -1,4 +1,4 @@ -/* audit.c -- Auditing support -*- linux-c -*- +/* audit.c -- Auditing support * Gateway between the kernel (e.g., selinux) and the user-space audit daemon. * System-call specific features have moved to auditsc.c * @@ -38,7 +38,7 @@ * 6) Support low-overhead kernel-based filtering to minimize the * information that must be passed to user-space. * - * Example user-space utilities: http://people.redhat.com/faith/audit/ + * Example user-space utilities: http://people.redhat.com/sgrubb/audit/ */ #include @@ -540,8 +540,8 @@ static inline int audit_log_drain(struct 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 *audit_log_start(str 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 @@ struct audit_buffer *audit_log_start(str 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; @@ -720,6 +722,29 @@ void audit_log_format(struct audit_buffe 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 * audit_buffer. */ diff -puN kernel/auditsc.c~bk-audit kernel/auditsc.c --- 25/kernel/auditsc.c~bk-audit 2005-04-04 18:53:40.000000000 -0700 +++ 25-akpm/kernel/auditsc.c 2005-04-04 18:53:40.000000000 -0700 @@ -1,4 +1,4 @@ -/* auditsc.c -- System-call auditing support -*- linux-c -*- +/* auditsc.c -- System-call auditing support * Handles all system-call specific auditing features. * * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina. @@ -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 tas 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 tas 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 @@ static void audit_log_exit(struct audit_ 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 @@ static void audit_log_exit(struct audit_ 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 @@ static inline unsigned int audit_serial( * 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 @@ void audit_syscall_entry(struct task_str if (!audit_enabled) return; + context->arch = arch; context->major = major; context->argv[0] = a1; context->argv[1] = a2; @@ -821,13 +831,13 @@ void audit_syscall_entry(struct task_str * 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 @@ void audit_syscall_exit(struct task_stru 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_inode(const char *name, const } 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; _