Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1191851

[PATCH 2/3] x86/asm/entry/32: Remove most of SYSCALL32 code, part 1

From Denys Vlasenko <dvlasenk@redhat.com>
Newsgroups linux.kernel
Subject [PATCH 2/3] x86/asm/entry/32: Remove most of SYSCALL32 code, part 1
Date 2015-07-24 15:50 +0200
Message-ID <pPLwn-7ok-23@gated-at.bofh.it> (permalink)
References <pPLwl-7ok-1@gated-at.bofh.it>
Organization linux.* mail to news gateway

Show all headers | View raw


SYSCALL32 code is nearly identical to SYSCALL32, except for initial
section. Merge them.

The removal is split into two parts, to make review eaiser. This is part 1.

auditsys_entry_common and auditsys_exit macros are indented one more tab without
any changes. This prevents diff from becoming unreadable.
They will be removed in part 2.

Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
CC: Ingo Molnar <mingo@kernel.org>
CC: Linus Torvalds <torvalds@linux-foundation.org>
CC: Krzysztof A. Sobiecki <sobkas@gmail.com>
CC: Steven Rostedt <rostedt@goodmis.org>
CC: Borislav Petkov <bp@alien8.de>
CC: "H. Peter Anvin" <hpa@zytor.com>
CC: Andy Lutomirski <luto@amacapital.net>
CC: Oleg Nesterov <oleg@redhat.com>
CC: Frederic Weisbecker <fweisbec@gmail.com>
CC: Alexei Starovoitov <ast@plumgrid.com>
CC: Will Drewry <wad@chromium.org>
CC: Kees Cook <keescook@chromium.org>
CC: x86@kernel.org
CC: linux-kernel@vger.kernel.org
---
 arch/x86/entry/entry_64_compat.S | 237 +++++++++++----------------------------
 1 file changed, 63 insertions(+), 174 deletions(-)

diff --git a/arch/x86/entry/entry_64_compat.S b/arch/x86/entry/entry_64_compat.S
index 9f9dfa5..2d0a2f0 100644
--- a/arch/x86/entry/entry_64_compat.S
+++ b/arch/x86/entry/entry_64_compat.S
@@ -16,13 +16,7 @@
 #include <linux/linkage.h>
 #include <linux/err.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		ia32_ret_from_sys_call_irqs_off
 # define sysretl_audit		ia32_ret_from_sys_call_irqs_off
 #endif
 
@@ -93,188 +87,82 @@ ENTRY(entry_SYSENTER_compat)
 	 * 32-bit zero extended
 	 */
 	ASM_STAC
-1:	movl	(%rbp), %ebp
+1:	movl	(%rbp), %r9d
 	_ASM_EXTABLE(1b, ia32_badarg)
 	ASM_CLAC
 
 	/*
-	 * Sysenter doesn't filter flags, so we need to clear NT
-	 * ourselves.  To save a few cycles, we can check whether
-	 * NT was set instead of doing an unconditional popfq.
+	 * Sysenter doesn't filter flags, so we need to clear NT ourselves.
 	 */
 	testl	$X86_EFLAGS_NT, EFLAGS(%rsp)
 	jnz	sysenter_fix_flags
 sysenter_flags_fixed:
