All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/7] x86: Pile o' FS/GS changes
@ 2016-04-08  0:31 Andy Lutomirski
  2016-04-08  0:31 ` [PATCH v3 1/7] selftests/x86: Test the FSBASE/GSBASE API and context switching Andy Lutomirski
                   ` (6 more replies)
  0 siblings, 7 replies; 16+ messages in thread
From: Andy Lutomirski @ 2016-04-08  0:31 UTC (permalink / raw)
  To: Borislav Petkov, security, x86, linux-kernel
  Cc: Linus Torvalds, Rudolf Marek, Andy Lutomirski

Hi all-

This whole mess is intended for x86/urgent.  It fixes several bugs.

It's probably a tiny performance regression on some workloads on
Intel CPUs.  It's probably varies between a less tiny regression and
a small speedup on newer AMD CPUs.  It's a bigger regression on AMD
K8.

The AMD code could be further sped up by adding a new 'clear_gs'
pvop with a better native implementation.  I don't particularly want
to deal with a backported new pvop, so I didn't do that.  Maybe I'll
do it later on for new kernels, though.

(For people who care about such things, there are probably three
bugs in here depending how you count.  Somewhere between one and two
of them were independently discovered by Rudolf Marek.)

Andy Lutomirski (5):
  selftests/x86: Test the FSBASE/GSBASE API and context switching
  x86/arch_prctl: Fix ARCH_GET_FS and ARCH_GET_GS
  x86/cpu: Probe the behavior of nulling out a segment at boot time
  x86/switch_to: Rewrite the FS and GS context switch code
  x86/cpu: Move X86_BUG_ESPFIX initialization to generic_identify

Borislav Petkov (2):
  x86/cpu: Add Erratum 88 detection on AMD
  x86/entry: Make gs_change a local label

 arch/x86/entry/entry_64.S              |  12 +-
 arch/x86/include/asm/cpufeatures.h     |   3 +
 arch/x86/kernel/cpu/amd.c              |   1 +
 arch/x86/kernel/cpu/common.c           |  71 ++++--
 arch/x86/kernel/process_64.c           | 167 ++++++++------
 tools/testing/selftests/x86/Makefile   |   1 +
 tools/testing/selftests/x86/fsgsbase.c | 398 +++++++++++++++++++++++++++++++++
 7 files changed, 560 insertions(+), 93 deletions(-)
 create mode 100644 tools/testing/selftests/x86/fsgsbase.c

-- 
2.5.5

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v3 1/7] selftests/x86: Test the FSBASE/GSBASE API and context switching
  2016-04-08  0:31 [PATCH v3 0/7] x86: Pile o' FS/GS changes Andy Lutomirski
@ 2016-04-08  0:31 ` Andy Lutomirski
  2016-04-13 11:28   ` [tip:x86/asm] " tip-bot for Andy Lutomirski
  2016-04-08  0:31 ` [PATCH v3 5/7] x86/cpu: Move X86_BUG_ESPFIX initialization to generic_identify Andy Lutomirski
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 16+ messages in thread
From: Andy Lutomirski @ 2016-04-08  0:31 UTC (permalink / raw)
  To: Borislav Petkov, security, x86, linux-kernel
  Cc: Linus Torvalds, Rudolf Marek, Andy Lutomirski

This catches two distinct bugs in the current code.  I'll fix them.

Signed-off-by: Andy Lutomirski <luto@kernel.org>
---
 tools/testing/selftests/x86/Makefile   |   1 +
 tools/testing/selftests/x86/fsgsbase.c | 398 +++++++++++++++++++++++++++++++++
 2 files changed, 399 insertions(+)
 create mode 100644 tools/testing/selftests/x86/fsgsbase.c

diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile
index b47ebd170690..c73425de3cfe 100644
--- a/tools/testing/selftests/x86/Makefile
+++ b/tools/testing/selftests/x86/Makefile
@@ -9,6 +9,7 @@ TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_sysc
 TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault test_syscall_vdso unwind_vdso \
 			test_FCMOV test_FCOMI test_FISTTP \
 			vdso_restorer
+TARGETS_C_64BIT_ONLY := fsgsbase
 
 TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY)
 TARGETS_C_64BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_64BIT_ONLY)
diff --git a/tools/testing/selftests/x86/fsgsbase.c b/tools/testing/selftests/x86/fsgsbase.c
new file mode 100644
index 000000000000..b7733055a359
--- /dev/null
+++ b/tools/testing/selftests/x86/fsgsbase.c
@@ -0,0 +1,398 @@
+/*
+ * fsgsbase.c, an fsgsbase test
+ * Copyright (c) 2014-2016 Andy Lutomirski
+ * GPL v2
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <err.h>
+#include <sys/user.h>
+#include <asm/prctl.h>
+#include <sys/prctl.h>
+#include <signal.h>
+#include <limits.h>
+#include <sys/ucontext.h>
+#include <sched.h>
+#include <linux/futex.h>
+#include <pthread.h>
+#include <asm/ldt.h>
+#include <sys/mman.h>
+
+#ifndef __x86_64__
+# error This test is 64-bit only
+#endif
+
+static volatile sig_atomic_t want_segv;
+static volatile unsigned long segv_addr;
+
+static int nerrs;
+
+static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
+		       int flags)
+{
+	struct sigaction sa;
+	memset(&sa, 0, sizeof(sa));
+	sa.sa_sigaction = handler;
+	sa.sa_flags = SA_SIGINFO | flags;
+	sigemptyset(&sa.sa_mask);
+	if (sigaction(sig, &sa, 0))
+		err(1, "sigaction");
+}
+
+static void clearhandler(int sig)
+{
+	struct sigaction sa;
+	memset(&sa, 0, sizeof(sa));
+	sa.sa_handler = SIG_DFL;
+	sigemptyset(&sa.sa_mask);
+	if (sigaction(sig, &sa, 0))
+		err(1, "sigaction");
+}
+
+static void sigsegv(int sig, siginfo_t *si, void *ctx_void)
+{
+	ucontext_t *ctx = (ucontext_t*)ctx_void;
+
+	if (!want_segv) {
+		clearhandler(SIGSEGV);
+		return;  /* Crash cleanly. */
+	}
+
+	want_segv = false;
+	segv_addr = (unsigned long)si->si_addr;
+
+	ctx->uc_mcontext.gregs[REG_RIP] += 4;	/* Skip the faulting mov */
+
+}
+
+enum which_base { FS, GS };
+
+static unsigned long read_base(enum which_base which)
+{
+	unsigned long offset;
+	/*
+	 * Unless we have FSGSBASE, there's no direct way to do this from
+	 * user mode.  We can get at it indirectly using signals, though.
+	 */
+
+	want_segv = true;
+
+	offset = 0;
+	if (which == FS) {
+		/* Use a constant-length instruction here. */
+		asm volatile ("mov %%fs:(%%rcx), %%rax" : : "c" (offset) : "rax");
+	} else {
+		asm volatile ("mov %%gs:(%%rcx), %%rax" : : "c" (offset) : "rax");
+	}
+	if (!want_segv)
+		return segv_addr + offset;
+
+	/*
+	 * If that didn't segfault, try the other end of the address space.
+	 * Unless we get really unlucky and run into the vsyscall page, this
+	 * is guaranteed to segfault.
+	 */
+
+	offset = (ULONG_MAX >> 1) + 1;
+	if (which == FS) {
+		asm volatile ("mov %%fs:(%%rcx), %%rax"
+			      : : "c" (offset) : "rax");
+	} else {
+		asm volatile ("mov %%gs:(%%rcx), %%rax"
+			      : : "c" (offset) : "rax");
+	}
+	if (!want_segv)
+		return segv_addr + offset;
+
+	abort();
+}
+
+static void check_gs_value(unsigned long value)
+{
+	unsigned long base;
+	unsigned short sel;
+
+	printf("[RUN]\tARCH_SET_GS to 0x%lx\n", value);
+	if (syscall(SYS_arch_prctl, ARCH_SET_GS, value) != 0)
+		err(1, "ARCH_SET_GS");
+
+	asm volatile ("mov %%gs, %0" : "=rm" (sel));
+	base = read_base(GS);
+	if (base == value) {
+		printf("[OK]\tGSBASE was set as expected (selector 0x%hx)\n",
+		       sel);
+	} else {
+		nerrs++;
+		printf("[FAIL]\tGSBASE was not as expected: got 0x%lx (selector 0x%hx)\n",
+		       base, sel);
+	}
+
+	if (syscall(SYS_arch_prctl, ARCH_GET_GS, &base) != 0)
+		err(1, "ARCH_GET_GS");
+	if (base == value) {
+		printf("[OK]\tARCH_GET_GS worked as expected (selector 0x%hx)\n",
+		       sel);
+	} else {
+		nerrs++;
+		printf("[FAIL]\tARCH_GET_GS was not as expected: got 0x%lx (selector 0x%hx)\n",
+		       base, sel);
+	}
+}
+
+static void mov_0_gs(unsigned long initial_base, bool schedule)
+{
+	unsigned long base, arch_base;
+
+	printf("[RUN]\tARCH_SET_GS to 0x%lx then mov 0 to %%gs%s\n", initial_base, schedule ? " and schedule " : "");
+	if (syscall(SYS_arch_prctl, ARCH_SET_GS, initial_base) != 0)
+		err(1, "ARCH_SET_GS");
+
+	if (schedule)
+		usleep(10);
+
+	asm volatile ("mov %0, %%gs" : : "rm" (0));
+	base = read_base(GS);
+	if (syscall(SYS_arch_prctl, ARCH_GET_GS, &arch_base) != 0)
+		err(1, "ARCH_GET_GS");
+	if (base == arch_base) {
+		printf("[OK]\tGSBASE is 0x%lx\n", base);
+	} else {
+		nerrs++;
+		printf("[FAIL]\tGSBASE changed to 0x%lx but kernel reports 0x%lx\n", base, arch_base);
+	}
+}
+
+static volatile unsigned long remote_base;
+static volatile bool remote_hard_zero;
+static volatile unsigned int ftx;
+
+/*
+ * ARCH_SET_FS/GS(0) may or may not program a selector of zero.  HARD_ZERO
+ * means to force the selector to zero to improve test coverage.
+ */
+#define HARD_ZERO 0xa1fa5f343cb85fa4
+
+static void do_remote_base()
+{
+	unsigned long to_set = remote_base;
+	bool hard_zero = false;
+	if (to_set == HARD_ZERO) {
+		to_set = 0;
+		hard_zero = true;
+	}
+
+	if (syscall(SYS_arch_prctl, ARCH_SET_GS, to_set) != 0)
+		err(1, "ARCH_SET_GS");
+
+	if (hard_zero)
+		asm volatile ("mov %0, %%gs" : : "rm" ((unsigned short)0));
+
+	unsigned short sel;
+	asm volatile ("mov %%gs, %0" : "=rm" (sel));
+	printf("\tother thread: ARCH_SET_GS(0x%lx)%s -- sel is 0x%hx\n",
+	       to_set, hard_zero ? " and clear gs" : "", sel);
+}
+
+void do_unexpected_base(void)
+{
+	/*
+	 * The goal here is to try to arrange for GS == 0, GSBASE !=
+	 * 0, and for the the kernel the think that GSBASE == 0.
+	 *
+	 * To make the test as reliable as possible, this uses
+	 * explicit descriptorss.  (This is not the only way.  This
+	 * could use ARCH_SET_GS with a low, nonzero base, but the
+	 * relevant side effect of ARCH_SET_GS could change.)
+	 */
+
+	/* Step 1: tell the kernel that we have GSBASE == 0. */
+	if (syscall(SYS_arch_prctl, ARCH_SET_GS, 0) != 0)
+		err(1, "ARCH_SET_GS");
+
+	/* Step 2: change GSBASE without telling the kernel. */
+	struct user_desc desc = {
+		.entry_number    = 0,
+		.base_addr       = 0xBAADF00D,
+		.limit           = 0xfffff,
+		.seg_32bit       = 1,
+		.contents        = 0, /* Data, grow-up */
+		.read_exec_only  = 0,
+		.limit_in_pages  = 1,
+		.seg_not_present = 0,
+		.useable         = 0
+	};
+	if (syscall(SYS_modify_ldt, 1, &desc, sizeof(desc)) == 0) {
+		printf("\tother thread: using LDT slot 0\n");
+		asm volatile ("mov %0, %%gs" : : "rm" ((unsigned short)0x7));
+	} else {
+		/* No modify_ldt for us (configured out, perhaps) */
+
+		struct user_desc *low_desc = mmap(
+			NULL, sizeof(desc),
+			PROT_READ | PROT_WRITE,
+			MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0);
+		memcpy(low_desc, &desc, sizeof(desc));
+
+		low_desc->entry_number = -1;
+
+		/* 32-bit set_thread_area */
+		long ret;
+		asm volatile ("int $0x80"
+			      : "=a" (ret) : "a" (243), "b" (low_desc)
+			      : "flags");
+		memcpy(&desc, low_desc, sizeof(desc));
+		munmap(low_desc, sizeof(desc));
+
+		if (ret != 0) {
+			printf("[NOTE]\tcould not create a segment -- test won't do anything\n");
+			return;
+		}
+		printf("\tother thread: using GDT slot %d\n", desc.entry_number);
+		asm volatile ("mov %0, %%gs" : : "rm" ((unsigned short)((desc.entry_number << 3) | 0x3)));
+	}
+
+	/*
+	 * Step 3: set the selector back to zero.  On AMD chips, this will
+	 * preserve GSBASE.
+	 */
+
+	asm volatile ("mov %0, %%gs" : : "rm" ((unsigned short)0));
+}
+
+static void *threadproc(void *ctx)
+{
+	while (1) {
+		while (ftx == 0)
+			syscall(SYS_futex, &ftx, FUTEX_WAIT, 0, NULL, NULL, 0);
+		if (ftx == 3)
+			return NULL;
+
+		if (ftx == 1)
+			do_remote_base();
+		else if (ftx == 2)
+			do_unexpected_base();
+		else
+			errx(1, "helper thread got bad command");
+
+		ftx = 0;
+		syscall(SYS_futex, &ftx, FUTEX_WAKE, 0, NULL, NULL, 0);		
+	}
+}
+
+static void set_gs_and_switch_to(unsigned long local, unsigned long remote)
+{
+	unsigned long base;
+
+	bool hard_zero = false;
+	if (local == HARD_ZERO) {
+		hard_zero = true;
+		local = 0;
+	}
+
+	printf("[RUN]\tARCH_SET_GS(0x%lx)%s, then schedule to 0x%lx\n",
+	       local, hard_zero ? " and clear gs" : "", remote);
+	if (syscall(SYS_arch_prctl, ARCH_SET_GS, local) != 0)
+		err(1, "ARCH_SET_GS");
+	if (hard_zero)
+		asm volatile ("mov %0, %%gs" : : "rm" ((unsigned short)0));
+
+	if (read_base(GS) != local) {
+		nerrs++;
+		printf("[FAIL]\tGSBASE wasn't set as expected\n");
+	}
+
+	remote_base = remote;
+	ftx = 1;
+	syscall(SYS_futex, &ftx, FUTEX_WAKE, 0, NULL, NULL, 0);
+	while (ftx != 0)
+		syscall(SYS_futex, &ftx, FUTEX_WAIT, 1, NULL, NULL, 0);
+
+	base = read_base(GS);
+	if (base == local) {
+		printf("[OK]\tGSBASE remained 0x%lx\n", local);
+	} else {
+		nerrs++;
+		printf("[FAIL]\tGSBASE changed to 0x%lx\n", base);
+	}
+}
+
+static void test_unexpected_base(void)
+{
+	unsigned long base;
+
+	printf("[RUN]\tARCH_SET_GS(0), clear gs, then manipulate GSBASE in a different thread\n");
+	if (syscall(SYS_arch_prctl, ARCH_SET_GS, 0) != 0)
+		err(1, "ARCH_SET_GS");
+	asm volatile ("mov %0, %%gs" : : "rm" ((unsigned short)0));
+
+	ftx = 2;
+	syscall(SYS_futex, &ftx, FUTEX_WAKE, 0, NULL, NULL, 0);
+	while (ftx != 0)
+		syscall(SYS_futex, &ftx, FUTEX_WAIT, 1, NULL, NULL, 0);
+
+	base = read_base(GS);
+	if (base == 0) {
+		printf("[OK]\tGSBASE remained 0\n");
+	} else {
+		nerrs++;
+		printf("[FAIL]\tGSBASE changed to 0x%lx\n", base);
+	}
+}
+
+int main()
+{
+	pthread_t thread;
+
+	sethandler(SIGSEGV, sigsegv, 0);
+
+	check_gs_value(0);
+	check_gs_value(1);
+	check_gs_value(0x200000000);
+	check_gs_value(0);
+	check_gs_value(0x200000000);
+	check_gs_value(1);
+
+	for (int sched = 0; sched < 2; sched++) {
+		mov_0_gs(0, !!sched);
+		mov_0_gs(1, !!sched);
+		mov_0_gs(0x200000000, !!sched);
+	}
+
+	/* Set up for multithreading. */
+
+	cpu_set_t cpuset;
+	CPU_ZERO(&cpuset);
+	CPU_SET(0, &cpuset);
+	if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0)
+		err(1, "sched_setaffinity to CPU 0");	/* should never fail */
+
+	if (pthread_create(&thread, 0, threadproc, 0) != 0)
+		err(1, "pthread_create");
+
+	static unsigned long bases_with_hard_zero[] = {
+		0, HARD_ZERO, 1, 0x200000000,
+	};
+
+	for (int local = 0; local < 4; local++) {
+		for (int remote = 0; remote < 4; remote++) {
+			set_gs_and_switch_to(bases_with_hard_zero[local],
+					     bases_with_hard_zero[remote]);
+		}
+	}
+
+	test_unexpected_base();
+
+	ftx = 3;  /* Kill the thread. */
+	syscall(SYS_futex, &ftx, FUTEX_WAKE, 0, NULL, NULL, 0);
+
+	if (pthread_join(thread, NULL) != 0)
+		err(1, "pthread_join");
+
+	return nerrs == 0 ? 0 : 1;
+}
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v3 5/7] x86/cpu: Move X86_BUG_ESPFIX initialization to generic_identify
  2016-04-08  0:31 [PATCH v3 0/7] x86: Pile o' FS/GS changes Andy Lutomirski
  2016-04-08  0:31 ` [PATCH v3 1/7] selftests/x86: Test the FSBASE/GSBASE API and context switching Andy Lutomirski
