[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Bug#708070: enable x32 support for the amd64 kernels



Control: tag -1 patch

On Thu, 2014-07-24 at 21:47 +0100, Robert de Bath wrote:
> On Thu, 24 Jul 2014, Ian Campbell wrote:
> 
> > On Thu, 2014-07-24 at 20:22 +0100, Robert de Bath wrote:
> >> On Thu, 24 Jul 2014, Ian Campbell wrote:
> >>
> > But that's rather different to now enabling x32 in the arch=amd64 kernel
> > which is what #708070 is about. Likewise creating a new
> > flavour=x86,arch=amd64 kernel.
> >
> > What the people responsible for the x32 arch on debian-ports do wrt an
> > arch=x32 flavour is up to them, but that's the situation analogous to
> > what you are referring to.
> >
> > Ian.
> 
> I was referring to the package that's now called
> linux-image-3.14-1-amd64:i386 not linux-image-3.14-1-amd64:amd64
> 
> The equivalents would be approximatly linux-image-3.14-1-x32:amd64 and
> linux-image-3.14-1-x32:i386 not any packages in the new port.
[...]

No, there should be no extra kernel flavours for i386 or amd64.

I had an idea how to unblock this, and finally got round to trying it,
and it seems to work.  That is, we build in x32 support but require a
run-time parameter to enable.  So, please try the attached patch
(against the sid branch), adding "syscall.x32=y" to the kernel command
line.

The general instructions for building a patched package are:
<http://kernel-handbook.alioth.debian.org/ch-common-tasks.html#s-common-official>. 

You'll need to follow subsection 4.2.3 and apply the patch like so:
    patch -p1 < ../x86-syscall-make-x32-syscall-support-conditional.patch
    quilt push

You won't need to change the ABI name.

Ben.

-- 
Ben Hutchings
Absolutum obsoletum. (If it works, it's out of date.) - Stafford Beer
Index: linux/debian/changelog
===================================================================
--- linux/debian/changelog	(revision 21631)
+++ linux/debian/changelog	(working copy)
@@ -1,3 +1,11 @@
+linux (3.14.13-2+x32) UNRELEASED; urgency=medium
+
+  [ Ben Hutchings ]
+  * [amd64] Enable X86_X32 (Closes: #708070)
+  * [amd64] syscall: Make x32 syscall support conditional on a kernel parameter
+
+ -- Ben Hutchings <ben@decadent.org.uk>  Fri, 25 Jul 2014 01:48:06 +0100
+
 linux (3.14.13-2) unstable; urgency=medium
 
   [ Aurelien Jarno ]
Index: linux/debian/config/kernelarch-x86/config-arch-64
===================================================================
--- linux/debian/config/kernelarch-x86/config-arch-64	(revision 21631)
+++ linux/debian/config/kernelarch-x86/config-arch-64	(working copy)
@@ -15,7 +15,7 @@
 CONFIG_NUMA_EMU=y
 CONFIG_PCI_MMCONFIG=y
 CONFIG_ISA_DMA_API=y
-# CONFIG_X86_X32 is not set
+CONFIG_X86_X32=y
 
 ##
 ## file: arch/x86/Kconfig.cpu
Index: linux/debian/patches/features/x86/x86-syscall-make-x32-syscall-support-conditional.patch
===================================================================
--- linux/debian/patches/features/x86/x86-syscall-make-x32-syscall-support-conditional.patch	(revision 0)
+++ linux/debian/patches/features/x86/x86-syscall-make-x32-syscall-support-conditional.patch	(working copy)
@@ -0,0 +1,140 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Fri, 25 Jul 2014 01:16:15 +0100
+Subject: x86/syscall: Make x32 syscall support conditional on a kernel parameter
+Bug-Debian: https://bugs.debian.org/708070
+
+Enabling x32 in the standard amd64 kernel would increase its attack
+surface while provide no benefit to the vast majority of its users.
+No-one seems interested in regularly checking for vulnerabilities
+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.
+
+So replace the mask (andl) instruction with a nop and add a kernel
+parameter "syscall.x32" which allows it to be turned back on again.
+
+Change the comparison instruction to cmpq because the upper 32 bits
+may or may not be cleared by the previous instruction.
+
+--- 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
+-	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:
+ #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
+-	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:
+ #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:
+ 	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:
++	andl $__SYSCALL_MASK,%eax
++system_call_mask_end:
++#endif
++
+ 	.macro FORK_LIKE func
+ ENTRY(stub_\func)
+ 	CFI_STARTPROC
+--- a/arch/x86/kernel/syscall_64.c
++++ b/arch/x86/kernel/syscall_64.c
+@@ -3,8 +3,13 @@
+ #include <linux/linkage.h>
+ #include <linux/sys.h>
+ #include <linux/cache.h>
++#include <linux/moduleparam.h>
++#undef MODULE_PARAM_PREFIX
++#define MODULE_PARAM_PREFIX "syscall."
++#include <linux/bug.h>
+ #include <asm/asm-offsets.h>
+ #include <asm/syscall.h>
++#include <asm/alternative.h>
+ 
+ #define __SYSCALL_COMMON(nr, sym, compat) __SYSCALL_64(nr, sym, compat)
+ 
+@@ -30,3 +35,42 @@ asmlinkage const sys_call_ptr_t sys_call
+ 	[0 ... __NR_syscall_max] = &sys_ni_syscall,
+ #include <asm/syscalls_64.h>
+ };
++
++#ifdef CONFIG_X86_X32_ABI
++
++/* Maybe enable x32 syscalls */
++
++static bool x32_enabled = false;
++
++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[];
++
++static int __init
++set_x32_enabled(const char *val, const struct kernel_param *kp)
++{
++	int ret = param_set_bool(val, kp);
++
++	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);
++
++	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);
++		pr_info("Enabled x32 syscalls\n");
++	}
++
++	return ret;
++}
++
++static const struct kernel_param_ops x32_enabled_ops = {
++	.get = param_get_bool,
++	.set = set_x32_enabled
++};
++
++late_param_cb(x32, &x32_enabled_ops, &x32_enabled, 0444);
++
++#endif
Index: linux/debian/patches/series
===================================================================
--- linux/debian/patches/series	(revision 21631)
+++ linux/debian/patches/series	(working copy)
@@ -110,3 +110,4 @@
 features/mips/MIPS-Malta-hang-on-halt.patch
 features/mips/MIPS-Malta-support-powering-down.patch
 features/mips/MIPS-Loongson-3-Add-Loongson-LS3A-RS780E-1-way-machi.patch
+features/x86/x86-syscall-make-x32-syscall-support-conditional.patch

Attachment: signature.asc
Description: This is a digitally signed message part


Reply to: