forked from Minki/linux
Merge branch 'x86/auditsc' of git://git.kernel.org/pub/scm/linux/kernel/git/frob/linux-2.6-roland
* 'x86/auditsc' of git://git.kernel.org/pub/scm/linux/kernel/git/frob/linux-2.6-roland: i386 syscall audit fast-path x86_64 ia32 syscall audit fast-path x86_64 syscall audit fast-path x86_64: remove bogus optimization in sysret_signal
This commit is contained in:
commit
338b9bb3ad
@ -15,6 +15,16 @@
|
||||
#include <asm/irqflags.h>
|
||||
#include <linux/linkage.h>
|
||||
|
||||
/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */
|
||||
#include <linux/elf-em.h>
|
||||
#define AUDIT_ARCH_I386 (EM_386|__AUDIT_ARCH_LE)
|
||||
#define __AUDIT_ARCH_LE 0x40000000
|
||||
|
||||
#ifndef CONFIG_AUDITSYSCALL
|
||||
#define sysexit_audit int_ret_from_sys_call
|
||||
#define sysretl_audit int_ret_from_sys_call
|
||||
#endif
|
||||
|
||||
#define IA32_NR_syscalls ((ia32_syscall_end - ia32_sys_call_table)/8)
|
||||
|
||||
.macro IA32_ARG_FIXUP noebp=0
|
||||
@ -148,13 +158,15 @@ ENTRY(ia32_sysenter_target)
|
||||
ja ia32_badsys
|
||||
sysenter_do_call:
|
||||
IA32_ARG_FIXUP 1
|
||||
sysenter_dispatch:
|
||||
call *ia32_sys_call_table(,%rax,8)
|
||||
movq %rax,RAX-ARGOFFSET(%rsp)
|
||||
GET_THREAD_INFO(%r10)
|
||||
DISABLE_INTERRUPTS(CLBR_NONE)
|
||||
TRACE_IRQS_OFF
|
||||
testl $_TIF_ALLWORK_MASK,TI_flags(%r10)
|
||||
jnz int_ret_from_sys_call
|
||||
jnz sysexit_audit
|
||||
sysexit_from_sys_call:
|
||||
andl $~TS_COMPAT,TI_status(%r10)
|
||||
/* clear IF, that popfq doesn't enable interrupts early */
|
||||
andl $~0x200,EFLAGS-R11(%rsp)
|
||||
@ -170,9 +182,63 @@ sysenter_do_call:
|
||||
TRACE_IRQS_ON
|
||||
ENABLE_INTERRUPTS_SYSEXIT32
|
||||
|
||||
sysenter_tracesys:
|
||||
#ifdef CONFIG_AUDITSYSCALL
|
||||
.macro auditsys_entry_common
|
||||
movl %esi,%r9d /* 6th arg: 4th syscall arg */
|
||||
movl %edx,%r8d /* 5th arg: 3rd syscall arg */
|
||||
/* (already in %ecx) 4th arg: 2nd syscall arg */
|
||||
movl %ebx,%edx /* 3rd arg: 1st syscall arg */
|
||||
movl %eax,%esi /* 2nd arg: syscall number */
|
||||
movl $AUDIT_ARCH_I386,%edi /* 1st arg: audit arch */
|
||||
call audit_syscall_entry
|
||||
movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall number */
|
||||
cmpl $(IA32_NR_syscalls-1),%eax
|
||||
ja ia32_badsys
|
||||
movl %ebx,%edi /* reload 1st syscall arg */
|
||||
movl RCX-ARGOFFSET(%rsp),%esi /* reload 2nd syscall arg */
|
||||
movl RDX-ARGOFFSET(%rsp),%edx /* reload 3rd syscall arg */
|
||||
movl RSI-ARGOFFSET(%rsp),%ecx /* reload 4th syscall arg */
|
||||
movl RDI-ARGOFFSET(%rsp),%r8d /* reload 5th syscall arg */
|
||||
.endm
|
||||
|
||||
.macro auditsys_exit exit
|
||||
testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10)
|
||||
jnz int_ret_from_sys_call
|
||||
TRACE_IRQS_ON
|
||||
sti
|
||||
movl %eax,%esi /* second arg, syscall return value */
|
||||
cmpl $0,%eax /* 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
|
||||
GET_THREAD_INFO(%r10)
|
||||
movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall return value */
|
||||
movl RBP-ARGOFFSET(%rsp),%ebp /* reload user register value */
|
||||
movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi
|
||||
cli
|
||||
TRACE_IRQS_OFF
|
||||
testl %edi,TI_flags(%r10)
|
||||
jnz int_with_check
|
||||
jmp \exit
|
||||
.endm
|
||||
|
||||
sysenter_auditsys:
|
||||
CFI_RESTORE_STATE
|
||||
auditsys_entry_common
|
||||
movl %ebp,%r9d /* reload 6th syscall arg */
|
||||
jmp sysenter_dispatch
|
||||
|
||||
sysexit_audit:
|
||||
auditsys_exit sysexit_from_sys_call
|
||||
#endif
|
||||
|
||||
sysenter_tracesys:
|
||||
xchgl %r9d,%ebp
|
||||
#ifdef CONFIG_AUDITSYSCALL
|
||||
testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10)
|
||||
jz sysenter_auditsys
|
||||
#endif
|
||||
SAVE_REST
|
||||
CLEAR_RREGS
|
||||
movq %r9,R9(%rsp)
|
||||
@ -252,13 +318,15 @@ cstar_do_call:
|
||||
cmpl $IA32_NR_syscalls-1,%eax
|
||||
ja ia32_badsys
|
||||
IA32_ARG_FIXUP 1
|
||||
cstar_dispatch:
|
||||
call *ia32_sys_call_table(,%rax,8)
|
||||
movq %rax,RAX-ARGOFFSET(%rsp)
|
||||
GET_THREAD_INFO(%r10)
|
||||
DISABLE_INTERRUPTS(CLBR_NONE)
|
||||
TRACE_IRQS_OFF
|
||||
testl $_TIF_ALLWORK_MASK,TI_flags(%r10)
|
||||
jnz int_ret_from_sys_call
|
||||
jnz sysretl_audit
|
||||
sysretl_from_sys_call:
|
||||
andl $~TS_COMPAT,TI_status(%r10)
|
||||
RESTORE_ARGS 1,-ARG_SKIP,1,1,1
|
||||
movl RIP-ARGOFFSET(%rsp),%ecx
|
||||
@ -270,8 +338,23 @@ cstar_do_call:
|
||||
CFI_RESTORE rsp
|
||||
USERGS_SYSRET32
|
||||
|
||||
cstar_tracesys:
|
||||
#ifdef CONFIG_AUDITSYSCALL
|
||||
cstar_auditsys:
|
||||
CFI_RESTORE_STATE
|
||||
movl %r9d,R9-ARGOFFSET(%rsp) /* register to be clobbered by call */
|
||||
auditsys_entry_common
|
||||
movl R9-ARGOFFSET(%rsp),%r9d /* reload 6th syscall arg */
|
||||
jmp cstar_dispatch
|
||||
|
||||
sysretl_audit:
|
||||
auditsys_exit sysretl_from_sys_call
|
||||
#endif
|
||||
|
||||
cstar_tracesys:
|
||||
#ifdef CONFIG_AUDITSYSCALL
|
||||
testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10)
|
||||
jz cstar_auditsys
|
||||
#endif
|
||||
xchgl %r9d,%ebp
|
||||
SAVE_REST
|
||||
CLEAR_RREGS
|
||||
|
@ -54,6 +54,16 @@
|
||||
#include <asm/ftrace.h>
|
||||
#include <asm/irq_vectors.h>
|
||||
|
||||
/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */
|
||||
#include <linux/elf-em.h>
|
||||
#define AUDIT_ARCH_I386 (EM_386|__AUDIT_ARCH_LE)
|
||||
#define __AUDIT_ARCH_LE 0x40000000
|
||||
|
||||
#ifndef CONFIG_AUDITSYSCALL
|
||||
#define sysenter_audit syscall_trace_entry
|
||||
#define sysexit_audit syscall_exit_work
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We use macros for low-level operations which need to be overridden
|
||||
* for paravirtualization. The following will never clobber any registers:
|
||||
@ -333,7 +343,8 @@ sysenter_past_esp:
|
||||
|
||||
/* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
|
||||
testw $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
|
||||
jnz syscall_trace_entry
|
||||
jnz sysenter_audit
|
||||
sysenter_do_call:
|
||||
cmpl $(nr_syscalls), %eax
|
||||
jae syscall_badsys
|
||||
call *sys_call_table(,%eax,4)
|
||||
@ -343,7 +354,8 @@ sysenter_past_esp:
|
||||
TRACE_IRQS_OFF
|
||||
movl TI_flags(%ebp), %ecx
|
||||
testw $_TIF_ALLWORK_MASK, %cx
|
||||
jne syscall_exit_work
|
||||
jne sysexit_audit
|
||||
sysenter_exit:
|
||||
/* if something modifies registers it must also disable sysexit */
|
||||
movl PT_EIP(%esp), %edx
|
||||
movl PT_OLDESP(%esp), %ecx
|
||||
@ -351,6 +363,45 @@ sysenter_past_esp:
|
||||
TRACE_IRQS_ON
|
||||
1: mov PT_FS(%esp), %fs
|
||||
ENABLE_INTERRUPTS_SYSEXIT
|
||||
|
||||
#ifdef CONFIG_AUDITSYSCALL
|
||||
sysenter_audit:
|
||||
testw $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
|
||||
jnz syscall_trace_entry
|
||||
addl $4,%esp
|
||||
CFI_ADJUST_CFA_OFFSET -4
|
||||
/* %esi already in 8(%esp) 6th arg: 4th syscall arg */
|
||||
/* %edx already in 4(%esp) 5th arg: 3rd syscall arg */
|
||||
/* %ecx already in 0(%esp) 4th arg: 2nd syscall arg */
|
||||
movl %ebx,%ecx /* 3rd arg: 1st syscall arg */
|
||||
movl %eax,%edx /* 2nd arg: syscall number */
|
||||
movl $AUDIT_ARCH_I386,%eax /* 1st arg: audit arch */
|
||||
call audit_syscall_entry
|
||||
pushl %ebx
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
movl PT_EAX(%esp),%eax /* reload syscall number */
|
||||
jmp sysenter_do_call
|
||||
|
||||
sysexit_audit:
|
||||
testw $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %cx
|
||||
jne syscall_exit_work
|
||||
TRACE_IRQS_ON
|
||||
ENABLE_INTERRUPTS(CLBR_ANY)
|
||||
movl %eax,%edx /* second arg, syscall return value */
|
||||
cmpl $0,%eax /* is it < 0? */
|
||||
setl %al /* 1 if so, 0 if not */
|
||||
movzbl %al,%eax /* zero-extend that */
|
||||
inc %eax /* first arg, 0->1(AUDITSC_SUCCESS), 1->2(AUDITSC_FAILURE) */
|
||||
call audit_syscall_exit
|
||||
DISABLE_INTERRUPTS(CLBR_ANY)
|
||||
TRACE_IRQS_OFF
|
||||
movl TI_flags(%ebp), %ecx
|
||||
testw $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %cx
|
||||
jne syscall_exit_work
|
||||
movl PT_EAX(%esp),%eax /* reload syscall return value */
|
||||
jmp sysenter_exit
|
||||
#endif
|
||||
|
||||
CFI_ENDPROC
|
||||
.pushsection .fixup,"ax"
|
||||
2: movl $0,PT_FS(%esp)
|
||||
|
@ -53,6 +53,12 @@
|
||||
#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
|
||||
|
@ -1476,7 +1476,8 @@ void audit_syscall_entry(int arch, int major,
|
||||
struct audit_context *context = tsk->audit_context;
|
||||
enum audit_state state;
|
||||
|
||||
BUG_ON(!context);
|
||||
if (unlikely(!context))
|
||||
return;
|
||||
|
||||
/*
|
||||
* This happens only on certain architectures that make system
|
||||
|
Loading…
Reference in New Issue
Block a user