linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2] x86, selftests: Add sigreturn_32 selftest
@ 2015-03-09 16:36 Andy Lutomirski
  2015-03-09 16:48 ` Ingo Molnar
  0 siblings, 1 reply; 6+ messages in thread
From: Andy Lutomirski @ 2015-03-09 16:36 UTC (permalink / raw)
  To: x86, linux-kernel, Ingo Molnar
  Cc: Steven Rostedt, Denys Vlasenko, Shuah Khan, Borislav Petkov,
	Andy Lutomirski

This is my sigreturn test, added mostly unchanged from its old home.
It abuses sigreturn to test interesting cases when returning to
user space.  It exercises espfix and various iret exceptions.

As a historical note, an older version of this test is the reference PoC
for a number of severe kernel vulnerabilities.  In other words, it will
violently crash many older kernels for multiple reasons.  Hopefully
putting it here will prevent regressions.

The integration with the selftest build process seems okay if not
particularly elegant.

I'm not using the ksft_ helpers at all yet.  I can do that later.

Signed-off-by: Andy Lutomirski <luto@amacapital.net>
---

Changes from v1:
 - Improve changelog.
 - Remove unnecessary includes, hopefully improving portability.

 tools/testing/selftests/Makefile         |   1 +
 tools/testing/selftests/x86/.gitignore   |   2 +
 tools/testing/selftests/x86/Makefile     |  18 ++
 tools/testing/selftests/x86/run_tests.sh |   6 +
 tools/testing/selftests/x86/sigreturn.c  | 529 +++++++++++++++++++++++++++++++
 5 files changed, 556 insertions(+)
 create mode 100644 tools/testing/selftests/x86/.gitignore
 create mode 100644 tools/testing/selftests/x86/Makefile
 create mode 100755 tools/testing/selftests/x86/run_tests.sh
 create mode 100644 tools/testing/selftests/x86/sigreturn.c

diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 4e511221a0c1..2ad56d451469 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -17,6 +17,7 @@ TARGETS += sysctl
 TARGETS += timers
 TARGETS += user
 TARGETS += vm
+TARGETS += x86
 #Please keep the TARGETS list alphabetically sorted
 
 TARGETS_HOTPLUG = cpu-hotplug
diff --git a/tools/testing/selftests/x86/.gitignore b/tools/testing/selftests/x86/.gitignore
new file mode 100644
index 000000000000..15034fef9698
--- /dev/null
+++ b/tools/testing/selftests/x86/.gitignore
@@ -0,0 +1,2 @@
+*_32
+*_64
diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile
new file mode 100644
index 000000000000..3c4fc3158ddc
--- /dev/null
+++ b/tools/testing/selftests/x86/Makefile
@@ -0,0 +1,18 @@
+.PHONY: all clean run_tests
+
+TARGETS_C_32ONLY := sigreturn
+
+BINARIES := $(TARGETS_C_32ONLY:%=%_32)
+
+CFLAGS := -O2 -g -std=gnu99 -pthread -Wall
+
+all: $(BINARIES)
+
+clean:
+	$(RM) $(BINARIES)
+
+run_tests:
+	./run_tests.sh
+
+$(TARGETS_C_32ONLY:%=%_32): %_32: %.c
+	gcc -m32 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl
diff --git a/tools/testing/selftests/x86/run_tests.sh b/tools/testing/selftests/x86/run_tests.sh
new file mode 100755
index 000000000000..2dd495300363
--- /dev/null
+++ b/tools/testing/selftests/x86/run_tests.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+# This is deliberately minimal.  IMO kselftests should provide a standard
+# script here.
+./sigreturn_32
+exit $?
diff --git a/tools/testing/selftests/x86/sigreturn.c b/tools/testing/selftests/x86/sigreturn.c
new file mode 100644
index 000000000000..fab52fd119fd
--- /dev/null
+++ b/tools/testing/selftests/x86/sigreturn.c
@@ -0,0 +1,529 @@
+/*
+ * Sigreturn test.
+ * Copyright (c) 2014-2015 Andrew Lutomirski.
+ *
+ * This abuses sigreturn to test interesting cases when returning to
+ * user space.  It exercises espfix and various iret exceptions.
+ *
+ * GPL v2.
+ */
+
+#define _GNU_SOURCE
+
+#include <time.h>
+#include <stdlib.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/mman.h>
+#include <sys/signal.h>
+#include <sys/ucontext.h>
+#include <asm/ldt.h>
+#include <err.h>
+#include <setjmp.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <sys/user.h>
+
+struct selectors {
+	unsigned short cs, gs, fs, ss;
+};
+
+static bool has_code16, has_data16, has_npcode32, has_npdata32;
+
+static int gdt_data16_idx, gdt_npdata32_idx;
+
+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 unsigned char stack16[65536] __attribute__((aligned(4096)));
+
+asm (".pushsection .text\n\t"
+     ".type int3, @function\n\t"
+     ".align 4096\n\t"
+     "int3:\n\t"
+     "mov %ss,%eax\n\t"
+     "int3\n\t"
+     ".size int3, . - int3\n\t"
+     ".align 4096, 0xcc\n\t"
+     ".popsection");
+extern char int3[4096];
+
+static void add_ldt(const struct user_desc *desc, bool *var, const char *name)
+{
+	if (syscall(SYS_modify_ldt, 1, desc, sizeof(*desc)) == 0) {
+		*var = true;
+	} else {
+		printf("[NOTE]\tFailed to create %s segment\n", name);
+		*var = false;
+	}
+}
+
+static void setup_ldt(void)
+{
+	if ((unsigned long)stack16 > (1ULL << 32) - sizeof(stack16))
+		errx(1, "stack16 is too high\n");
+	if ((unsigned long)int3 > (1ULL << 32) - sizeof(int3))
+		errx(1, "int3 is too high\n");
+
+	/* Borrowed from a test case by hpa */
+	const struct user_desc code16_desc = {
+		.entry_number    = 0,
+		.base_addr       = (unsigned long)int3,
+		.limit           = 4095,
+		.seg_32bit       = 0,
+		.contents        = 2, /* Code, not conforming */
+		.read_exec_only  = 0,
+		.limit_in_pages  = 0,
+		.seg_not_present = 0,
+		.useable         = 0
+	};
+	add_ldt(&code16_desc, &has_code16, "code16");
+
+	const struct user_desc data16_desc = {
+		.entry_number    = 1,
+		.base_addr       = (unsigned long)stack16,
+		.limit           = 0xffff,
+		.seg_32bit       = 0,
+		.contents        = 0, /* Data, grow-up */
+		.read_exec_only  = 0,
+		.limit_in_pages  = 0,
+		.seg_not_present = 0,
+		.useable         = 0
+	};
+	add_ldt(&data16_desc, &has_data16, "data16");
+
+	const struct user_desc npcode32_desc = {
+		.entry_number    = 3,
+		.base_addr       = (unsigned long)int3,
+		.limit           = 4095,
+		.seg_32bit       = 1,
+		.contents        = 2, /* Code, not conforming */
+		.read_exec_only  = 0,
+		.limit_in_pages  = 0,
+		.seg_not_present = 1,
+		.useable         = 0
+	};
+	add_ldt(&npcode32_desc, &has_npcode32, "npcode32");
+
+	const struct user_desc npdata32_desc = {
+		.entry_number    = 4,
+		.base_addr       = (unsigned long)stack16,
+		.limit           = 0xffff,
+		.seg_32bit       = 1,
+		.contents        = 0, /* Data, grow-up */
+		.read_exec_only  = 0,
+		.limit_in_pages  = 0,
+		.seg_not_present = 1,
+		.useable         = 0
+	};
+	add_ldt(&npdata32_desc, &has_npdata32, "npdata32");
+
+	struct user_desc gdt_data16_desc = {
+		.entry_number    = -1,
+		.base_addr       = (unsigned long)stack16,
+		.limit           = 0xffff,
+		.seg_32bit       = 0,
+		.contents        = 0, /* Data, grow-up */
+		.read_exec_only  = 0,
+		.limit_in_pages  = 0,
+		.seg_not_present = 0,
+		.useable         = 0
+	};
+
+	if (syscall(SYS_set_thread_area, &gdt_data16_desc) == 0) {
+		printf("[WARN]\tset_thread_area allocated data16 at index %d\n",
+		       gdt_data16_desc.entry_number);
+		gdt_data16_idx = gdt_data16_desc.entry_number;
+	} else {
+		printf("[OK]\tset_thread_area refused 16-bit data\n");
+	}
+
+	struct user_desc gdt_npdata32_desc = {
+		.entry_number    = -1,
+		.base_addr       = (unsigned long)stack16,
+		.limit           = 0xffff,
+		.seg_32bit       = 1,
+		.contents        = 0, /* Data, grow-up */
+		.read_exec_only  = 0,
+		.limit_in_pages  = 0,
+		.seg_not_present = 1,
+		.useable         = 0
+	};
+
+	if (syscall(SYS_set_thread_area, &gdt_npdata32_desc) == 0) {
+		printf("[WARN]\tset_thread_area allocated npdata32 at index %d\n",
+		       gdt_npdata32_desc.entry_number);
+		gdt_npdata32_idx = gdt_npdata32_desc.entry_number;
+	} else {
+		printf("[OK]\tset_thread_area refused 16-bit data\n");
+	}
+}
+
+static gregset_t initial_regs, requested_regs, resulting_regs;
+
+/* Per POSIX, these should be volatile sigatomic_t.  Go away, pedants. */
+static volatile unsigned short sig_cs, sig_ss;
+static volatile sig_atomic_t sig_trapped, sig_err, sig_trapno;
+
+#ifdef __x86_64__
+# define REG_IP REG_RIP
+# define REG_SP REG_RSP
+# define REG_AX REG_RAX
+
+static unsigned short *ssptr(ucontext_t *ctx)
+{
+	struct selectors *sels = (void *)&ctx->uc_mcontext.gregs[REG_CSGSFS];
+	return &sels->ss;
+}
+
+static unsigned short *csptr(ucontext_t *ctx)
+{
+	struct selectors *sels = (void *)&ctx->uc_mcontext.gregs[REG_CSGSFS];
+	return &sels->cs;
+}
+#else
+# define REG_IP REG_EIP
+# define REG_SP REG_ESP
+# define REG_AX REG_EAX
+
+static greg_t *ssptr(ucontext_t *ctx)
+{
+	return &ctx->uc_mcontext.gregs[REG_SS];
+}
+
+static greg_t *csptr(ucontext_t *ctx)
+{
+	return &ctx->uc_mcontext.gregs[REG_CS];
+}
+#endif
+
+static int nerrs;
+
+static void sigusr1(int sig, siginfo_t *info, void *ctx_void)
+{
+	ucontext_t *ctx = (ucontext_t *)ctx_void;
+
+	memcpy(&initial_regs, &ctx->uc_mcontext.gregs, sizeof(gregset_t));
+
+	*csptr(ctx) = sig_cs;
+	*ssptr(ctx) = sig_ss;
+
+	ctx->uc_mcontext.gregs[REG_IP] =
+		(sig_cs == 0x7 || sig_cs == 0x1f) ? 0 : (unsigned long)&int3;
+	ctx->uc_mcontext.gregs[REG_SP] = (unsigned long)0x8badf00d5aadc0deULL;
+	ctx->uc_mcontext.gregs[REG_AX] = 0;
+
+	memcpy(&requested_regs, &ctx->uc_mcontext.gregs, sizeof(gregset_t));
+	requested_regs[REG_AX] = *ssptr(ctx);	/* The asm code does this. */
+
+	return;
+}
+
+static void sigtrap(int sig, siginfo_t *info, void *ctx_void)
+{
+	ucontext_t *ctx = (ucontext_t*)ctx_void;
+
+	sig_err = ctx->uc_mcontext.gregs[REG_ERR];
+	sig_trapno = ctx->uc_mcontext.gregs[REG_TRAPNO];
+
+	unsigned short ss;
+	asm ("mov %%ss,%0" : "=r" (ss));
+
+	greg_t asm_ss = ctx->uc_mcontext.gregs[REG_AX];
+	if (asm_ss != sig_ss && sig == SIGTRAP) {
+		printf("[FAIL]\tSIGTRAP: ss = %hx, frame ss = %hx, ax = %llx\n",
+		       ss, *ssptr(ctx), (unsigned long long)asm_ss);
+		nerrs++;
+	}
+
+	memcpy(&resulting_regs, &ctx->uc_mcontext.gregs, sizeof(gregset_t));
+	memcpy(&ctx->uc_mcontext.gregs, &initial_regs, sizeof(gregset_t));
+
+	sig_trapped = sig;
+}
+
+static char altstack_data[SIGSTKSZ];
+
+int cs_bitness(unsigned short cs)
+{
+	uint32_t valid = 0, ar;
+	asm ("lar %[cs], %[ar]\n\t"
+	     "jnz 1f\n\t"
+	     "mov $1, %[valid]\n\t"
+	     "1:"
+	     : [ar] "=r" (ar), [valid] "+rm" (valid)
+	     : [cs] "r" (cs));
+
+	if (!valid)
+		return -1;
+
+	bool db = (ar & (1 << 22));
+	bool l = (ar & (1 << 21));
+
+	if (!(ar & (1<<11)))
+		return -1;	/* Not code. */
+
+	if (l && !db)
+		return 64;
+	else if (!l && db)
+		return 32;
+	else if (!l && !db)
+		return 16;
+	else
+		return -1;	/* Unknown bitness. */
+}
+
+int find_cs(int bitness)
+{
+	unsigned short my_cs;
+
+	asm ("mov %%cs,%0" :  "=r" (my_cs));
+
+	if (cs_bitness(my_cs) == bitness)
+		return my_cs;
+	if (cs_bitness(my_cs + (2 << 3)) == bitness)
+		return my_cs + (2 << 3);
+	if (my_cs > (2<<3) && cs_bitness(my_cs - (2 << 3)) == bitness)
+		return my_cs - (2 << 3);
+	if (cs_bitness(0x7) == bitness)
+		return 0x7;
+
+	printf("[WARN]\tCould not find %d-bit CS\n", bitness);
+	return -1;
+}
+
+static int do_test(int cs_bits, bool use_16bit_ss, int force_ss)
+{
+	int cs = find_cs(cs_bits);
+	if (cs == -1) {
+		printf("[SKIP]\tCode segment unavailable for %d-bit CS, %d-bit SS\n",
+		       cs_bits, use_16bit_ss ? 16 : 32);
+		return 0;
+	}
+
+	if (force_ss != -1) {
+		sig_ss = force_ss;
+	} else {
+		if (use_16bit_ss) {
+			if (!has_data16) {
+				printf("[SKIP]\tData segment unavailable for %d-bit CS, 16-bit SS\n",
+				       cs_bits);
+				return 0;
+			}
+			sig_ss = (1 << 3) | 7;	/* LDT selector 1, RPL = 3 */
+		} else {
+			asm volatile ("mov %%ss,%0" : "=r" (sig_ss));
+		}
+	}
+
+	sig_cs = cs;
+
+	printf("[RUN]\t%d-bit CS (%hx), %d-bit SS (%hx%s)\n",
+	       cs_bits, sig_cs, use_16bit_ss ? 16 : 32, sig_ss,
+	       (sig_ss & 4) ? "" : ", GDT");
+
+	raise(SIGUSR1);
+
+	nerrs = 0;
+
+	for (int i = 0; i < NGREG; i++) {
+		greg_t req = requested_regs[i], res = resulting_regs[i];
+		if (i == REG_TRAPNO || i == REG_IP)
+			continue;	/* don't care */
+		if (i == REG_SP) {
+			printf("\tSP: %llx -> %llx\n", (unsigned long long)req,
+			       (unsigned long long)res);
+			if (res == (req & 0xFFFFFFFF))
+				continue;  /* OK; not expected to work */
+		}
+
+		bool ignore_reg = false;
+#if __i386__
+		if (i == REG_UESP)
+			ignore_reg = true;
+#else
+		if (i == REG_CSGSFS) {
+			struct selectors *req_sels =
+				(void *)&requested_regs[REG_CSGSFS];
+			struct selectors *res_sels =
+				(void *)&resulting_regs[REG_CSGSFS];
+			if (req_sels->cs != res_sels->cs) {
+				printf("[FAIL]\tCS mismatch: requested 0x%hx; got 0x%hx\n",
+				       req_sels->cs, res_sels->cs);
+				nerrs++;
+			}
+
+			if (req_sels->ss != res_sels->ss) {
+				printf("[FAIL]\tSS mismatch: requested 0x%hx; got 0x%hx\n",
+				       req_sels->ss, res_sels->ss);
+				nerrs++;
+			}
+
+			continue;
+		}
+#endif
+
+		/* Sanity check on the kernel */
+		if (i == REG_AX && requested_regs[i] != resulting_regs[i]) {
+			printf("[FAIL]\tAX (saved SP) mismatch: requested 0x%llx; got 0x%llx\n",
+			       (unsigned long long)requested_regs[i],
+			       (unsigned long long)resulting_regs[i]);
+			nerrs++;
+			continue;
+		}
+
+		if (requested_regs[i] != resulting_regs[i] && !ignore_reg) {
+			printf("[FAIL]\tReg %d mismatch: requested 0x%llx; got 0x%llx\n",
+			       i, (unsigned long long)requested_regs[i],
+			       (unsigned long long)resulting_regs[i]);
+			nerrs++;
+		}
+	}
+
+	if (nerrs == 0)
+		printf("[OK]\tall registers okay\n");
+
+	return nerrs;
+}
+
+static int test_bad_iret(int cs_bits, unsigned short ss, int force_cs)
+{
+	int cs = force_cs == -1 ? find_cs(cs_bits) : force_cs;
+	if (cs == -1)
+		return 0;
+
+	sig_cs = cs;
+	sig_ss = ss;
+
+	printf("[RUN]\t%d-bit CS (%hx), bogus SS (%hx)\n",
+	       cs_bits, sig_cs, sig_ss);
+
+	sig_trapped = 0;
+	raise(SIGUSR1);
+	if (sig_trapped) {
+		char errdesc[32] = "";
+		if (sig_err) {
+			const char *src = (sig_err & 1) ? " EXT" : "";
+			const char *table;
+			if ((sig_err & 0x6) == 0x0)
+				table = "GDT";
+			else if ((sig_err & 0x6) == 0x4)
+				table = "LDT";
+			else if ((sig_err & 0x6) == 0x2)
+				table = "IDT";
+			else
+				table = "???";
+
+			sprintf(errdesc, "%s%s index %d, ",
+				table, src, sig_err >> 3);
+		}
+
+		char trapname[32];
+		if (sig_trapno == 13)
+			strcpy(trapname, "GP");
+		else if (sig_trapno == 11)
+			strcpy(trapname, "NP");
+		else if (sig_trapno == 12)
+			strcpy(trapname, "SS");
+		else if (sig_trapno == 32)
+			strcpy(trapname, "IRET");  /* X86_TRAP_IRET */
+		else
+			sprintf(trapname, "%d", sig_trapno);
+
+		printf("[OK]\tGot #%s(0x%lx) (i.e. %s%s)\n",
+		       trapname, (unsigned long)sig_err,
+		       errdesc, strsignal(sig_trapped));
+		return 0;
+	} else {
+		printf("[FAIL]\tDid not get SIGSEGV\n");
+		return 1;
+	}
+}
+
+int main(void)
+{
+	int total_nerrs = 0;
+	unsigned short my_cs, my_ss;
+
+#ifdef __x86_64__
+	printf("[WARN]\t***** The 64-bit version requires a special kernel. *****\n");
+	printf("[WARN]\t***** Build with -m32. *****\n");
+	usleep(1000000);
+#endif
+
+	asm volatile ("mov %%cs,%0" : "=r" (my_cs));
+	asm volatile ("mov %%ss,%0" : "=r" (my_ss));
+	setup_ldt();
+
+	stack_t stack = {
+		.ss_sp = altstack_data,
+		.ss_size = SIGSTKSZ,
+	};
+	if (sigaltstack(&stack, NULL) != 0)
+		err(1, "sigaltstack");
+
+	sethandler(SIGUSR1, sigusr1, 0);
+	sethandler(SIGTRAP, sigtrap, SA_ONSTACK);
+
+	total_nerrs += do_test(64, false, -1);
+	total_nerrs += do_test(32, false, -1);
+	total_nerrs += do_test(16, false, -1);
+	total_nerrs += do_test(64, true, -1);
+	total_nerrs += do_test(32, true, -1);
+	total_nerrs += do_test(16, true, -1);
+
+	if (gdt_data16_idx) {
+		total_nerrs += do_test(64, true, (gdt_data16_idx << 3) | 3);
+		total_nerrs += do_test(32, true, (gdt_data16_idx << 3) | 3);
+		total_nerrs += do_test(16, true, (gdt_data16_idx << 3) | 3);
+	}
+
+	clearhandler(SIGTRAP);
+	sethandler(SIGSEGV, sigtrap, SA_ONSTACK);
+	sethandler(SIGBUS, sigtrap, SA_ONSTACK);
+	sethandler(SIGILL, sigtrap, SA_ONSTACK);  /* 32-bit kernels do this */
+
+	test_bad_iret(64, (2 << 3) | 7, -1);
+	test_bad_iret(32, (2 << 3) | 7, -1);
+	test_bad_iret(16, (2 << 3) | 7, -1);
+
+	test_bad_iret(64, my_cs, -1);
+	test_bad_iret(32, my_cs, -1);
+	test_bad_iret(16, my_cs, -1);
+
+	/* IRET will fail with #NP */
+	test_bad_iret(32, my_ss, (3 << 3) | 7);
+
+	/* IRET will fail with #SS on the espfix stack */
+	test_bad_iret(32, (4 << 3) | 7, -1);
+
+	/* IRET will fail with #SS on the normal stack */
+	if (gdt_npdata32_idx)
+		test_bad_iret(32, (gdt_npdata32_idx << 3) | 3, -1);
+
+	return total_nerrs ? 1 : 0;
+}
-- 
2.1.0


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

* Re: [PATCH v2] x86, selftests: Add sigreturn_32 selftest
  2015-03-09 16:36 [PATCH v2] x86, selftests: Add sigreturn_32 selftest Andy Lutomirski
@ 2015-03-09 16:48 ` Ingo Molnar
  2015-03-09 17:48   ` Andy Lutomirski
  0 siblings, 1 reply; 6+ messages in thread
From: Ingo Molnar @ 2015-03-09 16:48 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: x86, linux-kernel, Steven Rostedt, Denys Vlasenko, Shuah Khan,
	Borislav Petkov


now I get this build failure:

make[1]: Entering directory 
'/home/mingo/tip/tools/testing/selftests/x86'
gcc -m32 -o sigreturn_32 -O2 -g -std=gnu99 -pthread -Wall  sigreturn.c -lrt -ldl
In file included from /usr/include/time.h:27:0,
                 from sigreturn.c:13:
/usr/include/features.h:374:25: fatal error: sys/cdefs.h: No such file or directory
 #  include <sys/cdefs.h>
                         ^
compilation terminated.
Makefile:18: recipe for target 'sigreturn_32' failed
make[1]: *** [sigreturn_32] Error 1

:-/

Thanks,

	Ingo

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

* Re: [PATCH v2] x86, selftests: Add sigreturn_32 selftest
  2015-03-09 16:48 ` Ingo Molnar
@ 2015-03-09 17:48   ` Andy Lutomirski
  2015-03-10  4:57     ` Ingo Molnar
  0 siblings, 1 reply; 6+ messages in thread
From: Andy Lutomirski @ 2015-03-09 17:48 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: X86 ML, linux-kernel, Steven Rostedt, Denys Vlasenko, Shuah Khan,
	Borislav Petkov

On Mon, Mar 9, 2015 at 9:48 AM, Ingo Molnar <mingo@kernel.org> wrote:
>
> now I get this build failure:
>
> make[1]: Entering directory
> '/home/mingo/tip/tools/testing/selftests/x86'
> gcc -m32 -o sigreturn_32 -O2 -g -std=gnu99 -pthread -Wall  sigreturn.c -lrt -ldl
> In file included from /usr/include/time.h:27:0,
>                  from sigreturn.c:13:
> /usr/include/features.h:374:25: fatal error: sys/cdefs.h: No such file or directory
>  #  include <sys/cdefs.h>
>                          ^
> compilation terminated.
> Makefile:18: recipe for target 'sigreturn_32' failed
> make[1]: *** [sigreturn_32] Error 1

It builds for me on Ubuntu.

It looks like your 32-bit build setup is broken.  The line that's
failing to compile is:

#include <time.h>

