summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@kernel.org>2015-04-17 14:07:02 -0700
committerAndy Lutomirski <luto@kernel.org>2015-04-17 14:16:00 -0700
commit8620bdbb677df38eb93494cff46cd7179dec0a21 (patch)
treec56e30c5680fde56fc4cbc356ca22fb3454ff2f8
parentf67708ab5f6432af863b3fa3f405bd120c492fb7 (diff)
downloadmisc-tests-8620bdbb677df38eb93494cff46cd7179dec0a21.tar.gz
Remove sigreturn and single_step_syscall
They live in the kernel tree now, in tools/testing/selftests/x86/ Signed-off-by: Andy Lutomirski <luto@kernel.org>
-rw-r--r--Makefile2
-rw-r--r--sigreturn.c532
-rw-r--r--single_step_syscall.c133
3 files changed, 1 insertions, 666 deletions
diff --git a/Makefile b/Makefile
index 5896c92..6dfce9e 100644
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@ SIMPLE_C_TARGETS := dump-vsyscall context_switch_latency kernel_pf user_visible_
SIMPLE_CC_TARGETS := evil-clock-test
-SPLIT_C_TARGETS := dump-vdso dump-vvar syscall_exit_regs sigreturn dump_all_pmcs single_step_syscall
+SPLIT_C_TARGETS := dump-vdso dump-vvar syscall_exit_regs dump_all_pmcs
SPLIT_CC_TARGETS := timing_test test_vsyscall test_vdso_parser
ALL_TARGETS := $(SIMPLE_C_TARGETS) $(SIMPLE_CC_TARGETS) $(SPLIT_C_TARGETS:%=%_64) $(SPLIT_CC_TARGETS:%=%_64) $(SPLIT_C_TARGETS:%=%_32) $(SPLIT_CC_TARGETS:%=%_32) syscall32_from_64 segregs
diff --git a/sigreturn.c b/sigreturn.c
deleted file mode 100644
index 5c8cace..0000000
--- a/sigreturn.c
+++ /dev/null
@@ -1,532 +0,0 @@
-#define _GNU_SOURCE
-
-#include <sys/time.h>
-#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/ptrace.h>
-#include <sys/user.h>
-
-#define LDT_OFFSET 6 /* Solaris reserves LDT entries 0-5 for internal use. */
-
-struct selectors {
- unsigned short cs, gs, fs, ss;
-};
-
-static unsigned short ldt_nonexistent_sel;
-static unsigned short code16_sel, data16_sel, npcode32_sel, npdata32_sel;
-
-static unsigned short gdt_data16_idx, gdt_npdata32_idx;
-
-static unsigned short LDT3(int idx)
-{
- return (idx << 3) | 7;
-}
-
-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, unsigned short *var,
- const char *name)
-{
- if (syscall(SYS_modify_ldt, 1, desc, sizeof(*desc)) == 0) {
- *var = LDT3(desc->entry_number);
- } else {
- printf("[NOTE]\tFailed to create %s segment\n", name);
- *var = 0;
- }
-}
-
-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");
-
- ldt_nonexistent_sel = LDT3(LDT_OFFSET + 2);
-
- const struct user_desc code16_desc = {
- .entry_number = LDT_OFFSET + 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, &code16_sel, "code16");
-
- const struct user_desc data16_desc = {
- .entry_number = LDT_OFFSET + 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, &data16_sel, "data16");
-
- const struct user_desc npcode32_desc = {
- .entry_number = LDT_OFFSET + 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, &npcode32_sel, "npcode32");
-
- const struct user_desc npdata32_desc = {
- .entry_number = LDT_OFFSET + 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, &npdata32_sel, "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;
-
-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 == code16_sel ? 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(code16_sel) == bitness)
- return code16_sel;
-
- 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 (!data16_sel) {
- printf("[SKIP]\tData segment unavailable for %d-bit CS, 16-bit SS\n",
- cs_bits);
- return 0;
- }
- sig_ss = data16_sel;
- } 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()
-{
- 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, ldt_nonexistent_sel, -1);
- test_bad_iret(32, ldt_nonexistent_sel, -1);
- test_bad_iret(16, ldt_nonexistent_sel, -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, npcode32_sel);
-
- /*
- * IRET will fail with #SS on the espfix stack
- * Note that, if espfix is enabled, Linux will lose track of
- * the actual cause of failure and report #GP(0) instead.
- */
- test_bad_iret(32, npdata32_sel, -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;
-}
diff --git a/single_step_syscall.c b/single_step_syscall.c
deleted file mode 100644
index 6c42bd0..0000000
--- a/single_step_syscall.c
+++ /dev/null
@@ -1,133 +0,0 @@
-#define _GNU_SOURCE
-
-#include <sys/time.h>
-#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/ptrace.h>
-#include <sys/user.h>
-
-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 volatile sig_atomic_t sig_traps;
-
-#ifdef __x86_64__
-# define REG_IP REG_RIP
-# define WIDTH "q"
-#else
-# define REG_IP REG_EIP
-# define WIDTH "l"
-#endif
-
-static unsigned long get_eflags(void)
-{
- unsigned long eflags;
- asm volatile ("pushf" WIDTH "\n\tpop" WIDTH " %0" : "=rm" (eflags));
- return eflags;
-}
-
-static void set_eflags(unsigned long eflags)
-{
- asm volatile ("push" WIDTH " %0\n\tpopf" WIDTH
- : : "rm" (eflags) : "flags");
-}
-
-#define X86_EFLAGS_TF (1UL << 8)
-
-static void sigtrap(int sig, siginfo_t *info, void *ctx_void)
-{
- ucontext_t *ctx = (ucontext_t*)ctx_void;
-
- if (get_eflags() & X86_EFLAGS_TF) {
- set_eflags(get_eflags() & ~X86_EFLAGS_TF);
- printf("[WARN]\tSIGTRAP handler had TF set\n");
- _exit(1);
- }
-
- sig_traps++;
-
- if (sig_traps == 10000 || sig_traps == 10001) {
- printf("[WARN]\tHit %d SIGTRAPs with si_addr 0x%lx, ip 0x%lx\n",
- (int)sig_traps,
- (unsigned long)info->si_addr,
- (unsigned long)ctx->uc_mcontext.gregs[REG_IP]);
- }
-}
-
-static void check_result(void)
-{
- unsigned long new_eflags = get_eflags();
- set_eflags(new_eflags & ~X86_EFLAGS_TF);
-
- if (!sig_traps) {
- printf("[FAIL]\tNo SIGTRAP\n");
- exit(1);
- }
-
- if (!(new_eflags & X86_EFLAGS_TF)) {
- printf("[FAIL]\tTF was cleared\n");
- exit(1);
- }
-
- printf("[OK]\tSurvived with TF set and %d traps\n", (int)sig_traps);
- sig_traps = 0;
-}
-
-int main()
-{
- int tmp;
-
- sethandler(SIGTRAP, sigtrap, 0);
-
- printf("[RUN]\tSet TF and check nop\n");
- set_eflags(get_eflags() | X86_EFLAGS_TF);
- asm volatile ("nop");
- check_result();
-
-#ifdef __x86_64__
- printf("[RUN]\tSet TF and check syscall-less opportunistic sysret\n");
- set_eflags(get_eflags() | X86_EFLAGS_TF);
- extern unsigned char post_nop[];
- asm volatile ("pushf" WIDTH "\n\t"
- "pop" WIDTH " %%r11\n\t"
- "nop\n\t"
- "post_nop:"
- : : "c" (post_nop) : "r11");
- check_result();
-#endif
-
- printf("[RUN]\tSet TF and check int80\n");
- set_eflags(get_eflags() | X86_EFLAGS_TF);
- asm volatile ("int $0x80" : "=a" (tmp) : "a" (SYS_getpid));
- check_result();
-
- syscall(SYS_getpid); /* Force symbol binding without TF set. */
- printf("[RUN]\tSet TF and check a fast syscall\n");
- set_eflags(get_eflags() | X86_EFLAGS_TF);
- syscall(SYS_getpid);
- check_result();
-
- return 0;
-}