-
-	orl	$TS_COMPAT, ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS)
-	testl	$_TIF_WORK_SYSCALL_ENTRY, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
-	jnz	sysenter_tracesys
-
-sysenter_do_call:
-	/* 32-bit syscall -> 64-bit C ABI argument conversion */
-	movl	%edi, %r8d		/* arg5 */
-	movl	%ebp, %r9d		/* arg6 */
-	xchg	%ecx, %esi		/* rsi:arg2, rcx:arg4 */
-	movl	%ebx, %edi		/* arg1 */
-	movl	%edx, %edx		/* arg3 (zero extension) */
-
-sysenter_dispatch:
-	cmpq	$(IA32_NR_syscalls-1), %rax
-	ja	1f
-	call	*ia32_sys_call_table(, %rax, 8)
-	movq	%rax, RAX(%rsp)
-1:
-	DISABLE_INTERRUPTS(CLBR_NONE)
-	TRACE_IRQS_OFF
-	testl	$_TIF_ALLWORK_MASK, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
-	jnz	sysexit_audit
-
-sysexit_from_sys_call:
-	/*
-	 * NB: SYSEXIT is not obviously safe for 64-bit kernels -- an
-	 * NMI between STI and SYSEXIT has poorly specified behavior,
-	 * and and NMI followed by an IRQ with usergs is fatal.  So
-	 * we just pretend we're using SYSEXIT but we really use
-	 * SYSRETL instead.
-	 *
-	 * This code path is still called 'sysexit' because it pairs
-	 * with 'sysenter' and it uses the SYSENTER calling convention.
-	 */
-	andl	$~TS_COMPAT, ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS)
-	movl	RSI(%rsp), %esi
-	movl	RDI(%rsp), %edi
-	movl	RIP(%rsp), %ecx		/* User %eip */
-	movl	EFLAGS(%rsp), %r11d	/* User eflags */
-	xorl	%edx, %edx		/* Do not leak kernel information */
-	xorq	%r10, %r10
-	xorq	%r9, %r9
-	xorq	%r8, %r8
-	TRACE_IRQS_ON
-
-	/*
-	 * SYSRETL works even on Intel CPUs.  Use it in preference to SYSEXIT,
-	 * since it avoids a dicey window with interrupts enabled.
-	 */
-	movl	RSP(%rsp), %esp
-
-	/*
-	 * USERGS_SYSRET32 does:
-	 *  gsbase = user's gs base
-	 *  eip = ecx
-	 *  rflags = r11
-	 *  cs = __USER32_CS
-	 *  ss = __USER_DS
-	 *
-	 * The prologue set RIP(%rsp) to VDSO32_SYSENTER_RETURN, which does:
-	 *
-	 *  pop %ebp
-	 *  pop %edx
-	 *  pop %ecx
-	 *
-	 * Therefore, we invoke SYSRETL with EDX and R8-R10 zeroed to
-	 * avoid info leaks.  R11 ends up with VDSO32_SYSENTER_RETURN's
-	 * address (already known to user code), and R12-R15 are
-	 * callee-saved and therefore don't contain any interesting
-	 * kernel data.
-	 */
-	USERGS_SYSRET32
-
-#ifdef CONFIG_AUDITSYSCALL
-	.macro auditsys_entry_common
-	/*
-	 * At this point, registers hold syscall args in the 32-bit syscall ABI:
-	 * EAX is syscall number, the 6 args are in EBX,ECX,EDX,ESI,EDI,EBP.
-	 *
-	 * We want to pass them to __audit_syscall_entry(), which is a 64-bit
-	 * C function with 5 parameters, so shuffle them to match what
-	 * the function expects: RDI,RSI,RDX,RCX,R8.
-	 */
-	movl	%esi, %r8d		/* arg5 (R8 ) <= 4th syscall arg (ESI) */
-	xchg	%ecx, %edx		/* arg4 (RCX) <= 3rd syscall arg (EDX) */
-					/* arg3 (RDX) <= 2nd syscall arg (ECX) */
-	movl	%ebx, %esi		/* arg2 (RSI) <= 1st syscall arg (EBX) */
-	movl	%eax, %edi		/* arg1 (RDI) <= syscall number  (EAX) */
-	call	__audit_syscall_entry
-
-	/*
-	 * We are going to jump back to the syscall dispatch code.
-	 * Prepare syscall args as required by the 64-bit C ABI.
-	 * Registers clobbered by __audit_syscall_entry() are
-	 * loaded from pt_regs on stack:
-	 */
-	movl	ORIG_RAX(%rsp), %eax	/* syscall number */
-	movl	%ebx, %edi		/* arg1 */
-	movl	RCX(%rsp), %esi		/* arg2 */
-	movl	RDX(%rsp), %edx		/* arg3 */
-	movl	RSI(%rsp), %ecx		/* arg4 */
-	movl	RDI(%rsp), %r8d		/* arg5 */
-	.endm
-
-	.macro auditsys_exit exit
-	TRACE_IRQS_ON
-	ENABLE_INTERRUPTS(CLBR_NONE)
-	testl	$(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
-	jnz	ia32_ret_from_sys_call
-	movl	%eax, %esi		/* second arg, syscall return value */
-	cmpl	$-MAX_ERRNO, %eax	/* is it an error ? */
-	jbe	1f
-	movslq	%eax, %rsi		/* if error sign extend to 64 bits */
-1:	setbe	%al			/* 1 if error, 0 if not */
-	movzbl	%al, %edi		/* zero-extend that into %edi */
-	call	__audit_syscall_exit
-	movq	RAX(%rsp), %rax		/* reload syscall return value */
-	movl	$(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %edi
-	DISABLE_INTERRUPTS(CLBR_NONE)
-	TRACE_IRQS_OFF
-	testl	%edi, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
-	jz	\exit
-	xorl	%eax, %eax		/* Do not leak kernel information */
-	movq	%rax, R11(%rsp)
-	movq	%rax, R10(%rsp)
-	movq	%rax, R9(%rsp)
-	movq	%rax, R8(%rsp)
-	jmp	int_ret_from_sys_call_irqs_off
-	.endm
-
-sysenter_auditsys:
-	auditsys_entry_common
-	movl	%ebp, %r9d		/* reload 6th syscall arg */
-	jmp	sysenter_dispatch
-
-sysexit_audit:
-	auditsys_exit sysexit_from_sys_call
-#endif
+	jmp	sysenter_jumps_here
 
 sysenter_fix_flags:
 	pushq	$(X86_EFLAGS_IF|X86_EFLAGS_FIXED)
 	popfq
 	jmp	sysenter_flags_fixed
-
-sysenter_tracesys:
-#ifdef CONFIG_AUDITSYSCALL
-	testl	$(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT), ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
-	jz	sysenter_auditsys
-#endif
-	SAVE_EXTRA_REGS
-	xorl	%eax, %eax		/* Do not leak kernel information */
-	movq	%rax, R11(%rsp)
-	movq	%rax, R10(%rsp)
-	movq	%rax, R9(%rsp)
-	movq	%rax, R8(%rsp)
-	movq	%rsp, %rdi		/* &pt_regs -> arg1 */
-	call	syscall_trace_enter
-
-	/* Reload arg registers from stack. (see sysenter_tracesys) */
-	movl	RCX(%rsp), %ecx
-	movl	RDX(%rsp), %edx
-	movl	RSI(%rsp), %esi
-	movl	RDI(%rsp), %edi
-	movl	%eax, %eax		/* zero extension */
-
-	RESTORE_EXTRA_REGS
-	jmp	sysenter_do_call
 ENDPROC(entry_SYSENTER_compat)
 
+
+	#ifdef CONFIG_AUDITSYSCALL
+		.macro auditsys_entry_common
+		/*
+		 * At this point, registers hold syscall args in the 32-bit syscall ABI:
+		 * EAX is syscall number, the 6 args are in EBX,ECX,EDX,ESI,EDI,EBP.
+		 *
+		 * We want to pass them to __audit_syscall_entry(), which is a 64-bit
+		 * C function with 5 parameters, so shuffle them to match what
+		 * the function expects: RDI,RSI,RDX,RCX,R8.
+		 */
+		movl	%esi, %r8d		/* arg5 (R8 ) <= 4th syscall arg (ESI) */
+		xchg	%ecx, %edx		/* arg4 (RCX) <= 3rd syscall arg (EDX) */
+						/* arg3 (RDX) <= 2nd syscall arg (ECX) */
+		movl	%ebx, %esi		/* arg2 (RSI) <= 1st syscall arg (EBX) */
+		movl	%eax, %edi		/* arg1 (RDI) <= syscall number  (EAX) */
+		call	__audit_syscall_entry
+
+		/*
+		 * We are going to jump back to the syscall dispatch code.
+		 * Prepare syscall args as required by the 64-bit C ABI.
+		 * Registers clobbered by __audit_syscall_entry() are
+		 * loaded from pt_regs on stack:
+		 */
+		movl	ORIG_RAX(%rsp), %eax	/* syscall number */
+		movl	%ebx, %edi		/* arg1 */
+		movl	RCX(%rsp), %esi		/* arg2 */
+		movl	RDX(%rsp), %edx		/* arg3 */
+		movl	RSI(%rsp), %ecx		/* arg4 */
+		movl	RDI(%rsp), %r8d		/* arg5 */
+		.endm
+
+		.macro auditsys_exit exit
+		TRACE_IRQS_ON
+		ENABLE_INTERRUPTS(CLBR_NONE)
+		testl	$(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
+		jnz	ia32_ret_from_sys_call
+		movl	%eax, %esi		/* second arg, syscall return value */
+		cmpl	$-MAX_ERRNO, %eax	/* is it an error ? */
+		jbe	1f
+		movslq	%eax, %rsi		/* if error sign extend to 64 bits */
+	1:	setbe	%al			/* 1 if error, 0 if not */
+		movzbl	%al, %edi		/* zero-extend that into %edi */
+		call	__audit_syscall_exit
+		movq	RAX(%rsp), %rax		/* reload syscall return value */
+		movl	$(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %edi
+		DISABLE_INTERRUPTS(CLBR_NONE)
+		TRACE_IRQS_OFF
+		testl	%edi, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
+		jz	\exit
+		xorl	%eax, %eax		/* Do not leak kernel information */
+		movq	%rax, R11(%rsp)
+		movq	%rax, R10(%rsp)
+		movq	%rax, R9(%rsp)
+		movq	%rax, R8(%rsp)
+		jmp	int_ret_from_sys_call_irqs_off
+		.endm
+	#endif
 /*
  * 32-bit SYSCALL instruction entry.
  *
@@ -343,6 +231,7 @@ ENTRY(entry_SYSCALL_compat)
 	_ASM_EXTABLE(1b, ia32_badarg)
 	ASM_CLAC
 
+sysenter_jumps_here:
 	orl	$TS_COMPAT, ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS)
 	testl	$_TIF_WORK_SYSCALL_ENTRY, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
 	jnz	cstar_tracesys
@@ -421,7 +310,7 @@ cstar_tracesys:
 	call	syscall_trace_enter
 	movl	R9(%rsp), %r9d
 
-	/* Reload arg registers from stack. (see sysenter_tracesys) */
+	/* Reload arg registers from stack. */
 	movl	RCX(%rsp), %ecx
 	movl	RDX(%rsp), %edx
 	movl	RSI(%rsp), %esi
-- 
1.8.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Back to linux.kernel | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

[PATCH 1/3] x86/asm/entry/32: Massage SYSENTER32 fast path to be nearly identical to SYSCALL32 Denys Vlasenko <dvlasenk@redhat.com> - 2015-07-24 15:50 +0200
  [PATCH 3/3] x86/asm/entry/32: Remove most of SYSCALL32 code, part 2 Denys Vlasenko <dvlasenk@redhat.com> - 2015-07-24 15:50 +0200
  [PATCH 2/3] x86/asm/entry/32: Remove most of SYSCALL32 code, part 1 Denys Vlasenko <dvlasenk@redhat.com> - 2015-07-24 15:50 +0200
    Re: [PATCH 2/3] x86/asm/entry/32: Remove most of SYSCALL32 code,  part 1 Denys Vlasenko <dvlasenk@redhat.com> - 2015-07-25 20:40 +0200
      Re: [PATCH 2/3] x86/asm/entry/32: Remove most of SYSCALL32 code, part 1 Andy Lutomirski <luto@amacapital.net> - 2015-07-25 21:40 +0200

csiph-web