Are you missing 32-bit headers?  This test *can't* be run as a 64-bit binary.

We could enable it to work as a 64-bit binary by merging this:

http://lkml.iu.edu/hypermail/linux/kernel/1407.1/03739.html

but it would still be nice to build the 32-bit version.  I could try
to rig up some makefile magic to skip building it if 32-bit headers
are missing.

--Andy

>
> :-/
>
> Thanks,
>
>         Ingo



-- 
Andy Lutomirski
AMA Capital Management, LLC

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

* Re: [PATCH v2] x86, selftests: Add sigreturn_32 selftest
  2015-03-09 17:48   ` Andy Lutomirski
@ 2015-03-10  4:57     ` Ingo Molnar
  2015-03-10 13:17       ` Andy Lutomirski
  0 siblings, 1 reply; 6+ messages in thread
From: Ingo Molnar @ 2015-03-10  4:57 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: X86 ML, linux-kernel, Steven Rostedt, Denys Vlasenko, Shuah Khan,
	Borislav Petkov


* Andy Lutomirski <luto@amacapital.net> wrote:

> On Mon, Mar 9, 2015 at 9:48 AM, Ingo Molnar <mingo@kernel.org> wrote:
> >
> > now I get this build failure:
> >
> > make[1]: Entering directory
> > '/home/mingo/tip/tools/testing/selftests/x86'
> > gcc -m32 -o sigreturn_32 -O2 -g -std=gnu99 -pthread -Wall  sigreturn.c -lrt -ldl
> > In file included from /usr/include/time.h:27:0,
> >                  from sigreturn.c:13:
> > /usr/include/features.h:374:25: fatal error: sys/cdefs.h: No such file or directory
> >  #  include <sys/cdefs.h>
> >                          ^
> > compilation terminated.
> > Makefile:18: recipe for target 'sigreturn_32' failed
> > make[1]: *** [sigreturn_32] Error 1
> 
> It builds for me on Ubuntu.
> 
> It looks like your 32-bit build setup is broken.  The line that's
> failing to compile is:
> 
> #include <time.h>
> 
> Are you missing 32-bit headers?  This test *can't* be run as a 64-bit binary.

Yeah, was a relatively fresh testbox, the magic incantation to get it 
to build there was:

  apt-get install gcc-multilib libc6-i386 libc6-dev-i386

On Fedora it's:

  yum install glibc-devel.*i686

Might make sense to include that in a README or so.

Thanks,

	Ingo

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

* Re: [PATCH v2] x86, selftests: Add sigreturn_32 selftest
  2015-03-10  4:57     ` Ingo Molnar
