android_kernel_samsung_msm8976/arch
Andy Lutomirski cb7977a9a8 x86_64, switch_to(): Load TLS descriptors before switching DS and ES
commit f647d7c155f069c1a068030255c300663516420e upstream.

Otherwise, if buggy user code points DS or ES into the TLS
array, they would be corrupted after a context switch.

This also significantly improves the comments and documents some
gotchas in the code.

Before this patch, the both tests below failed.  With this
patch, the es test passes, although the gsbase test still fails.

 ----- begin es test -----

/*
 * Copyright (c) 2014 Andy Lutomirski
 * GPL v2
 */

static unsigned short GDT3(int idx)
{
	return (idx << 3) | 3;
}

static int create_tls(int idx, unsigned int base)
{
	struct user_desc desc = {
		.entry_number    = idx,
		.base_addr       = base,
		.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_set_thread_area, &desc) != 0)
		err(1, "set_thread_area");

	return desc.entry_number;
}

int main()
{
	int idx = create_tls(-1, 0);
	printf("Allocated GDT index %d\n", idx);

	unsigned short orig_es;
	asm volatile ("mov %%es,%0" : "=rm" (orig_es));

	int errors = 0;
	int total = 1000;
	for (int i = 0; i < total; i++) {
		asm volatile ("mov %0,%%es" : : "rm" (GDT3(idx)));
		usleep(100);

		unsigned short es;
		asm volatile ("mov %%es,%0" : "=rm" (es));
		asm volatile ("mov %0,%%es" : : "rm" (orig_es));
		if (es != GDT3(idx)) {
			if (errors == 0)
				printf("[FAIL]\tES changed from 0x%hx to 0x%hx\n",
				       GDT3(idx), es);
			errors++;
		}
	}

	if (errors) {
		printf("[FAIL]\tES was corrupted %d/%d times\n", errors, total);
		return 1;
	} else {
		printf("[OK]\tES was preserved\n");
		return 0;
	}
}

 ----- end es test -----

 ----- begin gsbase test -----

/*
 * gsbase.c, a gsbase test
 * Copyright (c) 2014 Andy Lutomirski
 * GPL v2
 */

static unsigned char *testptr, *testptr2;

static unsigned char read_gs_testvals(void)
{
	unsigned char ret;
	asm volatile ("movb %%gs:%1, %0" : "=r" (ret) : "m" (*testptr));
	return ret;
}

int main()
{
	int errors = 0;

	testptr = mmap((void *)0x200000000UL, 1, PROT_READ | PROT_WRITE,
		       MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
	if (testptr == MAP_FAILED)
		err(1, "mmap");

	testptr2 = mmap((void *)0x300000000UL, 1, PROT_READ | PROT_WRITE,
		       MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
	if (testptr2 == MAP_FAILED)
		err(1, "mmap");

	*testptr = 0;
	*testptr2 = 1;

	if (syscall(SYS_arch_prctl, ARCH_SET_GS,
		    (unsigned long)testptr2 - (unsigned long)testptr) != 0)
		err(1, "ARCH_SET_GS");

	usleep(100);

	if (read_gs_testvals() == 1) {
		printf("[OK]\tARCH_SET_GS worked\n");
	} else {
		printf("[FAIL]\tARCH_SET_GS failed\n");
		errors++;
	}

	asm volatile ("mov %0,%%gs" : : "r" (0));

	if (read_gs_testvals() == 0) {
		printf("[OK]\tWriting 0 to gs worked\n");
	} else {
		printf("[FAIL]\tWriting 0 to gs failed\n");
		errors++;
	}

	usleep(100);

	if (read_gs_testvals() == 0) {
		printf("[OK]\tgsbase is still zero\n");
	} else {
		printf("[FAIL]\tgsbase was corrupted\n");
		errors++;
	}

	return errors == 0 ? 0 : 1;
}

 ----- end gsbase test -----

Signed-off-by: Andy Lutomirski <luto@amacapital.net>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Link: http://lkml.kernel.org/r/509d27c9fec78217691c3dad91cec87e1006b34a.1418075657.git.luto@amacapital.net
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2015-01-08 09:58:15 -08:00
..
alpha arch: mm: pass userspace fault flag to generic fault handler 2014-11-21 09:22:56 -08:00
arc arch: mm: pass userspace fault flag to generic fault handler 2014-11-21 09:22:56 -08:00
arm ARM: sched_clock: Load cycle count after epoch stabilizes 2014-12-16 09:09:43 -08:00
arm64 arch: mm: pass userspace fault flag to generic fault handler 2014-11-21 09:22:56 -08:00
avr32 arch: mm: pass userspace fault flag to generic fault handler 2014-11-21 09:22:56 -08:00
blackfin
c6x
cris arch: mm: pass userspace fault flag to generic fault handler 2014-11-21 09:22:56 -08:00
frv arch: mm: pass userspace fault flag to generic fault handler 2014-11-21 09:22:56 -08:00
h8300
hexagon arch: mm: pass userspace fault flag to generic fault handler 2014-11-21 09:22:56 -08:00
ia64 arch: mm: pass userspace fault flag to generic fault handler 2014-11-21 09:22:56 -08:00
m32r arch: mm: pass userspace fault flag to generic fault handler 2014-11-21 09:22:56 -08:00
m68k arch: mm: pass userspace fault flag to generic fault handler 2014-11-21 09:22:56 -08:00
metag arch: mm: pass userspace fault flag to generic fault handler 2014-11-21 09:22:56 -08:00
microblaze arch: mm: pass userspace fault flag to generic fault handler 2014-11-21 09:22:56 -08:00
mips MIPS: Loongson: Make platform serial setup always built-in. 2014-12-06 15:05:46 -08:00
mn10300 arch: mm: pass userspace fault flag to generic fault handler 2014-11-21 09:22:56 -08:00
openrisc arch: mm: pass userspace fault flag to generic fault handler 2014-11-21 09:22:56 -08:00
parisc arch: mm: pass userspace fault flag to generic fault handler 2014-11-21 09:22:56 -08:00
powerpc powerpc: 32 bit getcpu VDSO function uses 64 bit instructions 2014-12-16 09:09:43 -08:00
s390 arch: mm: pass userspace fault flag to generic fault handler 2014-11-21 09:22:56 -08:00
score arch: mm: pass userspace fault flag to generic fault handler 2014-11-21 09:22:56 -08:00
sh arch: mm: pass userspace fault flag to generic fault handler 2014-11-21 09:22:56 -08:00
sparc sparc64: Fix constraints on swab helpers. 2014-12-06 15:05:46 -08:00
tile arch: mm: pass userspace fault flag to generic fault handler 2014-11-21 09:22:56 -08:00
um arch: mm: pass userspace fault flag to generic fault handler 2014-11-21 09:22:56 -08:00
unicore32 arch: mm: pass userspace fault flag to generic fault handler 2014-11-21 09:22:56 -08:00
x86 x86_64, switch_to(): Load TLS descriptors before switching DS and ES 2015-01-08 09:58:15 -08:00
xtensa arch: mm: pass userspace fault flag to generic fault handler 2014-11-21 09:22:56 -08:00
.gitignore
Kconfig