@ 2016-04-08  0:31 ` Andy Lutomirski
  2016-04-13 11:30   ` [tip:x86/asm] x86/cpu: Move X86_BUG_ESPFIX initialization to generic_identify() tip-bot for Andy Lutomirski
  2016-04-08  0:31 ` [PATCH v3 7/7] x86/entry: Make gs_change a local label Andy Lutomirski
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 16+ messages in thread
From: Andy Lutomirski @ 2016-04-08  0:31 UTC (permalink / raw)
  To: Borislav Petkov, security, x86, linux-kernel
  Cc: Linus Torvalds, Rudolf Marek, Andy Lutomirski

It was in detect_nopl, which was either a mistake by me or some kind
of mis-merge.

Fixes: ff236456f072 ("x86/cpu: Move X86_BUG_ESPFIX initialization to generic_identify")
Signed-off-by: Andy Lutomirski <luto@kernel.org>
---
 arch/x86/kernel/cpu/common.c | 50 ++++++++++++++++++++++----------------------
 1 file changed, 25 insertions(+), 25 deletions(-)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index ceef584ae8b0..9ede8aa41f18 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -862,31 +862,6 @@ static void detect_nopl(struct cpuinfo_x86 *c)
 #else
 	set_cpu_cap(c, X86_FEATURE_NOPL);
 #endif
-
-	/*
-	 * ESPFIX is a strange bug.  All real CPUs have it.  Paravirt
-	 * systems that run Linux at CPL > 0 may or may not have the
-	 * issue, but, even if they have the issue, there's absolutely
-	 * nothing we can do about it because we can't use the real IRET
-	 * instruction.
-	 *
-	 * NB: For the time being, only 32-bit kernels support
-	 * X86_BUG_ESPFIX as such.  64-bit kernels directly choose
-	 * whether to apply espfix using paravirt hooks.  If any
-	 * non-paravirt system ever shows up that does *not* have the
-	 * ESPFIX issue, we can change this.
-	 */
-#ifdef CONFIG_X86_32
-#ifdef CONFIG_PARAVIRT
-	do {
-		extern void native_iret(void);
-		if (pv_cpu_ops.iret == native_iret)
-			set_cpu_bug(c, X86_BUG_ESPFIX);
-	} while (0);
-#else
-	set_cpu_bug(c, X86_BUG_ESPFIX);
-#endif
-#endif
 }
 
 static void detect_null_seg_behavior(struct cpuinfo_x86 *c)
@@ -952,6 +927,31 @@ static void generic_identify(struct cpuinfo_x86 *c)
 	detect_nopl(c);
 
 	detect_null_seg_behavior(c);
+
+	/*
+	 * ESPFIX is a strange bug.  All real CPUs have it.  Paravirt
+	 * systems that run Linux at CPL > 0 may or may not have the
+	 * issue, but, even if they have the issue, there's absolutely
+	 * nothing we can do about it because we can't use the real IRET
+	 * instruction.
+	 *
+	 * NB: For the time being, only 32-bit kernels support
+	 * X86_BUG_ESPFIX as such.  64-bit kernels directly choose
+	 * whether to apply espfix using paravirt hooks.  If any
+	 * non-paravirt system ever shows up that does *not* have the
+	 * ESPFIX issue, we can change this.
+	 */
+#ifdef CONFIG_X86_32
+#ifdef CONFIG_PARAVIRT
+	do {
+		extern void native_iret(void);
+		if (pv_cpu_ops.iret == native_iret)
+			set_cpu_bug(c, X86_BUG_ESPFIX);
+	} while (0);
+#else
+	set_cpu_bug(c, X86_BUG_ESPFIX);
+#endif
+#endif
 }
 
 static void x86_init_cache_qos(struct cpuinfo_x86 *c)
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v3 7/7] x86/entry: Make gs_change a local label
  2016-04-08  0:31 [PATCH v3 0/7] x86: Pile o' FS/GS changes Andy Lutomirski
  2016-04-08  0:31 ` [PATCH v3 1/7] selftests/x86: Test the FSBASE/GSBASE API and context switching Andy Lutomirski
  2016-04-08  0:31 ` [PATCH v3 5/7] x86/cpu: Move X86_BUG_ESPFIX initialization to generic_identify Andy Lutomirski
@ 2016-04-08  0:31 ` Andy Lutomirski
  2016-04-13 11:31   ` [tip:x86/asm] x86/entry/64: " tip-bot for Borislav Petkov
  2016-04-08 10:39 ` [PATCH v3 0/7] x86: Pile o' FS/GS changes Borislav Petkov
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 16+ messages in thread
From: Andy Lutomirski @ 2016-04-08  0:31 UTC (permalink / raw)
  To: Borislav Petkov, security, x86, linux-kernel
  Cc: Linus Torvalds, Rudolf Marek, Borislav Petkov, Andy Lutomirski

From: Borislav Petkov <bp@suse.de>

... so that it doesn't appear in objdump output.

Signed-off-by: Borislav Petkov <bp@suse.de>
Signed-off-by: Andy Lutomirski <luto@kernel.org>
---
 arch/x86/entry/entry_64.S | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
index 64d2033d1e49..1693c17dbf81 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -781,7 +781,7 @@ ENTRY(native_load_gs_index)
 	pushfq
 	DISABLE_INTERRUPTS(CLBR_ANY & ~CLBR_RDI)
 	SWAPGS
-gs_change:
+.Lgs_change:
 	movl	%edi, %gs
 2:	ALTERNATIVE "", "mfence", X86_BUG_SWAPGS_FENCE
 	SWAPGS
@@ -789,7 +789,7 @@ gs_change:
 	ret
 END(native_load_gs_index)
 
-	_ASM_EXTABLE(gs_change, bad_gs)
+	_ASM_EXTABLE(.Lgs_change, bad_gs)
 	.section .fixup, "ax"
 	/* running with kernelgs */
 bad_gs:
@@ -1019,13 +1019,13 @@ ENTRY(error_entry)
 	movl	%ecx, %eax			/* zero extend */
 	cmpq	%rax, RIP+8(%rsp)
 	je	.Lbstep_iret
-	cmpq	$gs_change, RIP+8(%rsp)
+	cmpq	$.Lgs_change, RIP+8(%rsp)
 	jne	.Lerror_entry_done
 
 	/*
-	 * hack: gs_change can fail with user gsbase.  If this happens, fix up
+	 * hack: .Lgs_change can fail with user gsbase.  If this happens, fix up
 	 * gsbase and proceed.  We'll fix up the exception and land in
-	 * gs_change's error handler with kernel gsbase.
+	 * .Lgs_change's error handler with kernel gsbase.
 	 */
 	jmp	.Lerror_entry_from_usermode_swapgs
 
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 6/7] x86/cpu: Add Erratum 88 detection on AMD
       [not found] ` <aec6b2df1bfc56101d4e9e2e5d5d570bf41663c6.1460075211.git.luto@kernel.org>
@ 2016-04-08  1:40   ` Andy Lutomirski
  2016-04-08  9:51     ` Borislav Petkov
  2016-04-13 11:30   ` [tip:x86/asm] " tip-bot for Borislav Petkov
  1 sibling, 1 reply; 16+ messages in thread
From: Andy Lutomirski @ 2016-04-08  1:40 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Borislav Petkov, security, X86 ML, linux-kernel, Linus Torvalds,
	Rudolf Marek, Borislav Petkov, stable, Andi Kleen

On Thu, Apr 7, 2016 at 5:31 PM, Andy Lutomirski <luto@kernel.org> wrote:
> From: Borislav Petkov <bp@suse.de>
>
> Erratum 88 affects old AMD K8s, where a SWAPGS fails to cause an input
> dependency on GS. Therefore, we need to MFENCE before it.
>
> But that MFENCE is expensive and unnecessary on the remaining x86 CPUs
> out there so patch it out on the CPUs which don't require it.

This is basically identical to:

https://lkml.kernel.org/g/1458576969-13309-4-git-send-email-andi@firstfloor.org

Whoops!  I thought I'd seen that somewhere but I couldn't spot it.

Ingo, etc: we should probably apply one of those patches with a
-stable tag (to mitigate the otherwise potentially unpleasant
performance regression in here), but I don't really care which one.
Andi's has a name for the bug that seems nicer by one character to me,
but it would have to be (trivally) rebased.

--Andy

