Merge with master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
authorDavid Woodhouse <dwmw2@shinybook.infradead.org>
Thu, 5 May 2005 12:59:37 +0000 (13:59 +0100)
committerDavid Woodhouse <dwmw2@shinybook.infradead.org>
Thu, 5 May 2005 12:59:37 +0000 (13:59 +0100)
18 files changed:
arch/i386/kernel/ptrace.c
arch/ia64/kernel/ptrace.c
arch/mips/kernel/ptrace.c
arch/ppc64/kernel/ptrace.c
arch/s390/kernel/ptrace.c
arch/um/kernel/ptrace.c
arch/x86_64/kernel/ptrace.c
fs/namei.c
fs/proc/base.c
include/asm-um/ptrace-i386.h
include/asm-um/ptrace-x86_64.h
include/asm-um/thread_info.h
include/linux/audit.h
include/linux/netlink.h
init/Kconfig
kernel/audit.c
kernel/auditsc.c
net/netlink/af_netlink.c

index e8c965ce86eb2ddcc824c8c13d6988a426cb374b..e34f651fa13c001de7b84967c0882d71bda35c1e 100644 (file)
@@ -683,24 +683,18 @@ void do_syscall_trace(struct pt_regs *regs, int entryexit)
        /* 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 */
@@ -715,4 +709,9 @@ void do_syscall_trace(struct pt_regs *regs, int entryexit)
                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);
+
 }
index c253fd5914fcb6e4144f1bc8dc2930a22dbde161..907464ee7273221468afa4c59cc811042ed2fd11 100644 (file)
@@ -1596,20 +1596,25 @@ syscall_trace_enter (long arg0, long arg1, long arg2, long arg3,
                     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(&regs))
+               long syscall;
+               int arch;
+
+               if (IS_IA32_PROCESS(&regs)) {
                        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... */
@@ -1620,7 +1625,7 @@ syscall_trace_leave (long arg0, long arg1, long arg2, long arg3,
                     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))
index a2f899c2f4d495cd224b1e0966b3a201be987d87..92e70ca3bff9d60bb6bf51a660f75b09496d089c 100644 (file)
@@ -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 pt_regs *regs, int entryexit)
                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]);
 }
index 5a846324ca8cc981cfa3fd2d9bf566ab21858ebb..9f8c6087ae568aaa9a7a2dd999ce65d3ea9828b9 100644 (file)
@@ -305,14 +305,17 @@ static void do_syscall_trace(void)
 
 void do_syscall_trace_enter(struct pt_regs *regs)
 {
+       if (test_thread_flag(TIF_SYSCALL_TRACE)
+           && (current->ptrace & PT_PTRACED))
+               do_syscall_trace();
+
        if (unlikely(current->audit_context))
-               audit_syscall_entry(current, regs->gpr[0],
+               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]);
 
-       if (test_thread_flag(TIF_SYSCALL_TRACE)
-           && (current->ptrace & PT_PTRACED))
-               do_syscall_trace();
 }
 
 void do_syscall_trace_leave(struct pt_regs *regs)
@@ -320,7 +323,9 @@ void do_syscall_trace_leave(struct pt_regs *regs)
        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))
index 9f0d73e3f5f727ddbdffe498fcccb65acb48bc8e..26889366929a1ac3d9162a2ba357dd837a143877 100644 (file)
@@ -712,18 +712,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));
 
@@ -736,4 +731,10 @@ syscall_trace(struct pt_regs *regs, int entryexit)
                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]);
 }
index e50e60ff5d275bca5664b2db0b26e2f7b3e2129d..959b2d2490df273bdd2051cd65bb01ab7acb3004 100644 (file)
@@ -337,15 +337,18 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit)
 
        if (unlikely(current->audit_context)) {
                if (!entryexit)
-                       audit_syscall_entry(current, 
-                                           UPT_SYSCALL_NR(&regs->regs),
-                                           UPT_SYSCALL_ARG1(&regs->regs),
-                                           UPT_SYSCALL_ARG2(&regs->regs),
-                                           UPT_SYSCALL_ARG3(&regs->regs),
-                                           UPT_SYSCALL_ARG4(&regs->regs));
-               else
-                       audit_syscall_exit(current, 
-                                          UPT_SYSCALL_RET(&regs->regs));
+                       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 {
+                        int res = UPT_SYSCALL_RET(regs);
+                       audit_syscall_exit(current, AUDITSC_RESULT(res),
+                                           res);
+                }
        }
 
        /* Fake a debug trap */
