diff --git a/debian/changelog b/debian/changelog index d3ddd9c9b..ec364e4cb 100644 --- a/debian/changelog +++ b/debian/changelog @@ -4,6 +4,12 @@ linux (3.14.13-3) UNRELEASED; urgency=medium * Update German debconf template translations (Holger Wansing) (Closes: #756049). + [ Ben Hutchings ] + * [amd64] Reject x32 executables if x32 ABI not supported + * [amd64] Make x32 syscall support conditional on a kernel parameter + * [amd64] Enable X86_X32 (Closes: #708070) and X86_X32_DISABLED. + Use the kernel parameter "syscall.x32=y" to enable support for x32. + -- Aurelien Jarno Fri, 25 Jul 2014 23:02:24 +0200 linux (3.14.13-2) unstable; urgency=medium diff --git a/debian/config/kernelarch-x86/config-arch-64 b/debian/config/kernelarch-x86/config-arch-64 index 06e458115..d2f2f99a3 100644 --- a/debian/config/kernelarch-x86/config-arch-64 +++ b/debian/config/kernelarch-x86/config-arch-64 @@ -15,7 +15,8 @@ CONFIG_X86_64_ACPI_NUMA=y CONFIG_NUMA_EMU=y CONFIG_PCI_MMCONFIG=y CONFIG_ISA_DMA_API=y -# CONFIG_X86_X32 is not set +CONFIG_X86_X32=y +CONFIG_X86_X32_DISABLED=y ## ## file: arch/x86/Kconfig.cpu diff --git a/debian/patches/bugfix/x86/x86-reject-x32-executables-if-x32-abi-not-supported.patch b/debian/patches/bugfix/x86/x86-reject-x32-executables-if-x32-abi-not-supported.patch new file mode 100644 index 000000000..a9231aa9c --- /dev/null +++ b/debian/patches/bugfix/x86/x86-reject-x32-executables-if-x32-abi-not-supported.patch @@ -0,0 +1,31 @@ +From: Ben Hutchings +Date: Sat, 26 Jul 2014 15:03:11 +0100 +Subject: x86: Reject x32 executables if x32 ABI not supported +Forwarded: http://mid.gmane.org/1406431195.29010.154.camel@deadeye.wl.decadent.org.uk + +It is currently possible to execve() an x32 executable on an x86_64 +kernel that has only ia32 compat enabled. However all its syscalls +will fail, even _exit(). This usually causes it to segfault. + +Change the ELF compat architecture check so that x32 executables are +rejected if we don't support the x32 ABI. + +Signed-off-by: Ben Hutchings +--- + arch/x86/include/asm/elf.h | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/arch/x86/include/asm/elf.h ++++ b/arch/x86/include/asm/elf.h +@@ -155,8 +155,9 @@ do { \ + #define elf_check_arch(x) \ + ((x)->e_machine == EM_X86_64) + +-#define compat_elf_check_arch(x) \ +- (elf_check_arch_ia32(x) || (x)->e_machine == EM_X86_64) ++#define compat_elf_check_arch(x) \ ++ (elf_check_arch_ia32(x) || \ ++ (IS_ENABLED(CONFIG_X86_X32_ABI) && (x)->e_machine == EM_X86_64)) + + #if __USER32_DS != __USER_DS + # error "The following code assumes __USER32_DS == __USER_DS" diff --git a/debian/patches/features/x86/x86-make-x32-syscall-support-conditional.patch b/debian/patches/features/x86/x86-make-x32-syscall-support-conditional.patch new file mode 100644 index 000000000..bdf8aea14 --- /dev/null +++ b/debian/patches/features/x86/x86-make-x32-syscall-support-conditional.patch @@ -0,0 +1,203 @@ +From: Ben Hutchings +Date: Fri, 25 Jul 2014 01:16:15 +0100 +Subject: x86: 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 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. + +Signed-off-by: Ben Hutchings +--- + Documentation/kernel-parameters.txt | 4 ++++ + arch/x86/Kconfig | 8 +++++++ + arch/x86/include/asm/elf.h | 8 ++++++- + arch/x86/kernel/entry_64.S | 36 ++++++++++++++++++++++--------- + arch/x86/kernel/syscall_64.c | 43 +++++++++++++++++++++++++++++++++++++ + 5 files changed, 88 insertions(+), 11 deletions(-) + +--- a/Documentation/kernel-parameters.txt ++++ b/Documentation/kernel-parameters.txt +@@ -3132,6 +3132,10 @@ bytes respectively. Such letter suffixes + + switches= [HW,M68k] + ++ syscall.x32= [KNL,x86_64] Enable/disable use of x32 syscalls on ++ an x86_64 kernel where CONFIG_X86_X32 is enabled. ++ Default depends on CONFIG_X86_X32_DISABLED. ++ + sysfs.deprecated=0|1 [KNL] + Enable/disable old style sysfs layout for old udev + on older distributions. When this option is enabled +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -2383,6 +2383,14 @@ config X86_X32 + elf32_x86_64 support enabled to compile a kernel with this + option set. + ++config X86_X32_DISABLED ++ bool "x32 ABI disabled by default" ++ depends on X86_X32 ++ default n ++ help ++ Disable the x32 ABI unless explicitly enabled using the ++ kernel paramter "syscall.x32=y". ++ + config COMPAT + def_bool y + depends on IA32_EMULATION || X86_X32 +--- a/arch/x86/include/asm/elf.h ++++ b/arch/x86/include/asm/elf.h +@@ -149,6 +149,12 @@ do { \ + + #else /* CONFIG_X86_32 */ + ++#ifdef CONFIG_X86_X32_ABI ++extern bool x32_enabled; ++#else ++#define x32_enabled 0 ++#endif ++ + /* + * This is used to ensure we don't load something for the wrong architecture. + */ +@@ -157,7 +163,7 @@ do { \ + + #define compat_elf_check_arch(x) \ + (elf_check_arch_ia32(x) || \ +- (IS_ENABLED(CONFIG_X86_X32_ABI) && (x)->e_machine == EM_X86_64)) ++ (x32_enabled && (x)->e_machine == EM_X86_64)) + + #if __USER32_DS != __USER_DS + # 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 +- 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,14 @@ + #include + #include + #include ++#include ++#undef MODULE_PARAM_PREFIX ++#define MODULE_PARAM_PREFIX "syscall." ++#include ++#include + #include + #include ++#include + + #define __SYSCALL_COMMON(nr, sym, compat) __SYSCALL_64(nr, sym, compat) + +@@ -30,3 +36,40 @@ asmlinkage const sys_call_ptr_t sys_call + [0 ... __NR_syscall_max] = &sys_ni_syscall, + #include + }; ++ ++#ifdef CONFIG_X86_X32_ABI ++ ++/* Maybe enable x32 syscalls */ ++ ++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[]; ++ ++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); ++ ++ 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); ++#ifdef CONFIG_X86_X32_DISABLED ++ pr_info("Enabled x32 syscalls\n"); ++#endif ++ } ++#ifndef CONFIG_X86_X32_DISABLED ++ else ++ pr_info("Disabled x32 syscalls\n"); ++#endif ++ ++ return 0; ++} ++late_initcall(x32_enable); ++ ++#endif diff --git a/debian/patches/series b/debian/patches/series index e54e1a6d4..8b1768c71 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -110,3 +110,5 @@ features/mips/MIPS-Malta-Let-PIIX4-respond-to-PCI-special-cycles.patch 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 +bugfix/x86/x86-reject-x32-executables-if-x32-abi-not-supported.patch +features/x86/x86-make-x32-syscall-support-conditional.patch