[kernel] r21689 - dists/sid/linux/debian/patches/features/x86

Ben Hutchings benh at moszumanska.debian.org
Wed Aug 6 03:30:05 UTC 2014


Author: benh
Date: Wed Aug  6 03:30:05 2014
New Revision: 21689

Log:
Update x32 syscall patch to block system calls >= 512 by default

System calls from x32 tasks are distinguished by having bit 30 set,
but they share the system call table with x86_64 so where parameter/
return value adjustment is needed there is a difference in the low
bits too.  The x32-specific calls are numbered from 512 and of course
are not present in the table if the kernel doesn't support x32.

This means we need to change both the maximum syscall number and the
mask instruction.

Modified:
   dists/sid/linux/debian/patches/features/x86/x86-make-x32-syscall-support-conditional.patch

Modified: dists/sid/linux/debian/patches/features/x86/x86-make-x32-syscall-support-conditional.patch
==============================================================================
--- dists/sid/linux/debian/patches/features/x86/x86-make-x32-syscall-support-conditional.patch	Wed Aug  6 01:52:52 2014	(r21688)
+++ dists/sid/linux/debian/patches/features/x86/x86-make-x32-syscall-support-conditional.patch	Wed Aug  6 03:30:05 2014	(r21689)
@@ -9,15 +9,12 @@
 specific to x32 (at least no-one with a white hat).
 
 Still, adding another flavour just to turn on x32 seems wasteful.  And
-the only difference on syscall entry is whether we mask the x32 flag
-out of the syscall number before range-checking it.
+the only differences on syscall entry are two instructions (mask out
+the x32 flag and compare the syscall number).
 
-So replace the mask (andl) instruction with a nop and add a kernel
-parameter "syscall.x32" which allows it to be enabled/disabled at
-boot time.  Add a Kconfig parameter to set the default.
-
-Change the comparison instruction to cmpq, because now the upper 32
-bits may or may not be cleared by the previous instruction.
+So pad the standard comparison with a nop and add a kernel parameter
+"syscall.x32" which controls whether this is replaced with the x32
+version at boot time.  Add a Kconfig parameter to set the default.
 
 Signed-off-by: Ben Hutchings <ben at decadent.org.uk>
 ---
@@ -43,7 +40,7 @@
  			on older distributions. When this option is enabled
 --- a/arch/x86/Kconfig
 +++ b/arch/x86/Kconfig
-@@ -2383,6 +2383,14 @@ config X86_X32
+@@ -2384,6 +2384,14 @@ config X86_X32
  	  elf32_x86_64 support enabled to compile a kernel with this
  	  option set.
  
@@ -84,60 +81,48 @@
  # error "The following code assumes __USER32_DS == __USER_DS"
 --- a/arch/x86/kernel/entry_64.S
 +++ b/arch/x86/kernel/entry_64.S
-@@ -618,12 +618,14 @@ GLOBAL(system_call_after_swapgs)
- 	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
- 	jnz tracesys
- system_call_fastpath:
--#if __SYSCALL_MASK == ~0
--	cmpq $__NR_syscall_max,%rax
--#else
+@@ -621,8 +621,12 @@ system_call_fastpath:
+ #if __SYSCALL_MASK == ~0
+ 	cmpq $__NR_syscall_max,%rax
+ #else
 -	andl $__SYSCALL_MASK,%eax
 -	cmpl $__NR_syscall_max,%eax
-+#if __SYSCALL_MASK != ~0
-+	.globl system_call_fast_maybe_mask
-+	.globl system_call_fast_masked
-+system_call_fast_maybe_mask:
-+	.byte P6_NOP5_ATOMIC
-+system_call_fast_masked:
++	.globl system_call_fast_compare
++	.globl system_call_fast_compare_end
++system_call_fast_compare:
++	cmpq $511,%rax			/* x32 syscalls start at 512 */
++	.byte P6_NOP4
++system_call_fast_compare_end:
  #endif
-+	cmpq $__NR_syscall_max,%rax
  	ja badsys
  	movq %r10,%rcx