>
> Signed-off-by: Borislav Petkov <bp@suse.de>
> Cc: <stable@vger.kernel.org>
> Signed-off-by: Andy Lutomirski <luto@kernel.org
> ---
>  arch/x86/entry/entry_64.S          | 2 +-
>  arch/x86/include/asm/cpufeatures.h | 2 ++
>  arch/x86/kernel/cpu/amd.c          | 1 +
>  3 files changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
> index 858b555e274b..64d2033d1e49 100644
> --- a/arch/x86/entry/entry_64.S
> +++ b/arch/x86/entry/entry_64.S
> @@ -783,7 +783,7 @@ ENTRY(native_load_gs_index)
>         SWAPGS
>  gs_change:
>         movl    %edi, %gs
> -2:     mfence                                  /* workaround */
> +2:     ALTERNATIVE "", "mfence", X86_BUG_SWAPGS_FENCE
>         SWAPGS
>         popfq
>         ret
> diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
> index 2a052302bc43..7bfb6b70c745 100644
> --- a/arch/x86/include/asm/cpufeatures.h
> +++ b/arch/x86/include/asm/cpufeatures.h
> @@ -295,6 +295,8 @@
>  #define X86_BUG_CLFLUSH_MONITOR        X86_BUG(7) /* AAI65, CLFLUSH required before MONITOR */
>  #define X86_BUG_SYSRET_SS_ATTRS        X86_BUG(8) /* SYSRET doesn't fix up SS attrs */
>  #define X86_BUG_NULL_SEG       X86_BUG(9) /* Nulling a selector preserves the base */
> +#define X86_BUG_SWAPGS_FENCE   X86_BUG(10) /* SWAPGS without input dep on GS */
> +
>
>  #ifdef CONFIG_X86_32
>  /*
> diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
> index 6e47e3a916f1..b7cc9efe08b5 100644
> --- a/arch/x86/kernel/cpu/amd.c
> +++ b/arch/x86/kernel/cpu/amd.c
> @@ -632,6 +632,7 @@ static void init_amd_k8(struct cpuinfo_x86 *c)
>          */
>         msr_set_bit(MSR_K7_HWCR, 6);
>  #endif
> +       set_cpu_bug(c, X86_BUG_SWAPGS_FENCE);
>  }
>
>  static void init_amd_gh(struct cpuinfo_x86 *c)
> --
> 2.5.5
>



-- 
Andy Lutomirski
AMA Capital Management, LLC

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 2/7] x86/arch_prctl: Fix ARCH_GET_FS and ARCH_GET_GS
       [not found] ` <c6e7b507c72ca3bdbf6c7a8a3ceaa0334e873bd9.1460075211.git.luto@kernel.org>
@ 2016-04-08  7:13   ` Ingo Molnar
  2016-04-08  9:39     ` Dmitry Safonov
  2016-04-08 16:03     ` Andy Lutomirski
  2016-04-13 11:29   ` [tip:x86/asm] " tip-bot for Andy Lutomirski
  1 sibling, 2 replies; 16+ messages in thread
From: Ingo Molnar @ 2016-04-08  7:13 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Borislav Petkov, security, x86, linux-kernel, Linus Torvalds,
	Rudolf Marek, Denys Vlasenko, Thomas Gleixner, H. Peter Anvin


* Andy Lutomirski <luto@kernel.org> wrote:

> ARCH_GET_FS and ARCH_GET_GS attempted to figure out the fsbase and
> gsbase respectively from saved thread state.  This was wrong: fsbase
> and gsbase live in registers while a thread is running, not in
> memory.

So I'm wondering, the current code looks totally broken,what user-space code can 
possibly use this? I checked glibc and Wine, and neither of them does. Wine uses 
ARCH_SET_GS and glibc uses ARCH_SET_FS, but that's all - neither actually tries to 
use the ARCH_GET_* reading APIs.

So for backporting purposes I'd be much happier about simply returning -EINVAL or 
-ENOSYS, and we could re-introduce this code in v4.7.

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 2/7] x86/arch_prctl: Fix ARCH_GET_FS and ARCH_GET_GS
  2016-04-08  7:13   ` [PATCH v3 2/7] x86/arch_prctl: Fix ARCH_GET_FS and ARCH_GET_GS Ingo Molnar
@ 2016-04-08  9:39     ` Dmitry Safonov
  2016-04-08 16:03     ` Andy Lutomirski
  1 sibling, 0 replies; 16+ messages in thread
From: Dmitry Safonov @ 2016-04-08  9:39 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Andy Lutomirski, Borislav Petkov, security, x86, linux-kernel,
	Linus Torvalds, Rudolf Marek, Denys Vlasenko, Thomas Gleixner,
	H. Peter Anvin, gorcunov

2016-04-08 10:13 GMT+03:00 Ingo Molnar <mingo@kernel.org>:
>
> * Andy Lutomirski <luto@kernel.org> wrote:
>
>> ARCH_GET_FS and ARCH_GET_GS attempted to figure out the fsbase and
>> gsbase respectively from saved thread state.  This was wrong: fsbase
>> and gsbase live in registers while a thread is running, not in
>> memory.
>
> So I'm wondering, the current code looks totally broken,what user-space code can
> possibly use this? I checked glibc and Wine, and neither of them does. Wine uses
> ARCH_SET_GS and glibc uses ARCH_SET_FS, but that's all - neither actually tries to
> use the ARCH_GET_* reading APIs.

Just FYI, CRIU also does not use ARCH_GET_{FS,GS}, only ARCH_SET_{FS,GS}.
It gets them with the help of PTRACE_GETREGSET.

> So for backporting purposes I'd be much happier about simply returning -EINVAL or
> -ENOSYS, and we could re-introduce this code in v4.7.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 6/7] x86/cpu: Add Erratum 88 detection on AMD
  2016-04-08  1:40   ` [PATCH v3 6/7] x86/cpu: Add Erratum 88 detection on AMD Andy Lutomirski
@ 2016-04-08  9:51     ` Borislav Petkov
  0 siblings, 0 replies; 16+ messages in thread
From: Borislav Petkov @ 2016-04-08  9:51 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Andy Lutomirski, security, X86 ML, linux-kernel, Linus Torvalds,
	Rudolf Marek, Borislav Petkov, stable, Andi Kleen

On Thu, Apr 07, 2016 at 06:40:13PM -0700, Andy Lutomirski wrote:
> Ingo, etc: we should probably apply one of those patches with a
> -stable tag (to mitigate the otherwise potentially unpleasant
> performance regression in here), but I don't really care which one.
> Andi's has a name for the bug that seems nicer by one character to me,
> but it would have to be (trivally) rebased.

I don't care which one as long as the commit message says "erratum 88"
somewhere.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 0/7] x86: Pile o' FS/GS changes
  2016-04-08  0:31 [PATCH v3 0/7] x86: Pile o' FS/GS changes Andy Lutomirski
                   ` (2 preceding siblings ...)
  2016-04-08  0:31 ` [PATCH v3 7/7] x86/entry: Make gs_change a local label Andy Lutomirski
@ 2016-04-08 10:39 ` Borislav Petkov
  2016-04-08 10:40 ` Borislav Petkov
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 16+ messages in thread
From: Borislav Petkov @ 2016-04-08 10:39 UTC (permalink / raw)
  To: Andy Lutomirski; +Cc: security, x86, linux-kernel, Linus Torvalds, Rudolf Marek

On Thu, Apr 07, 2016 at 05:31:43PM -0700, Andy Lutomirski wrote:
> Hi all-
> 
> This whole mess is intended for x86/urgent.  It fixes several bugs.
> 
> It's probably a tiny performance regression on some workloads on
> Intel CPUs.  It's probably varies between a less tiny regression and
> a small speedup on newer AMD CPUs.  It's a bigger regression on AMD
> K8.

Shhh, otherwise the 2-3 K8 users left would crawl out of the woodwork
complaining. ;-)

> The AMD code could be further sped up by adding a new 'clear_gs'
> pvop with a better native implementation.  I don't particularly want
> to deal with a backported new pvop, so I didn't do that.  Maybe I'll
> do it later on for new kernels, though.

Yeah, before you do that, we should probably measure that first to see
whether it is worth the trouble and the added pvop gunk at all.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 0/7] x86: Pile o' FS/GS changes
  2016-04-08  0:31 [PATCH v3 0/7] x86: Pile o' FS/GS changes Andy Lutomirski
                   ` (3 preceding siblings ...)
  2016-04-08 10:39 ` [PATCH v3 0/7] x86: Pile o' FS/GS changes Borislav Petkov
