linux/arch
Andy Lutomirski bf904d2762 x86/pti/64: Remove the SYSCALL64 entry trampoline
The SYSCALL64 trampoline has a couple of nice properties:

 - The usual sequence of SWAPGS followed by two GS-relative accesses to
   set up RSP is somewhat slow because the GS-relative accesses need
   to wait for SWAPGS to finish.  The trampoline approach allows
   RIP-relative accesses to set up RSP, which avoids the stall.

 - The trampoline avoids any percpu access before CR3 is set up,
   which means that no percpu memory needs to be mapped in the user
   page tables.  This prevents using Meltdown to read any percpu memory
   outside the cpu_entry_area and prevents using timing leaks
   to directly locate the percpu areas.

The downsides of using a trampoline may outweigh the upsides, however.
It adds an extra non-contiguous I$ cache line to system calls, and it
forces an indirect jump to transfer control back to the normal kernel
text after CR3 is set up.  The latter is because x86 lacks a 64-bit
direct jump instruction that could jump from the trampoline to the entry
text.  With retpolines enabled, the indirect jump is extremely slow.

Change the code to map the percpu TSS into the user page tables to allow
the non-trampoline SYSCALL64 path to work under PTI.  This does not add a
new direct information leak, since the TSS is readable by Meltdown from the
cpu_entry_area alias regardless.  It does allow a timing attack to locate
the percpu area, but KASLR is more or less a lost cause against local
attack on CPUs vulnerable to Meltdown regardless.  As far as I'm concerned,
on current hardware, KASLR is only useful to mitigate remote attacks that
try to attack the kernel without first gaining RCE against a vulnerable
user process.

On Skylake, with CONFIG_RETPOLINE=y and KPTI on, this reduces syscall
overhead from ~237ns to ~228ns.

There is a possible alternative approach: Move the trampoline within 2G of
the entry text and make a separate copy for each CPU.  This would allow a
direct jump to rejoin the normal entry path. There are pro's and con's for
this approach:

 + It avoids a pipeline stall

 - It executes from an extra page and read from another extra page during
   the syscall. The latter is because it needs to use a relative
   addressing mode to find sp1 -- it's the same *cacheline*, but accessed
   using an alias, so it's an extra TLB entry.

 - Slightly more memory. This would be one page per CPU for a simple
   implementation and 64-ish bytes per CPU or one page per node for a more
   complex implementation.

 - More code complexity.

The current approach is chosen for simplicity and because the alternative
does not provide a significant benefit, which makes it worth.

[ tglx: Added the alternative discussion to the changelog ]

Signed-off-by: Andy Lutomirski <luto@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Borislav Petkov <bp@suse.de>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lkml.kernel.org/r/8c7c6e483612c3e4e10ca89495dc160b1aa66878.1536015544.git.luto@kernel.org
2018-09-12 21:33:53 +02:00
..
alpha Merge branch 'userns-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace 2018-08-24 09:25:39 -07:00
arc kbuild: rename LDFLAGS to KBUILD_LDFLAGS 2018-08-24 08:22:08 +09:00
arm Fixes for omap variants against v4.19-rc1 2018-09-01 18:22:19 -07:00
arm64 ARM: SoC fixes 2018-09-02 10:44:28 -07:00
c6x kbuild: rename LDFLAGS to KBUILD_LDFLAGS 2018-08-24 08:22:08 +09:00
h8300 Kbuild updates for v4.19 (2nd) 2018-08-25 13:40:38 -07:00
hexagon kbuild: rename LDFLAGS to KBUILD_LDFLAGS 2018-08-24 08:22:08 +09:00
ia64 ia64: Fix allnoconfig section mismatch for ioc_init/ioc_iommu_info 2018-08-22 14:12:47 -07:00
m68k m68k/mac: Use correct PMU response format 2018-08-31 09:33:45 +02:00
microblaze kbuild: rename LDFLAGS to KBUILD_LDFLAGS 2018-08-24 08:22:08 +09:00
mips Kbuild updates for v4.19 (2nd) 2018-08-25 13:40:38 -07:00
nds32 nds32: linker script: GCOV kernel may refers data in __exit 2018-09-05 10:16:26 +08:00
nios2 nios2: kconfig: remove duplicate DEBUG_STACK_USAGE symbol defintions 2018-08-27 09:47:20 +08:00
openrisc OpenRISC updates for 4.19 2018-08-23 14:09:37 -07:00
parisc Merge branch 'parisc-4.19-2' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux 2018-08-22 14:06:37 -07:00
powerpc powerpc: disable support for relative ksymtab references 2018-08-29 16:12:07 -07:00
riscv RISC-V: Use a less ugly workaround for unused variable warnings 2018-08-28 12:58:36 -07:00
s390 Kbuild updates for v4.19 (2nd) 2018-08-25 13:40:38 -07:00
sh kbuild: rename LDFLAGS to KBUILD_LDFLAGS 2018-08-24 08:22:08 +09:00
sparc sparc: set a default 32-bit dma mask for OF devices 2018-09-02 10:02:04 +02:00
um kbuild: rename LDFLAGS to KBUILD_LDFLAGS 2018-08-24 08:22:08 +09:00
unicore32 mm: convert return type of handle_mm_fault() caller to vm_fault_t 2018-08-17 16:20:28 -07:00
x86 x86/pti/64: Remove the SYSCALL64 entry trampoline 2018-09-12 21:33:53 +02:00
xtensa Kbuild updates for v4.19 (2nd) 2018-08-25 13:40:38 -07:00
.gitignore
Kconfig Merge branch 'tlb-fixes' 2018-08-23 14:55:01 -07:00