]> err.no Git - linux-2.6/blobdiff - arch/x86/kernel/entry_64.S
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6] / arch / x86 / kernel / entry_64.S
index 8410e26f418337d7fc37d77dba6a1f0e60e7f525..89434d439605484b48a7b26ba31c55e82c9821c5 100644 (file)
 #include <asm/paravirt.h>
 #include <asm/ftrace.h>
 
+/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this.  */
+#include <linux/elf-em.h>
+#define AUDIT_ARCH_X86_64      (EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
+#define __AUDIT_ARCH_64BIT 0x80000000
+#define __AUDIT_ARCH_LE           0x40000000
+
        .code64
 
 #ifdef CONFIG_FTRACE
@@ -351,6 +357,7 @@ ENTRY(system_call_after_swapgs)
        GET_THREAD_INFO(%rcx)
        testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%rcx)
        jnz tracesys
+system_call_fastpath:
        cmpq $__NR_syscall_max,%rax
        ja badsys
        movq %r10,%rcx
@@ -402,16 +409,16 @@ sysret_careful:
 sysret_signal:
        TRACE_IRQS_ON
        ENABLE_INTERRUPTS(CLBR_NONE)
-       testl $_TIF_DO_NOTIFY_MASK,%edx
-       jz    1f
-
-       /* Really a signal */
+#ifdef CONFIG_AUDITSYSCALL
+       bt $TIF_SYSCALL_AUDIT,%edx
+       jc sysret_audit
+#endif
        /* edx: work flags (arg3) */
        leaq do_notify_resume(%rip),%rax
        leaq -ARGOFFSET(%rsp),%rdi # &pt_regs -> arg1
        xorl %esi,%esi # oldset -> arg2
        call ptregscall_common
-1:     movl $_TIF_WORK_MASK,%edi
+       movl $_TIF_WORK_MASK,%edi
        /* Use IRET because user could have changed frame. This
           works because ptregscall_common has called FIXUP_TOP_OF_STACK. */
        DISABLE_INTERRUPTS(CLBR_NONE)
@@ -422,8 +429,45 @@ badsys:
        movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
        jmp ret_from_sys_call
 
+#ifdef CONFIG_AUDITSYSCALL
+       /*
+        * Fast path for syscall audit without full syscall trace.
+        * We just call audit_syscall_entry() directly, and then
+        * jump back to the normal fast path.
+        */
+auditsys:
+       movq %r10,%r9                   /* 6th arg: 4th syscall arg */
+       movq %rdx,%r8                   /* 5th arg: 3rd syscall arg */
+       movq %rsi,%rcx                  /* 4th arg: 2nd syscall arg */
+       movq %rdi,%rdx                  /* 3rd arg: 1st syscall arg */
+       movq %rax,%rsi                  /* 2nd arg: syscall number */
+       movl $AUDIT_ARCH_X86_64,%edi    /* 1st arg: audit arch */
+       call audit_syscall_entry
+       LOAD_ARGS 0             /* reload call-clobbered registers */
+       jmp system_call_fastpath
+
+       /*
+        * Return fast path for syscall audit.  Call audit_syscall_exit()
+        * directly and then jump back to the fast path with TIF_SYSCALL_AUDIT
+        * masked off.
+        */
+sysret_audit:
+       movq %rax,%rsi          /* second arg, syscall return value */
+       cmpq $0,%rax            /* is it < 0? */
+       setl %al                /* 1 if so, 0 if not */
+       movzbl %al,%edi         /* zero-extend that into %edi */
+       inc %edi /* first arg, 0->1(AUDITSC_SUCCESS), 1->2(AUDITSC_FAILURE) */
+       call audit_syscall_exit
+       movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi
+       jmp sysret_check
+#endif /* CONFIG_AUDITSYSCALL */
+
        /* Do syscall tracing */
 tracesys:                       
+#ifdef CONFIG_AUDITSYSCALL
+       testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%rcx)
+       jz auditsys
+#endif
        SAVE_REST
        movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
        FIXUP_TOP_OF_STACK %rdi
@@ -448,6 +492,7 @@ tracesys:
  * Has correct top of stack, but partial stack frame.
  */
        .globl int_ret_from_sys_call
+       .globl int_with_check
 int_ret_from_sys_call:
        DISABLE_INTERRUPTS(CLBR_NONE)
        TRACE_IRQS_OFF