@ 2016-04-08 10:40 ` Borislav Petkov
       [not found] ` <c6e7b507c72ca3bdbf6c7a8a3ceaa0334e873bd9.1460075211.git.luto@kernel.org>
       [not found] ` <aec6b2df1bfc56101d4e9e2e5d5d570bf41663c6.1460075211.git.luto@kernel.org>
  6 siblings, 0 replies; 16+ messages in thread
From: Borislav Petkov @ 2016-04-08 10:40 UTC (permalink / raw)
  To: Andy Lutomirski; +Cc: security, x86, linux-kernel, Linus Torvalds, Rudolf Marek

On Thu, Apr 07, 2016 at 05:31:43PM -0700, Andy Lutomirski wrote:
> Hi all-
> 
> This whole mess is intended for x86/urgent.  It fixes several bugs.
> 
> It's probably a tiny performance regression on some workloads on
> Intel CPUs.  It's probably varies between a less tiny regression and
> a small speedup on newer AMD CPUs.  It's a bigger regression on AMD
> K8.
> 
> The AMD code could be further sped up by adding a new 'clear_gs'
> pvop with a better native implementation.  I don't particularly want
> to deal with a backported new pvop, so I didn't do that.  Maybe I'll
> do it later on for new kernels, though.
> 
> (For people who care about such things, there are probably three
> bugs in here depending how you count.  Somewhere between one and two
> of them were independently discovered by Rudolf Marek.)
> 
> Andy Lutomirski (5):
>   selftests/x86: Test the FSBASE/GSBASE API and context switching
>   x86/arch_prctl: Fix ARCH_GET_FS and ARCH_GET_GS
>   x86/cpu: Probe the behavior of nulling out a segment at boot time
>   x86/switch_to: Rewrite the FS and GS context switch code
>   x86/cpu: Move X86_BUG_ESPFIX initialization to generic_identify
> 
> Borislav Petkov (2):
>   x86/cpu: Add Erratum 88 detection on AMD
>   x86/entry: Make gs_change a local label
> 
>  arch/x86/entry/entry_64.S              |  12 +-
>  arch/x86/include/asm/cpufeatures.h     |   3 +
>  arch/x86/kernel/cpu/amd.c              |   1 +
>  arch/x86/kernel/cpu/common.c           |  71 ++++--
>  arch/x86/kernel/process_64.c           | 167 ++++++++------
>  tools/testing/selftests/x86/Makefile   |   1 +
>  tools/testing/selftests/x86/fsgsbase.c | 398 +++++++++++++++++++++++++++++++++
>  7 files changed, 560 insertions(+), 93 deletions(-)
>  create mode 100644 tools/testing/selftests/x86/fsgsbase.c

Forgot to add:

Reviewed-by: Borislav Petkov <bp@suse.de>

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 2/7] x86/arch_prctl: Fix ARCH_GET_FS and ARCH_GET_GS
  2016-04-08  7:13   ` [PATCH v3 2/7] x86/arch_prctl: Fix ARCH_GET_FS and ARCH_GET_GS Ingo Molnar
  2016-04-08  9:39     ` Dmitry Safonov
@ 2016-04-08 16:03     ` Andy Lutomirski
  1 sibling, 0 replies; 16+ messages in thread
From: Andy Lutomirski @ 2016-04-08 16:03 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Andy Lutomirski, Borislav Petkov, security, X86 ML, linux-kernel,
	Linus Torvalds, Rudolf Marek, Denys Vlasenko, Thomas Gleixner,
	H. Peter Anvin

On Fri, Apr 8, 2016 at 12:13 AM, Ingo Molnar <mingo@kernel.org> wrote:
>
> * Andy Lutomirski <luto@kernel.org> wrote:
>
>> ARCH_GET_FS and ARCH_GET_GS attempted to figure out the fsbase and
>> gsbase respectively from saved thread state.  This was wrong: fsbase
>> and gsbase live in registers while a thread is running, not in
>> memory.
>
> So I'm wondering, the current code looks totally broken,what user-space code can
> possibly use this? I checked glibc and Wine, and neither of them does. Wine uses
> ARCH_SET_GS and glibc uses ARCH_SET_FS, but that's all - neither actually tries to
> use the ARCH_GET_* reading APIs.
>
> So for backporting purposes I'd be much happier about simply returning -EINVAL or
> -ENOSYS, and we could re-introduce this code in v4.7.
>

Let's just not backport this one.  There's no security issue here.  If
you like the rest of the series, can you remove the stable tag from
this patch when you apply it?

I think the old code was at least correct enough that if you did
ARCH_GET_FS after ARCH_SET_FS with no funny business in between, it
would work.

--Andy


-- 
Andy Lutomirski
AMA Capital Management, LLC

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [tip:x86/asm] selftests/x86: Test the FSBASE/GSBASE API and context switching
  2016-04-08  0:31 ` [PATCH v3 1/7] selftests/x86: Test the FSBASE/GSBASE API and context switching Andy Lutomirski
@ 2016-04-13 11:28   ` tip-bot for Andy Lutomirski
  0 siblings, 0 replies; 16+ messages in thread
From: tip-bot for Andy Lutomirski @ 2016-04-13 11:28 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: mingo, bp, bp, hpa, tglx, linux-kernel, r.marek, luto, peterz,
	luto, dvlasenk, brgerst, torvalds

Commit-ID:  0051202f6ad5fd9c04d220343e66d1eb890f7b81
Gitweb:     http://git.kernel.org/tip/0051202f6ad5fd9c04d220343e66d1eb890f7b81
Author:     Andy Lutomirski <luto@kernel.org>
AuthorDate: Thu, 7 Apr 2016 17:31:44 -0700
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 13 Apr 2016 10:20:41 +0200

selftests/x86: Test the FSBASE/GSBASE API and context switching

This catches two distinct bugs in the current code.  I'll fix them.

Signed-off-by: Andy Lutomirski <luto@kernel.org>
Reviewed-by: Borislav Petkov <bp@suse.de>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Rudolf Marek <r.marek@assembler.cz>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/7e5941148d1e2199f070dadcdf7355959f5f8e85.1460075211.git.luto@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 tools/testing/selftests/x86/Makefile   |   1 +
 tools/testing/selftests/x86/fsgsbase.c | 398 +++++++++++++++++++++++++++++++++
 2 files changed, 399 insertions(+)

diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile
index b47ebd1..c73425d 100644
--- a/tools/testing/selftests/x86/Makefile
+++ b/tools/testing/selftests/x86/Makefile
@@ -9,6 +9,7 @@ TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_sysc
 TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault test_syscall_vdso unwind_vdso \
 			test_FCMOV test_FCOMI test_FISTTP \
 			vdso_restorer
+TARGETS_C_64BIT_ONLY := fsgsbase
 
 TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY)
 TARGETS_C_64BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_64BIT_ONLY)