index c64b9c97c7459d035c3e4852d7d2e18508010ce7..e26e86bb56fe53381e2016e4f478dbdc37ec0294 100644 (file)
@@ -635,20 +635,29 @@ asmlinkage void syscall_trace_enter(struct pt_regs *regs)
        /* do the secure computing check first */
        secure_computing(regs->orig_rax);
 
-       if (unlikely(current->audit_context))
-               audit_syscall_entry(current, 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);
+
+       if (unlikely(current->audit_context)) {
+               if (test_thread_flag(TIF_IA32)) {
+                       audit_syscall_entry(current, AUDIT_ARCH_I386,
+                                           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);
+               }
+       }
 }
 
 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))
index 9e4aef2a1a21d44a9ba54b00f5ac284dd590f331..0f76fd75591bd0d5c3fbf44a2540519a972a44a2 100644 (file)
@@ -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, struct nameidata *nd)
        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 *name, unsigned int flags, struct nameidata
                        nd->dentry = dget(current->fs->altroot);
                        read_unlock(&current->fs->lock);
                        if (__emul_lookup_dentry(name,nd))
-                               return 0;
+                               goto out; /* found in altroot */
                        read_lock(&current->fs->lock);
                }
                nd->mnt = mntget(current->fs->rootmnt);
@@ -1021,6 +1024,7 @@ int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata
        read_unlock(&current->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);
index 07cafdf74ef2f343b4eef2e8f0356d69a7f8e6f4..e31903aadd96f6f3a4cc327c67f9163352da262f 100644 (file)
@@ -820,7 +820,7 @@ static ssize_t proc_loginuid_write(struct file * file, const char __user * buf,
                goto out_free_page;
 
        }
-       length = audit_set_loginuid(task->audit_context, loginuid);
+       length = audit_set_loginuid(task, loginuid);
        if (likely(length == 0))
                length = count;
 
index 9e47590ec293b7c9e444f8fd02e0ffd9f3f3b942..04222f35c43e2cd0a64b9b28e390be9953104ee6 100644 (file)
@@ -6,6 +6,8 @@
 #ifndef __UM_PTRACE_I386_H
 #define __UM_PTRACE_I386_H
 
+#define HOST_AUDIT_ARCH AUDIT_ARCH_I386
+
 #include "sysdep/ptrace.h"
 #include "asm/ptrace-generic.h"
 
index c34be39b78b2262277b6abdf2c38dd5e30afb6af..be51219a8ffe468a600dc8727f9a9b83e90c0f3d 100644 (file)
@@ -14,6 +14,8 @@
 #include "asm/ptrace-generic.h"
 #undef signal_fault
 
+#define HOST_AUDIT_ARCH AUDIT_ARCH_X86_64
+
 void signal_fault(struct pt_regs_subarch *regs, void *frame, char *where);
 
 #define FS_BASE (21 * sizeof(unsigned long))
index bffb577bc54e3b88b1706a0c9e49d489e05bcd87..a10ea155907efbf3d455f21eec33b95bfa9239ad 100644 (file)
@@ -72,12 +72,14 @@ static inline struct thread_info *current_thread_info(void)
                                         */
 #define TIF_RESTART_BLOCK      4
 #define TIF_MEMDIE             5
+#define TIF_SYSCALL_AUDIT      6
 
 #define _TIF_SYSCALL_TRACE     (1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING                (1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG     (1 << TIF_POLLING_NRFLAG)
-#define _TIF_RESTART_BLOCK     (1 << TIF_RESTART_BLOCK)
+#define _TIF_MEMDIE            (1 << TIF_MEMDIE)
+#define _TIF_SYSCALL_AUDIT     (1 << TIF_SYSCALL_AUDIT)
 
 #endif
 