- 	call *sys_call_table(,%rax,8)  # XXX:	 rip relative
-@@ -737,12 +739,14 @@ tracesys:
- 	 */
- 	LOAD_ARGS ARGOFFSET, 1
- 	RESTORE_REST
--#if __SYSCALL_MASK == ~0
--	cmpq $__NR_syscall_max,%rax
--#else
+@@ -740,8 +744,12 @@ tracesys:
+ #if __SYSCALL_MASK == ~0
+ 	cmpq $__NR_syscall_max,%rax
+ #else
 -	andl $__SYSCALL_MASK,%eax
 -	cmpl $__NR_syscall_max,%eax
-+#if __SYSCALL_MASK != ~0
-+	.globl system_call_trace_maybe_mask
-+	.globl system_call_trace_masked
-+system_call_trace_maybe_mask:
-+	.byte P6_NOP5_ATOMIC
-+system_call_trace_masked:
++	.globl system_call_trace_compare
++	.globl system_call_trace_compare_end
++system_call_trace_compare:
++	cmpq $511,%rax			/* x32 syscalls start at 512 */
++	.byte P6_NOP4
++system_call_trace_compare_end:
  #endif
-+	cmpq $__NR_syscall_max,%rax
  	ja   int_ret_from_sys_call	/* RAX(%rsp) set to -ENOSYS above */
  	movq %r10,%rcx	/* fixup for C */
- 	call *sys_call_table(,%rax,8)
-@@ -813,6 +817,18 @@ int_restore_rest:
+@@ -813,6 +821,16 @@ int_restore_rest:
  	CFI_ENDPROC
  END(system_call)
  
 +#if __SYSCALL_MASK != ~0
-+	/*
-+	 * This replaces the nops before the syscall range check
-+	 * if syscall.x32 is set
-+	 */
-+	.globl system_call_mask
-+	.globl system_call_mask_end
-+system_call_mask:
++	/* This replaces the usual comparisons if syscall.x32 is set */
++	.globl system_call_mask_compare
++	.globl system_call_mask_compare_end
++system_call_mask_compare:
 +	andl $__SYSCALL_MASK,%eax
-+system_call_mask_end:
++	cmpl $__NR_syscall_max,%eax
++system_call_mask_compare_end:
 +#endif
 +
  	.macro FORK_LIKE func
@@ -172,21 +157,21 @@
 +bool x32_enabled = !IS_ENABLED(CONFIG_X86_X32_DISABLED);
 +module_param_named(x32, x32_enabled, bool, 0444);
 +
-+extern char system_call_fast_masked[], system_call_fast_maybe_mask[],
-+	system_call_trace_masked[], system_call_trace_maybe_mask[],
-+	system_call_mask_end[], system_call_mask[];
++extern char system_call_fast_compare_end[], system_call_fast_compare[],
++	system_call_trace_compare_end[], system_call_trace_compare[],
++	system_call_mask_compare_end[], system_call_mask_compare[];
 +
 +static int __init x32_enable(void)
 +{
-+	BUG_ON(system_call_fast_masked - system_call_fast_maybe_mask != 5);
-+	BUG_ON(system_call_trace_masked - system_call_trace_maybe_mask != 5);
-+	BUG_ON(system_call_mask_end - system_call_mask != 5);
++	BUG_ON(system_call_fast_compare_end - system_call_fast_compare != 10);
++	BUG_ON(system_call_trace_compare_end - system_call_trace_compare != 10);
++	BUG_ON(system_call_mask_compare_end - system_call_mask_compare != 10);
 +
 +	if (x32_enabled) {
-+		text_poke_early(system_call_fast_maybe_mask,
-+				system_call_mask, 5);
-+		text_poke_early(system_call_trace_maybe_mask,
-+				system_call_mask, 5);
++		text_poke_early(system_call_fast_compare,
++				system_call_mask_compare, 10);
++		text_poke_early(system_call_trace_compare,
++				system_call_mask_compare, 10);
 +#ifdef CONFIG_X86_X32_DISABLED
 +		pr_info("Enabled x32 syscalls\n");
 +#endif



More information about the Kernel-svn-changes mailing list