diff --git a/tools/testing/selftests/x86/fsgsbase.c b/tools/testing/selftests/x86/fsgsbase.c
new file mode 100644
index 0000000..5b2b4b3
--- /dev/null
+++ b/tools/testing/selftests/x86/fsgsbase.c
@@ -0,0 +1,398 @@
+/*
+ * fsgsbase.c, an fsgsbase test
+ * Copyright (c) 2014-2016 Andy Lutomirski
+ * GPL v2
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <err.h>
+#include <sys/user.h>
+#include <asm/prctl.h>
+#include <sys/prctl.h>
+#include <signal.h>
+#include <limits.h>
+#include <sys/ucontext.h>
+#include <sched.h>
+#include <linux/futex.h>
+#include <pthread.h>
+#include <asm/ldt.h>
+#include <sys/mman.h>
+
+#ifndef __x86_64__
+# error This test is 64-bit only
+#endif
+
+static volatile sig_atomic_t want_segv;
+static volatile unsigned long segv_addr;
+
+static int nerrs;
+
+static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
+		       int flags)
+{
+	struct sigaction sa;
+	memset(&sa, 0, sizeof(sa));
+	sa.sa_sigaction = handler;
+	sa.sa_flags = SA_SIGINFO | flags;
+	sigemptyset(&sa.sa_mask);
+	if (sigaction(sig, &sa, 0))
+		err(1, "sigaction");
+}
+
+static void clearhandler(int sig)
+{
+	struct sigaction sa;
+	memset(&sa, 0, sizeof(sa));
+	sa.sa_handler = SIG_DFL;
+	sigemptyset(&sa.sa_mask);
+	if (sigaction(sig, &sa, 0))
+		err(1, "sigaction");
+}
+
+static void sigsegv(int sig, siginfo_t *si, void *ctx_void)
+{
+	ucontext_t *ctx = (ucontext_t*)ctx_void;
+
+	if (!want_segv) {
+		clearhandler(SIGSEGV);
+		return;  /* Crash cleanly. */
+	}
+
+	want_segv = false;
+	segv_addr = (unsigned long)si->si_addr;
+
+	ctx->uc_mcontext.gregs[REG_RIP] += 4;	/* Skip the faulting mov */
+
+}
+
+enum which_base { FS, GS };
+
+static unsigned long read_base(enum which_base which)
+{
+	unsigned long offset;
+	/*
+	 * Unless we have FSGSBASE, there's no direct way to do this from
+	 * user mode.  We can get at it indirectly using signals, though.
+	 */
+
+	want_segv = true;
+
+	offset = 0;
+	if (which == FS) {
+		/* Use a constant-length instruction here. */
+		asm volatile ("mov %%fs:(%%rcx), %%rax" : : "c" (offset) : "rax");
+	} else {
+		asm volatile ("mov %%gs:(%%rcx), %%rax" : : "c" (offset) : "rax");
+	}
+	if (!want_segv)
+		return segv_addr + offset;
+
+	/*
+	 * If that didn't segfault, try the other end of the address space.
+	 * Unless we get really unlucky and run into the vsyscall page, this
+	 * is guaranteed to segfault.
+	 */
+
+	offset = (ULONG_MAX >> 1) + 1;
+	if (which == FS) {
+		asm volatile ("mov %%fs:(%%rcx), %%rax"
+			      : : "c" (offset) : "rax");
+	} else {
+		asm volatile ("mov %%gs:(%%rcx), %%rax"
+			      : : "c" (offset) : "rax");
+	}
+	if (!want_segv)
+		return segv_addr + offset;
+
+	abort();
+}
+
+static void check_gs_value(unsigned long value)
+{
+	unsigned long base;
+	unsigned short sel;
+
+	printf("[RUN]\tARCH_SET_GS to 0x%lx\n", value);
+	if (syscall(SYS_arch_prctl, ARCH_SET_GS, value) != 0)
+		err(1, "ARCH_SET_GS");
+
+	asm volatile ("mov %%gs, %0" : "=rm" (sel));
+	base = read_base(GS);
+	if (base == value) {
+		printf("[OK]\tGSBASE was set as expected (selector 0x%hx)\n",
+		       sel);
+	} else {
+		nerrs++;
+		printf("[FAIL]\tGSBASE was not as expected: got 0x%lx (selector 0x%hx)\n",
+		       base, sel);
+	}
+
+	if (syscall(SYS_arch_prctl, ARCH_GET_GS, &base) != 0)
+		err(1, "ARCH_GET_GS");
+	if (base == value) {
+		printf("[OK]\tARCH_GET_GS worked as expected (selector 0x%hx)\n",
+		       sel);
+	} else {
+		nerrs++;
+		printf("[FAIL]\tARCH_GET_GS was not as expected: got 0x%lx (selector 0x%hx)\n",
+		       base, sel);
+	}
+}
+
+static void mov_0_gs(unsigned long initial_base, bool schedule)
+{
+	unsigned long base, arch_base;
+
+	printf("[RUN]\tARCH_SET_GS to 0x%lx then mov 0 to %%gs%s\n", initial_base, schedule ? " and schedule " : "");
+	if (syscall(SYS_arch_prctl, ARCH_SET_GS, initial_base) != 0)
+		err(1, "ARCH_SET_GS");
+
+	if (schedule)
+		usleep(10);
+
+	asm volatile ("mov %0, %%gs" : : "rm" (0));
+	base = read_base(GS);
+	if (syscall(SYS_arch_prctl, ARCH_GET_GS, &arch_base) != 0)
+		err(1, "ARCH_GET_GS");
+	if (base == arch_base) {
+		printf("[OK]\tGSBASE is 0x%lx\n", base);
+	} else {
+		nerrs++;
+		printf("[FAIL]\tGSBASE changed to 0x%lx but kernel reports 0x%lx\n", base, arch_base);
+	}
+}
+
+static volatile unsigned long remote_base;
+static volatile bool remote_hard_zero;
+static volatile unsigned int ftx;
+
+/*
+ * ARCH_SET_FS/GS(0) may or may not program a selector of zero.  HARD_ZERO
+ * means to force the selector to zero to improve test coverage.
+ */
+#define HARD_ZERO 0xa1fa5f343cb85fa4
+
+static void do_remote_base()
+{
+	unsigned long to_set = remote_base;
+	bool hard_zero = false;
+	if (to_set == HARD_ZERO) {
+		to_set = 0;
+		hard_zero = true;
+	}
+
+	if (syscall(SYS_arch_prctl, ARCH_SET_GS, to_set) != 0)
+		err(1, "ARCH_SET_GS");
+
+	if (hard_zero)
+		asm volatile ("mov %0, %%gs" : : "rm" ((unsigned short)0));
+
+	unsigned short sel;
+	asm volatile ("mov %%gs, %0" : "=rm" (sel));
+	printf("\tother thread: ARCH_SET_GS(0x%lx)%s -- sel is 0x%hx\n",
+	       to_set, hard_zero ? " and clear gs" : "", sel);
+}
+
+void do_unexpected_base(void)
+{
+	/*
+	 * The goal here is to try to arrange for GS == 0, GSBASE !=
+	 * 0, and for the the kernel the think that GSBASE == 0.
+	 *
+	 * To make the test as reliable as possible, this uses
+	 * explicit descriptorss.  (This is not the only way.  This
+	 * could use ARCH_SET_GS with a low, nonzero base, but the
+	 * relevant side effect of ARCH_SET_GS could change.)
+	 */
+
+	/* Step 1: tell the kernel that we have GSBASE == 0. */
+	if (syscall(SYS_arch_prctl, ARCH_SET_GS, 0) != 0)
+		err(1, "ARCH_SET_GS");
+
+	/* Step 2: change GSBASE without telling the kernel. */
+	struct user_desc desc = {
+		.entry_number    = 0,
+		.base_addr       = 0xBAADF00D,
+		.limit           = 0xfffff,
+		.seg_32bit       = 1,
+		.contents        = 0, /* Data, grow-up */
+		.read_exec_only  = 0,
+		.limit_in_pages  = 1,
+		.seg_not_present = 0,
+		.useable         = 0
+	};
+	if (syscall(SYS_modify_ldt, 1, &desc, sizeof(desc)) == 0) {
+		printf("\tother thread: using LDT slot 0\n");
+		asm volatile ("mov %0, %%gs" : : "rm" ((unsigned short)0x7));
+	} else {
+		/* No modify_ldt for us (configured out, perhaps) */
+
+		struct user_desc *low_desc = mmap(
+			NULL, sizeof(desc),
+			PROT_READ | PROT_WRITE,
+			MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0);
+		memcpy(low_desc, &desc, sizeof(desc));
+
+		low_desc->entry_number = -1;
+
+		/* 32-bit set_thread_area */
+		long ret;
+		asm volatile ("int $0x80"
+			      : "=a" (ret) : "a" (243), "b" (low_desc)
+			      : "flags");
+		memcpy(&desc, low_desc, sizeof(desc));
+		munmap(low_desc, sizeof(desc));
+
+		if (ret != 0) {
+			printf("[NOTE]\tcould not create a segment -- test won't do anything\n");
+			return;
+		}
+		printf("\tother thread: using GDT slot %d\n", desc.entry_number);
+		asm volatile ("mov %0, %%gs" : : "rm" ((unsigned short)((desc.entry_number << 3) | 0x3)));
+	}
+
+	/*
+	 * Step 3: set the selector back to zero.  On AMD chips, this will
+	 * preserve GSBASE.
+	 */
+
+	asm volatile ("mov %0, %%gs" : : "rm" ((unsigned short)0));
+}
+
+static void *threadproc(void *ctx)
+{
+	while (1) {
+		while (ftx == 0)
+			syscall(SYS_futex, &ftx, FUTEX_WAIT, 0, NULL, NULL, 0);
+		if (ftx == 3)
+			return NULL;
+
+		if (ftx == 1)
+			do_remote_base();
+		else if (ftx == 2)
+			do_unexpected_base();
+		else
+			errx(1, "helper thread got bad command");
+
+		ftx = 0;
+		syscall(SYS_futex, &ftx, FUTEX_WAKE, 0, NULL, NULL, 0);
+	}
+}
+
+static void set_gs_and_switch_to(unsigned long local, unsigned long remote)
+{
+	unsigned long base;
+
+	bool hard_zero = false;
+	if (local == HARD_ZERO) {
+		hard_zero = true;
+		local = 0;
+	}
+
+	printf("[RUN]\tARCH_SET_GS(0x%lx)%s, then schedule to 0x%lx\n",
+	       local, hard_zero ? " and clear gs" : "", remote);
+	if (syscall(SYS_arch_prctl, ARCH_SET_GS, local) != 0)
+		err(1, "ARCH_SET_GS");
+	if (hard_zero)
+		asm volatile ("mov %0, %%gs" : : "rm" ((unsigned short)0));
+
+	if (read_base(GS) != local) {
+		nerrs++;
+		printf("[FAIL]\tGSBASE wasn't set as expected\n");
+	}
+
+	remote_base = remote;
+	ftx = 1;
+	syscall(SYS_futex, &ftx, FUTEX_WAKE, 0, NULL, NULL, 0);
+	while (ftx != 0)
+		syscall(SYS_futex, &ftx, FUTEX_WAIT, 1, NULL, NULL, 0);
+
+	base = read_base(GS);
+	if (base == local) {
+		printf("[OK]\tGSBASE remained 0x%lx\n", local);
+	} else {
+		nerrs++;
+		printf("[FAIL]\tGSBASE changed to 0x%lx\n", base);
+	}
+}
+
+static void test_unexpected_base(void)
+{
+	unsigned long base;
+
+	printf("[RUN]\tARCH_SET_GS(0), clear gs, then manipulate GSBASE in a different thread\n");
+	if (syscall(SYS_arch_prctl, ARCH_SET_GS, 0) != 0)
+		err(1, "ARCH_SET_GS");
+	asm volatile ("mov %0, %%gs" : : "rm" ((unsigned short)0));
+
+	ftx = 2;
+	syscall(SYS_futex, &ftx, FUTEX_WAKE, 0, NULL, NULL, 0);
+	while (ftx != 0)
+		syscall(SYS_futex, &ftx, FUTEX_WAIT, 1, NULL, NULL, 0);
+
+	base = read_base(GS);
+	if (base == 0) {
+		printf("[OK]\tGSBASE remained 0\n");
+	} else {
+		nerrs++;
+		printf("[FAIL]\tGSBASE changed to 0x%lx\n", base);
+	}
+}
+
+int main()
+{
+	pthread_t thread;
+
+	sethandler(SIGSEGV, sigsegv, 0);
+
+	check_gs_value(0);
+	check_gs_value(1);
+	check_gs_value(0x200000000);
+	check_gs_value(0);
+	check_gs_value(0x200000000);
+	check_gs_value(1);
+
+	for (int sched = 0; sched < 2; sched++) {
+		mov_0_gs(0, !!sched);
+		mov_0_gs(1, !!sched);
+		mov_0_gs(0x200000000, !!sched);
+	}
+
+	/* Set up for multithreading. */
+
+	cpu_set_t cpuset;
+	CPU_ZERO(&cpuset);
+	CPU_SET(0, &cpuset);
+	if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0)
+		err(1, "sched_setaffinity to CPU 0");	/* should never fail */
+
+	if (pthread_create(&thread, 0, threadproc, 0) != 0)
+		err(1, "pthread_create");
+
+	static unsigned long bases_with_hard_zero[] = {
+		0, HARD_ZERO, 1, 0x200000000,
+	};
+
+	for (int local = 0; local < 4; local++) {
+		for (int remote = 0; remote < 4; remote++) {
+			set_gs_and_switch_to(bases_with_hard_zero[local],
+					     bases_with_hard_zero[remote]);
+		}
+	}
+
+	test_unexpected_base();
+
+	ftx = 3;  /* Kill the thread. */
+	syscall(SYS_futex, &ftx, FUTEX_WAKE, 0, NULL, NULL, 0);
+
+	if (pthread_join(thread, NULL) != 0)
+		err(1, "pthread_join");
+
+	return nerrs == 0 ? 0 : 1;
+}

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [tip:x86/asm] x86/arch_prctl: Fix ARCH_GET_FS and ARCH_GET_GS
       [not found] ` <c6e7b507c72ca3bdbf6c7a8a3ceaa0334e873bd9.1460075211.git.luto@kernel.org>
  2016-04-08  7:13   ` [PATCH v3 2/7] x86/arch_prctl: Fix ARCH_GET_FS and ARCH_GET_GS Ingo Molnar