index 3628f7cfb1789c16ff9e5f6d20e76e9b6d69672e..19f04b04979878ffcfa2706a9acb98421537226d 100644 (file)
@@ -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 <linux/sched.h>
+#include <linux/elf.h>
+
 /* 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). */
 #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,32 +165,36 @@ 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);
 
                                /* Private API (for audit.c only) */
 extern int  audit_receive_filter(int type, int pid, int uid, int seq,
-                                void *data);
+                                void *data, uid_t loginuid);
 extern void audit_get_stamp(struct audit_context *ctx,
-                           struct timespec *t, int *serial);
-extern int  audit_set_loginuid(struct audit_context *ctx, uid_t loginuid);
+                           struct timespec *t, unsigned int *serial);
+extern int  audit_set_loginuid(struct task_struct *task, 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 audit_buffer *ab,
                                             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 char *message);
 #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
index f731abdc1a29a9cd1d5290d6a8121414377e88df..b2738ac8bc999f30c0840f318c5da73d95214fed 100644 (file)
@@ -110,6 +110,7 @@ struct netlink_skb_parms
        __u32                   dst_pid;
        __u32                   dst_groups;
        kernel_cap_t            eff_cap;
+       __u32                   loginuid;       /* Login (audit) uid */
 };
 
 #define NETLINK_CB(skb)                (*(struct netlink_skb_parms*)&((skb)->cb))
index 40d286d1d118f5c5d65498ad911a84a9d047cdb1..d920baed109a4c0bfb91d85e436626ccac886fbb 100644 (file)
@@ -173,7 +173,7 @@ config AUDIT
 
 config AUDITSYSCALL
        bool "Enable system-call auditing support"
-       depends on AUDIT && (X86 || PPC64 || ARCH_S390 || IA64)
+       depends on AUDIT && (X86 || PPC64 || ARCH_S390 || IA64 || UML)
        default y if SECURITY_SELINUX
        help
          Enable low-overhead system-call auditing infrastructure that
index ac26d4d960d3366d0473ede3533ab89446b75dc3..9c4f1af0c794674404810d7caff0131218cbc950 100644 (file)
@@ -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 <linux/init.h>
@@ -142,7 +142,6 @@ struct audit_buffer {
        int                  total;
        int                  type;
        int                  pid;
-       int                  count; /* Times requeued */
 };
 
 void audit_set_type(struct audit_buffer *ab, int type)
@@ -239,36 +238,36 @@ void audit_log_lost(const char *message)
 
 }
 
-static int audit_set_rate_limit(int limit)
+static int audit_set_rate_limit(int limit, uid_t loginuid)
 {
        int old          = audit_rate_limit;
        audit_rate_limit = limit;
-       audit_log(current->audit_context, "audit_rate_limit=%d old=%d",
-                 audit_rate_limit, old);
+       audit_log(NULL, "audit_rate_limit=%d old=%d by auid %u",
+                       audit_rate_limit, old, loginuid);
        return old;
 }
 
-static int audit_set_backlog_limit(int limit)
+static int audit_set_backlog_limit(int limit, uid_t loginuid)
 {
        int old          = audit_backlog_limit;
        audit_backlog_limit = limit;
-       audit_log(current->audit_context, "audit_backlog_limit=%d old=%d",
-                 audit_backlog_limit, old);
+       audit_log(NULL, "audit_backlog_limit=%d old=%d by auid %u",
+                       audit_backlog_limit, old, loginuid);
        return old;
 }
 
-static int audit_set_enabled(int state)
+static int audit_set_enabled(int state, uid_t loginuid)
 {
        int old          = audit_enabled;
        if (state != 0 && state != 1)
                return -EINVAL;
        audit_enabled = state;
-       audit_log(current->audit_context, "audit_enabled=%d old=%d",
-                 audit_enabled, old);
+       audit_log(NULL, "audit_enabled=%d old=%d by auid %u",
+                 audit_enabled, old, loginuid);
        return old;
 }
 
-static int audit_set_failure(int state)
+static int audit_set_failure(int state, uid_t loginuid)
 {
        int old          = audit_failure;
        if (state != AUDIT_FAIL_SILENT
@@ -276,8 +275,8 @@ static int audit_set_failure(int state)
            && state != AUDIT_FAIL_PANIC)
                return -EINVAL;
        audit_failure = state;
-       audit_log(current->audit_context, "audit_failure=%d old=%d",
-                 audit_failure, old);
+       audit_log(NULL, "audit_failure=%d old=%d by auid %u",
+                 audit_failure, old, loginuid);
        return old;
 }
 
@@ -344,6 +343,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
        int                     err;
        struct audit_buffer     *ab;
        u16                     msg_type = nlh->nlmsg_type;
