[PATCH] per arch syscall info

David Woodhouse dwmw2 at infradead.org
Tue Mar 22 16:54:53 UTC 2005


On Wed, 2005-03-16 at 18:13 -0800, Chris Wright wrote:
> +/* distinguish syscall tables */
> +#define AUDIT_ARCH_IA32                0
> +#define AUDIT_ARCH_X86_64      1
> +#define AUDIT_ARCH_IA64                2
> +#define AUDIT_ARCH_PPC         3
> +#define AUDIT_ARCH_PPC64       4
> +#define AUDIT_ARCH_MIPS                5

I really don't like making up a new centralised number space for these.
So much so that I almost suggested using strings. I don't like the cost
of filtering on those though. Let's compromise and use existing numbers,
like the ELF machine types.

This is the patch from my audit.15 kernel which should be turning up
shortly. We finish the arch identifiers, fix the ptrace/audit ordering
problem, fix the return code of syscalls to be 'long', and use an
explicit success/failure flag on architectures where that's conveyed
separately from the return code.

I also stopped logging the arch for a second time in syscall exit.

--- linux-2.6.9/kernel/auditsc.c.auditarch	2005-03-18 14:13:01.000000000 +0000
+++ linux-2.6.9/kernel/auditsc.c	2005-03-22 14:28:14.095999744 +0000
@@ -124,7 +124,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];
@@ -136,6 +136,7 @@ struct audit_context {
 	uid_t		    uid, euid, suid, fsuid;
 	gid_t		    gid, egid, sgid, fsgid;
 	unsigned long	    personality;
+	int		    arch;
 	struct list_head    wtrail; /* The list of watched files/dirs that were
 				     * accessed and determined to be valid and
 				     * unfiltered in this audit_context
@@ -372,6 +373,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)
@@ -379,7 +384,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) {
@@ -679,8 +684,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=%d", 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"
@@ -821,7 +829,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)
 {
@@ -875,6 +883,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;
@@ -898,13 +907,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
@@ -917,6 +926,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;
--- linux-2.6.9/arch/s390/kernel/ptrace.c.auditarch	2004-10-18 22:55:07.000000000 +0100
+++ linux-2.6.9/arch/s390/kernel/ptrace.c	2005-03-22 14:25:23.251013360 +0000
@@ -707,18 +707,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));
 
@@ -731,4 +726,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]);
 }
--- linux-2.6.9/arch/ppc64/kernel/ptrace.c.auditarch	2005-03-18 14:13:01.000000000 +0000
+++ linux-2.6.9/arch/ppc64/kernel/ptrace.c	2005-03-22 14:25:23.215018832 +0000
@@ -303,20 +303,24 @@ 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)
 {
 	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))
--- linux-2.6.9/arch/x86_64/kernel/ptrace.c.auditarch	2004-10-18 22:53:46.000000000 +0100
+++ linux-2.6.9/arch/x86_64/kernel/ptrace.c	2005-03-22 14:34:51.447034792 +0000
@@ -517,22 +517,27 @@ 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)
 {
+	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))
--- linux-2.6.9/arch/mips/kernel/ptrace.c.auditarch	2004-10-18 22:55:36.000000000 +0100
+++ linux-2.6.9/arch/mips/kernel/ptrace.c	2005-03-22 14:39:32.757005608 +0000
@@ -305,19 +305,13 @@ out:
  */
 asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
 {
-	if (unlikely(current->audit_context)) {
-		if (!entryexit)
-			audit_syscall_entry(current, regs->orig_eax,
-			                    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 */
@@ -333,4 +327,9 @@ asmlinkage void do_syscall_trace(struct 
 		send_sig(current->exit_code, current, 1);
 		current->exit_code = 0;
 	}
+ out:
+	if (unlikely(current->audit_context) && )
+		audit_syscall_entry(current, audit_arch(), regs->orig_eax,
+				    regs->regs[4], regs->regs[5],
+				    regs->regs[6], regs->regs[7]);
 }
--- linux-2.6.9/arch/i386/kernel/ptrace.c.auditarch	2004-10-18 22:53:45.000000000 +0100
+++ linux-2.6.9/arch/i386/kernel/ptrace.c	2005-03-22 14:30:39.853075920 +0000
@@ -530,20 +530,14 @@ out:
 __attribute__((regparm(3)))
 void do_syscall_trace(struct pt_regs *regs, int entryexit)
 {
-	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 (!test_thread_flag(TIF_SYSCALL_TRACE) &&
 	    !test_thread_flag(TIF_SINGLESTEP))
-		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 */
 	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) &&
@@ -558,4 +552,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);
+
 }
--- linux-2.6.9/arch/ia64/kernel/ptrace.c.auditarch	2004-10-18 22:55:29.000000000 +0100
+++ linux-2.6.9/arch/ia64/kernel/ptrace.c	2005-03-22 14:38:02.299044824 +0000
@@ -17,6 +17,7 @@
 #include <linux/smp_lock.h>
 #include <linux/user.h>
 #include <linux/security.h>
+#include <linux/audit.h>
 
 #include <asm/pgtable.h>
 #include <asm/processor.h>
@@ -1511,17 +1511,22 @@ syscall_trace_enter (long arg0, long arg
 	struct pt_regs *regs = (struct pt_regs *) &stack;
 	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))
+		int arch;
+
+		if (IS_IA32_PROCESS(regs)) {
 			syscall = regs->r1;
-		else
+			arch = AUDIT_ARCH_I386;
+		} else {
 			syscall = regs->r15;
-
-		audit_syscall_entry(current, syscall, arg0, arg1, arg2, arg3);
+			arch = AUDIT_ARCH_IA64;
+		}
+		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... */
@@ -1530,7 +1535,9 @@ syscall_trace_leave (long arg0, long arg
 		     long arg4, long arg5, long arg6, long arg7, long stack)
 {
 	if (unlikely(current->audit_context))
-		audit_syscall_exit(current, ((struct pt_regs *) &stack)->r8);
+		audit_syscall_exit(current, 
+				   AUDITSC_RESULT(((struct pt_regs *) &stack)->r8),
+				   ((struct pt_regs *) &stack)->r8);
 
 	if (test_thread_flag(TIF_SYSCALL_TRACE) && (current->ptrace & PT_PTRACED))
 		syscall_trace();
--- linux-2.6.9/include/linux/audit.h.auditarch	2005-03-18 14:13:01.000000000 +0000
+++ linux-2.6.9/include/linux/audit.h	2005-03-22 14:46:49.005983264 +0000
@@ -28,6 +28,8 @@
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <asm/atomic.h>
+#include <linux/sched.h>
+#include <linux/elf.h>
 #endif
 
 /* Request and reply types */
@@ -75,6 +77,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). */
@@ -108,6 +111,38 @@
 /* 32 byte max key size */
 #define AUDIT_FILTERKEY_MAX	32
 
+/* 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;
@@ -164,15 +199,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 table,
 				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);
@@ -188,8 +227,8 @@ extern int audit_ipc_perms(unsigned long
 #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,ta,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)


-- 
dwmw2




More information about the Linux-audit mailing list