[PATCH] per arch syscall info
Chris Wright
chrisw at osdl.org
Tue Mar 22 18:07:58 UTC 2005
* David Woodhouse (dwmw2 at infradead.org) wrote:
> 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.
Ah yes, much better plan.
> 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.
Nice cleanup.
> I also stopped logging the arch for a second time in syscall exit.
Agreed, I see no reason to keep it (was never triggered in a meaningful
way in my limited testing). BTW, what about arch/um?
> --- 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",
Kinda surprised to see a string as opposed to decimal value, but
it also doesn't really matter ;-)
> + 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) && )
Woops, lost !entryexit
> + 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)
Heh, now we have to get audit support in all those extra arches ;-)
> +
> #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)
Insignificant nits for audit_syscall_exit() ...s/ta/f/ And, might as
well use 'arch' across the board for audit_syscall_entry().
> #define audit_getname(n) do { ; } while (0)
> #define audit_putname(n) do { ; } while (0)
> #define audit_inode(n,i) do { ; } while (0)
More information about the Linux-audit
mailing list