@ 2015-03-10 13:17       ` Andy Lutomirski
  2015-03-10 13:55         ` Ingo Molnar
  0 siblings, 1 reply; 6+ messages in thread
From: Andy Lutomirski @ 2015-03-10 13:17 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: X86 ML, linux-kernel, Steven Rostedt, Denys Vlasenko, Shuah Khan,
	Borislav Petkov

On Mon, Mar 9, 2015 at 9:57 PM, Ingo Molnar <mingo@kernel.org> wrote:
>
> * Andy Lutomirski <luto@amacapital.net> wrote:
>
>> On Mon, Mar 9, 2015 at 9:48 AM, Ingo Molnar <mingo@kernel.org> wrote:
>> >
>> > now I get this build failure:
>> >
>> > make[1]: Entering directory
>> > '/home/mingo/tip/tools/testing/selftests/x86'
>> > gcc -m32 -o sigreturn_32 -O2 -g -std=gnu99 -pthread -Wall  sigreturn.c -lrt -ldl
>> > In file included from /usr/include/time.h:27:0,
>> >                  from sigreturn.c:13:
>> > /usr/include/features.h:374:25: fatal error: sys/cdefs.h: No such file or directory
>> >  #  include <sys/cdefs.h>
>> >                          ^
>> > compilation terminated.
>> > Makefile:18: recipe for target 'sigreturn_32' failed
>> > make[1]: *** [sigreturn_32] Error 1
>>
>> It builds for me on Ubuntu.
>>
>> It looks like your 32-bit build setup is broken.  The line that's
>> failing to compile is:
>>
>> #include <time.h>
>>
>> Are you missing 32-bit headers?  This test *can't* be run as a 64-bit binary.
>
> Yeah, was a relatively fresh testbox, the magic incantation to get it
> to build there was:
>
>   apt-get install gcc-multilib libc6-i386 libc6-dev-i386
>
> On Fedora it's:
>
>   yum install glibc-devel.*i686
>
> Might make sense to include that in a README or so.