+       uid_t                   loginuid; /* loginuid of sender */
 
        err = audit_netlink_ok(NETLINK_CB(skb).eff_cap, msg_type);
        if (err)
@@ -351,6 +351,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 
        pid  = NETLINK_CREDS(skb)->pid;
        uid  = NETLINK_CREDS(skb)->uid;
+       loginuid = NETLINK_CB(skb).loginuid;
        seq  = nlh->nlmsg_seq;
        data = NLMSG_DATA(nlh);
 
@@ -371,34 +372,36 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                        return -EINVAL;
                status_get   = (struct audit_status *)data;
                if (status_get->mask & AUDIT_STATUS_ENABLED) {
-                       err = audit_set_enabled(status_get->enabled);
+                       err = audit_set_enabled(status_get->enabled, loginuid);
                        if (err < 0) return err;
                }
                if (status_get->mask & AUDIT_STATUS_FAILURE) {
-                       err = audit_set_failure(status_get->failure);
+                       err = audit_set_failure(status_get->failure, loginuid);
                        if (err < 0) return err;
                }
                if (status_get->mask & AUDIT_STATUS_PID) {
                        int old   = audit_pid;
                        audit_pid = status_get->pid;
-                       audit_log(current->audit_context,
-                                 "audit_pid=%d old=%d", audit_pid, old);
+                       audit_log(NULL, "audit_pid=%d old=%d by auid %u",
+                                 audit_pid, old, loginuid);
                }
                if (status_get->mask & AUDIT_STATUS_RATE_LIMIT)
-                       audit_set_rate_limit(status_get->rate_limit);
+                       audit_set_rate_limit(status_get->rate_limit, loginuid);
                if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT)
-                       audit_set_backlog_limit(status_get->backlog_limit);
+                       audit_set_backlog_limit(status_get->backlog_limit,
+                                                       loginuid);
                break;
        case AUDIT_USER:
                ab = audit_log_start(NULL);
                if (!ab)
                        break;  /* audit_panic has been called */
                audit_log_format(ab,
-                                "user pid=%d uid=%d length=%d msg='%.1024s'",
+                                "user pid=%d uid=%d length=%d loginuid=%u"
+                                " msg='%.1024s'",
                                 pid, uid,
                                 (int)(nlh->nlmsg_len
                                       - ((char *)data - (char *)nlh)),
-                                (char *)data);
+                                loginuid, (char *)data);
                ab->type = AUDIT_USER;
                ab->pid  = pid;
                audit_log_end(ab);
@@ -411,7 +414,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
        case AUDIT_LIST:
 #ifdef CONFIG_AUDITSYSCALL
                err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
-                                          uid, seq, data);
+                                          uid, seq, data, loginuid);
 #else
                err = -EOPNOTSUPP;
 #endif
@@ -480,7 +483,7 @@ static void audit_log_move(struct audit_buffer *ab)
        if (ab->len == 0)
                return;
 
-       skb = skb_peek(&ab->sklist);
+       skb = skb_peek_tail(&ab->sklist);
        if (!skb || skb_tailroom(skb) <= ab->len + extra) {
                skb = alloc_skb(2 * ab->len + extra, GFP_ATOMIC);
                if (!skb) {
@@ -519,9 +522,9 @@ static inline int audit_log_drain(struct audit_buffer *ab)
                        retval = netlink_unicast(audit_sock, skb, audit_pid,
                                                 MSG_DONTWAIT);
                }
-               if (retval == -EAGAIN && ab->count < 5) {
-                       ++ab->count;
-                       skb_queue_tail(&ab->sklist, skb);
+               if (retval == -EAGAIN &&
+                   (atomic_read(&audit_backlog)) < audit_backlog_limit) {
+                       skb_queue_head(&ab->sklist, skb);
                        audit_log_end_irq(ab);
                        return 1;
                }
@@ -537,8 +540,8 @@ static inline int audit_log_drain(struct audit_buffer *ab)
                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;
@@ -617,7 +620,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx)
        struct audit_buffer     *ab     = NULL;
        unsigned long           flags;
        struct timespec         t;
-       int                     serial  = 0;
+       unsigned int            serial;
 
        if (!audit_initialized)
                return NULL;
@@ -659,15 +662,16 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx)
        ab->total = 0;
        ab->type  = AUDIT_KERNEL;
        ab->pid   = 0;