@ 2016-04-13 11:29   ` tip-bot for Andy Lutomirski
  1 sibling, 0 replies; 16+ messages in thread
From: tip-bot for Andy Lutomirski @ 2016-04-13 11:29 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: peterz, mingo, luto, torvalds, r.marek, dvlasenk, bp,
	linux-kernel, bp, brgerst, luto, tglx, hpa

Commit-ID:  d47b50e7a111bb7a56fb1c974728b56209d7f515
Gitweb:     http://git.kernel.org/tip/d47b50e7a111bb7a56fb1c974728b56209d7f515
Author:     Andy Lutomirski <luto@kernel.org>
AuthorDate: Thu, 7 Apr 2016 17:31:45 -0700
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 13 Apr 2016 10:20:41 +0200

x86/arch_prctl: Fix ARCH_GET_FS and ARCH_GET_GS

ARCH_GET_FS and ARCH_GET_GS attempted to figure out the fsbase and
gsbase respectively from saved thread state.  This was wrong: fsbase
and gsbase live in registers while a thread is running, not in
memory.

For reasons I can't fathom, the fsbase and gsbase code were
different.  Since neither was correct, I didn't try to figure out
what the point of the difference was.

Change it to simply read the MSRs.

The code for reading the base for a remote thread is also completely
wrong if the target thread uses its own descriptors (which is the case
for all 32-bit threaded programs), but fixing that is a different
story.

Signed-off-by: Andy Lutomirski <luto@kernel.org>
Reviewed-by: Borislav Petkov <bp@suse.de>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Rudolf Marek <r.marek@assembler.cz>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/c6e7b507c72ca3bdbf6c7a8a3ceaa0334e873bd9.1460075211.git.luto@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/kernel/process_64.c | 19 +++++++------------
 1 file changed, 7 insertions(+), 12 deletions(-)

diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 6cbab31..c671b9b 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -566,10 +566,10 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
 		break;
 	case ARCH_GET_FS: {
 		unsigned long base;
-		if (task->thread.fsindex == FS_TLS_SEL)
-			base = read_32bit_tls(task, FS_TLS);
-		else if (doit)
+		if (doit)
 			rdmsrl(MSR_FS_BASE, base);
+		else if (task->thread.fsindex == FS_TLS_SEL)
+			base = read_32bit_tls(task, FS_TLS);
 		else
 			base = task->thread.fs;
 		ret = put_user(base, (unsigned long __user *)addr);
@@ -577,16 +577,11 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
 	}
 	case ARCH_GET_GS: {
 		unsigned long base;
-		unsigned gsindex;
-		if (task->thread.gsindex == GS_TLS_SEL)
+		if (doit)
+			rdmsrl(MSR_KERNEL_GS_BASE, base);
+		else if (task->thread.gsindex == GS_TLS_SEL)
 			base = read_32bit_tls(task, GS_TLS);
-		else if (doit) {
-			savesegment(gs, gsindex);
-			if (gsindex)
-				rdmsrl(MSR_KERNEL_GS_BASE, base);
-			else
-				base = task->thread.gs;
-		} else
+		else
 			base = task->thread.gs;
 		ret = put_user(base, (unsigned long __user *)addr);
 		break;

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [tip:x86/asm] x86/cpu: Move X86_BUG_ESPFIX initialization to generic_identify()
  2016-04-08  0:31 ` [PATCH v3 5/7] x86/cpu: Move X86_BUG_ESPFIX initialization to generic_identify Andy Lutomirski
@ 2016-04-13 11:30   ` tip-bot for Andy Lutomirski
  0 siblings, 0 replies; 16+ messages in thread
From: tip-bot for Andy Lutomirski @ 2016-04-13 11:30 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: tglx, torvalds, peterz, mingo, luto, linux-kernel, r.marek, luto,
	brgerst, bp, dvlasenk, hpa, bp

Commit-ID:  0230bb038fa99af0c425fc4cffed307e545a9642
Gitweb:     http://git.kernel.org/tip/0230bb038fa99af0c425fc4cffed307e545a9642
Author:     Andy Lutomirski <luto@kernel.org>
AuthorDate: Thu, 7 Apr 2016 17:31:48 -0700
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 13 Apr 2016 10:20:42 +0200

x86/cpu: Move X86_BUG_ESPFIX initialization to generic_identify()

It was in detect_nopl(), which was either a mistake by me or some kind
of mis-merge.

Signed-off-by: Andy Lutomirski <luto@kernel.org>
Reviewed-by: Borislav Petkov <bp@suse.de>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Rudolf Marek <r.marek@assembler.cz>
Cc: Thomas Gleixner <tglx@linutronix.de>
Fixes: ff236456f072 ("x86/cpu: Move X86_BUG_ESPFIX initialization to generic_identify")
Link: http://lkml.kernel.org/r/0949337f13660461edca08ab67d1a841441289c9.1460075211.git.luto@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/kernel/cpu/common.c | 50 ++++++++++++++++++++++----------------------
 1 file changed, 25 insertions(+), 25 deletions(-)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 8e40eee..28d3255 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -862,31 +862,6 @@ static void detect_nopl(struct cpuinfo_x86 *c)
 #else
 	set_cpu_cap(c, X86_FEATURE_NOPL);
 #endif
-
-	/*
-	 * ESPFIX is a strange bug.  All real CPUs have it.  Paravirt
-	 * systems that run Linux at CPL > 0 may or may not have the
-	 * issue, but, even if they have the issue, there's absolutely
-	 * nothing we can do about it because we can't use the real IRET
-	 * instruction.
-	 *
-	 * NB: For the time being, only 32-bit kernels support
-	 * X86_BUG_ESPFIX as such.  64-bit kernels directly choose
-	 * whether to apply espfix using paravirt hooks.  If any
-	 * non-paravirt system ever shows up that does *not* have the
-	 * ESPFIX issue, we can change this.
-	 */
-#ifdef CONFIG_X86_32
-#ifdef CONFIG_PARAVIRT
-	do {
-		extern void native_iret(void);
-		if (pv_cpu_ops.iret == native_iret)
-			set_cpu_bug(c, X86_BUG_ESPFIX);
-	} while (0);
-#else
-	set_cpu_bug(c, X86_BUG_ESPFIX);
-#endif
-#endif
 }
 
 static void detect_null_seg_behavior(struct cpuinfo_x86 *c)
@@ -952,6 +927,31 @@ static void generic_identify(struct cpuinfo_x86 *c)
 	detect_nopl(c);
 
 	detect_null_seg_behavior(c);
+
+	/*
+	 * ESPFIX is a strange bug.  All real CPUs have it.  Paravirt
+	 * systems that run Linux at CPL > 0 may or may not have the
+	 * issue, but, even if they have the issue, there's absolutely
+	 * nothing we can do about it because we can't use the real IRET
+	 * instruction.
+	 *
+	 * NB: For the time being, only 32-bit kernels support
+	 * X86_BUG_ESPFIX as such.  64-bit kernels directly choose
+	 * whether to apply espfix using paravirt hooks.  If any
+	 * non-paravirt system ever shows up that does *not* have the
+	 * ESPFIX issue, we can change this.
+	 */
+#ifdef CONFIG_X86_32
+# ifdef CONFIG_PARAVIRT
+	do {
+		extern void native_iret(void);
+		if (pv_cpu_ops.iret == native_iret)
+			set_cpu_bug(c, X86_BUG_ESPFIX);
+	} while (0);
+# else
+	set_cpu_bug(c, X86_BUG_ESPFIX);
+# endif
+#endif
 }
 
 static void x86_init_cache_qos(struct cpuinfo_x86 *c)

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [tip:x86/asm] x86/cpu: Add Erratum 88 detection on AMD
       [not found] ` <aec6b2df1bfc56101d4e9e2e5d5d570bf41663c6.1460075211.git.luto@kernel.org>
  2016-04-08  1:40   ` [PATCH v3 6/7] x86/cpu: Add Erratum 88 detection on AMD Andy Lutomirski
@ 2016-04-13 11:30   ` tip-bot for Borislav Petkov
  1 sibling, 0 replies; 16+ messages in thread