I could rig up the makefile to give that hint.

Should we just say that selftests/x86 won't work if you can't build
32-bit binaries, or should we try to degrade more gracefully?

--Andy

>
> Thanks,
>
>         Ingo



-- 
Andy Lutomirski
AMA Capital Management, LLC

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

* Re: [PATCH v2] x86, selftests: Add sigreturn_32 selftest
  2015-03-10 13:17       ` Andy Lutomirski
@ 2015-03-10 13:55         ` Ingo Molnar
  0 siblings, 0 replies; 6+ messages in thread
From: Ingo Molnar @ 2015-03-10 13:55 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: X86 ML, linux-kernel, Steven Rostedt, Denys Vlasenko, Shuah Khan,
	Borislav Petkov


* Andy Lutomirski <luto@amacapital.net> wrote:

> On Mon, Mar 9, 2015 at 9:57 PM, Ingo Molnar <mingo@kernel.org> wrote:
> >
> > * Andy Lutomirski <luto@amacapital.net> wrote:
> >
> >> On Mon, Mar 9, 2015 at 9:48 AM, Ingo Molnar <mingo@kernel.org> wrote:
> >> >
> >> > now I get this build failure:
> >> >
> >> > make[1]: Entering directory
> >> > '/home/mingo/tip/tools/testing/selftests/x86'
> >> > gcc -m32 -o sigreturn_32 -O2 -g -std=gnu99 -pthread -Wall  sigreturn.c -lrt -ldl
> >> > In file included from /usr/include/time.h:27:0,
> >> >                  from sigreturn.c:13:
> >> > /usr/include/features.h:374:25: fatal error: sys/cdefs.h: No such file or directory
> >> >  #  include <sys/cdefs.h>
> >> >                          ^
> >> > compilation terminated.
> >> > Makefile:18: recipe for target 'sigreturn_32' failed
> >> > make[1]: *** [sigreturn_32] Error 1
> >>
> >> It builds for me on Ubuntu.
> >>
> >> It looks like your 32-bit build setup is broken.  The line that's
> >> failing to compile is:
> >>
> >> #include <time.h>
> >>
> >> Are you missing 32-bit headers?  This test *can't* be run as a 64-bit binary.
> >
> > Yeah, was a relatively fresh testbox, the magic incantation to get it
> > to build there was:
> >
> >   apt-get install gcc-multilib libc6-i386 libc6-dev-i386
> >
> > On Fedora it's:
> >
> >   yum install glibc-devel.*i686
> >
> > Might make sense to include that in a README or so.
> 
> I could rig up the makefile to give that hint.
> 
> Should we just say that selftests/x86 won't work if you can't build 
> 32-bit binaries, or should we try to degrade more gracefully?

I'd suggest to keep it simple: just make it easy for people to 
discover how to build it properly.

Thanks,

	Ingo

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

end of thread, other threads:[~2015-03-10 13:55 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-09 16:36 [PATCH v2] x86, selftests: Add sigreturn_32 selftest Andy Lutomirski
2015-03-09 16:48 ` Ingo Molnar
2015-03-09 17:48   ` Andy Lutomirski
2015-03-10  4:57     ` Ingo Molnar
2015-03-10 13:17       ` Andy Lutomirski
2015-03-10 13:55         ` Ingo Molnar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).