-       ab->count = 0;
 
 #ifdef CONFIG_AUDITSYSCALL
        if (ab->ctx)
                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;
@@ -717,6 +721,29 @@ void audit_log_format(struct audit_buffer *ab, const char *fmt, ...)
        va_end(args);
 }
 
+void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf, size_t len)
+{
+       int i;
+
+       for (i=0; i<len; i++)
+               audit_log_format(ab, "%02x", buf[i]);
+}
+
+void audit_log_untrustedstring(struct audit_buffer *ab, const char *string)
+{
+       const unsigned char *p = string;
+
+       while (*p) {
+               if (*p == '"' || *p == ' ' || *p < 0x20 || *p > 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. */
index 6f1931381bc9eae1ff454c943036c5b077c4a8a6..37b3ac94bc47492d026ae697cc92b1d4ddd70bd5 100644 (file)
@@ -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;
@@ -250,7 +251,8 @@ static int audit_copy_rule(struct audit_rule *d, struct audit_rule *s)
        return 0;
 }
 
-int audit_receive_filter(int type, int pid, int uid, int seq, void *data)
+int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
+                                                       uid_t loginuid)
 {
        u32                flags;
        struct audit_entry *entry;
@@ -285,6 +287,7 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data)
                        err = audit_add_rule(entry, &audit_entlist);
                if (!err && (flags & AUDIT_AT_EXIT))
                        err = audit_add_rule(entry, &audit_extlist);
+               audit_log(NULL, "auid %u added an audit rule\n", loginuid);
                break;
        case AUDIT_DEL:
                flags =((struct audit_rule *)data)->flags;
@@ -294,6 +297,7 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data)
                        err = audit_del_rule(data, &audit_entlist);
                if (!err && (flags & AUDIT_AT_EXIT))
                        err = audit_del_rule(data, &audit_extlist);
+               audit_log(NULL, "auid %u removed an audit rule\n", loginuid);
                break;
        default:
                return -EINVAL;
@@ -348,6 +352,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 +363,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 +656,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"
@@ -696,9 +707,10 @@ static void audit_log_exit(struct audit_context *context)
                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",
@@ -772,7 +784,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)
 {
@@ -826,6 +838,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;
@@ -849,13 +862,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
@@ -868,6 +881,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;
@@ -981,7 +995,7 @@ void audit_inode(const char *name, const struct inode *inode)
 }
 
 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;
@@ -996,20 +1010,21 @@ void audit_get_stamp(struct audit_context *ctx,
 
 extern int audit_set_type(struct audit_buffer *ab, int type);
 
-int audit_set_loginuid(struct audit_context *ctx, uid_t loginuid)
+int audit_set_loginuid(struct task_struct *task, uid_t loginuid)
 {
-       if (ctx) {
+       if (task->audit_context) {
                struct audit_buffer *ab;
 
                ab = audit_log_start(NULL);
                if (ab) {
                        audit_log_format(ab, "login pid=%d uid=%u "
                                "old loginuid=%u new loginuid=%u",
-                               ctx->pid, ctx->uid, ctx->loginuid, loginuid);
+                               task->pid, task->uid, 
+                               task->audit_context->loginuid, loginuid);
                        audit_set_type(ab, AUDIT_LOGIN);
                        audit_log_end(ab);
                }
-               ctx->loginuid = loginuid;
+               task->audit_context->loginuid = loginuid;
        }
        return 0;
 }
index 4ee392066148e771925f601c5159f6d0960776af..733bf52cef3e72c663a9f4bc7f90cecab421c706 100644 (file)
@@ -49,6 +49,8 @@
 #include <linux/bitops.h>
 #include <linux/mm.h>
 #include <linux/types.h>
+#include <linux/audit.h>
+
 #include <net/sock.h>
 #include <net/scm.h>
 
@@ -904,6 +906,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
        NETLINK_CB(skb).groups  = nlk->groups;
        NETLINK_CB(skb).dst_pid = dst_pid;
        NETLINK_CB(skb).dst_groups = dst_groups;
+       NETLINK_CB(skb).loginuid = audit_get_loginuid(current->audit_context);
        memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
 
        /* What can I do? Netlink is asynchronous, so that