From: tip-bot for Borislav Petkov @ 2016-04-13 11:30 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: bp, peterz, brgerst, linux-kernel, mingo, tglx, bp, dvlasenk,
	hpa, r.marek, torvalds, luto

Commit-ID:  96e5d28ae7a5250f3deb2434f1895c9daf48b1bd
Gitweb:     http://git.kernel.org/tip/96e5d28ae7a5250f3deb2434f1895c9daf48b1bd
Author:     Borislav Petkov <bp@suse.de>
AuthorDate: Thu, 7 Apr 2016 17:31:49 -0700
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 13 Apr 2016 10:20:42 +0200

x86/cpu: Add Erratum 88 detection on AMD

Erratum 88 affects old AMD K8s, where a SWAPGS fails to cause an input
dependency on GS. Therefore, we need to MFENCE before it.

But that MFENCE is expensive and unnecessary on the remaining x86 CPUs
out there so patch it out on the CPUs which don't require it.

Signed-off-by: Borislav Petkov <bp@suse.de>
Signed-off-by: Andy Lutomirski <luto@kernel.org
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Rudolf Marek <r.marek@assembler.cz>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/aec6b2df1bfc56101d4e9e2e5d5d570bf41663c6.1460075211.git.luto@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/entry/entry_64.S          | 2 +-
 arch/x86/include/asm/cpufeatures.h | 2 ++
 arch/x86/kernel/cpu/amd.c          | 1 +
 3 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
index 858b555..64d2033 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -783,7 +783,7 @@ ENTRY(native_load_gs_index)
 	SWAPGS
 gs_change:
 	movl	%edi, %gs
-2:	mfence					/* workaround */
+2:	ALTERNATIVE "", "mfence", X86_BUG_SWAPGS_FENCE
 	SWAPGS
 	popfq
 	ret
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index 2a05230..7bfb6b7 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -295,6 +295,8 @@
 #define X86_BUG_CLFLUSH_MONITOR	X86_BUG(7) /* AAI65, CLFLUSH required before MONITOR */
 #define X86_BUG_SYSRET_SS_ATTRS	X86_BUG(8) /* SYSRET doesn't fix up SS attrs */
 #define X86_BUG_NULL_SEG	X86_BUG(9) /* Nulling a selector preserves the base */
+#define X86_BUG_SWAPGS_FENCE	X86_BUG(10) /* SWAPGS without input dep on GS */
+
 
 #ifdef CONFIG_X86_32
 /*
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 6e47e3a..b7cc9ef 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -632,6 +632,7 @@ static void init_amd_k8(struct cpuinfo_x86 *c)
 	 */
 	msr_set_bit(MSR_K7_HWCR, 6);
 #endif
+	set_cpu_bug(c, X86_BUG_SWAPGS_FENCE);
 }
 
 static void init_amd_gh(struct cpuinfo_x86 *c)

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [tip:x86/asm] x86/entry/64: Make gs_change a local label
  2016-04-08  0:31 ` [PATCH v3 7/7] x86/entry: Make gs_change a local label Andy Lutomirski
@ 2016-04-13 11:31   ` tip-bot for Borislav Petkov
  0 siblings, 0 replies; 16+ messages in thread
From: tip-bot for Borislav Petkov @ 2016-04-13 11:31 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hpa, tglx, dvlasenk, r.marek, luto, bp, mingo, bp, brgerst,
	torvalds, peterz, linux-kernel, luto

Commit-ID:  42c748bb2544f21c3d115240527fe4478e193641
Gitweb:     http://git.kernel.org/tip/42c748bb2544f21c3d115240527fe4478e193641
Author:     Borislav Petkov <bp@suse.de>
AuthorDate: Thu, 7 Apr 2016 17:31:50 -0700
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 13 Apr 2016 10:20:42 +0200

x86/entry/64: Make gs_change a local label

... so that it doesn't appear in objdump output.

Signed-off-by: Borislav Petkov <bp@suse.de>
Signed-off-by: Andy Lutomirski <luto@kernel.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Rudolf Marek <r.marek@assembler.cz>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/b9c532a0e5f8d56dede2bd59767d40024d5a75e2.1460075211.git.luto@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/entry/entry_64.S | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
index 64d2033..1693c17 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -781,7 +781,7 @@ ENTRY(native_load_gs_index)
 	pushfq
 	DISABLE_INTERRUPTS(CLBR_ANY & ~CLBR_RDI)
 	SWAPGS
-gs_change:
+.Lgs_change:
 	movl	%edi, %gs
 2:	ALTERNATIVE "", "mfence", X86_BUG_SWAPGS_FENCE
 	SWAPGS
@@ -789,7 +789,7 @@ gs_change:
 	ret
 END(native_load_gs_index)
 
-	_ASM_EXTABLE(gs_change, bad_gs)
+	_ASM_EXTABLE(.Lgs_change, bad_gs)
 	.section .fixup, "ax"
 	/* running with kernelgs */
 bad_gs:
@@ -1019,13 +1019,13 @@ ENTRY(error_entry)
 	movl	%ecx, %eax			/* zero extend */
 	cmpq	%rax, RIP+8(%rsp)
 	je	.Lbstep_iret
-	cmpq	$gs_change, RIP+8(%rsp)
+	cmpq	$.Lgs_change, RIP+8(%rsp)
 	jne	.Lerror_entry_done
 
 	/*
-	 * hack: gs_change can fail with user gsbase.  If this happens, fix up
+	 * hack: .Lgs_change can fail with user gsbase.  If this happens, fix up
 	 * gsbase and proceed.  We'll fix up the exception and land in
-	 * gs_change's error handler with kernel gsbase.
+	 * .Lgs_change's error handler with kernel gsbase.
 	 */
 	jmp	.Lerror_entry_from_usermode_swapgs
 

^ permalink raw reply related	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2016-04-13 11:33 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-04-08  0:31 [PATCH v3 0/7] x86: Pile o' FS/GS changes Andy Lutomirski
2016-04-08  0:31 ` [PATCH v3 1/7] selftests/x86: Test the FSBASE/GSBASE API and context switching Andy Lutomirski
2016-04-13 11:28   ` [tip:x86/asm] " tip-bot for Andy Lutomirski
2016-04-08  0:31 ` [PATCH v3 5/7] x86/cpu: Move X86_BUG_ESPFIX initialization to generic_identify Andy Lutomirski
2016-04-13 11:30   ` [tip:x86/asm] x86/cpu: Move X86_BUG_ESPFIX initialization to generic_identify() tip-bot for Andy Lutomirski
2016-04-08  0:31 ` [PATCH v3 7/7] x86/entry: Make gs_change a local label Andy Lutomirski
2016-04-13 11:31   ` [tip:x86/asm] x86/entry/64: " tip-bot for Borislav Petkov
2016-04-08 10:39 ` [PATCH v3 0/7] x86: Pile o' FS/GS changes Borislav Petkov
2016-04-08 10:40 ` Borislav Petkov
     [not found] ` <c6e7b507c72ca3bdbf6c7a8a3ceaa0334e873bd9.1460075211.git.luto@kernel.org>
2016-04-08  7:13   ` [PATCH v3 2/7] x86/arch_prctl: Fix ARCH_GET_FS and ARCH_GET_GS Ingo Molnar
2016-04-08  9:39     ` Dmitry Safonov
2016-04-08 16:03     ` Andy Lutomirski
2016-04-13 11:29   ` [tip:x86/asm] " tip-bot for Andy Lutomirski
     [not found] ` <aec6b2df1bfc56101d4e9e2e5d5d570bf41663c6.1460075211.git.luto@kernel.org>
2016-04-08  1:40   ` [PATCH v3 6/7] x86/cpu: Add Erratum 88 detection on AMD Andy Lutomirski
2016-04-08  9:51     ` Borislav Petkov
2016-04-13 11:30   ` [tip:x86/asm] " tip-bot for Borislav Petkov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.