/* * vm86 regs test. * Copyright (c) 2014-2015 Andrew Lutomirski. * * This tests that vm86 regs work as expected. * * GPL v2. */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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 sigsegv_vm86(int sig, siginfo_t *info, void *ctx_void) { ucontext_t *ctx = (ucontext_t*)ctx_void; printf("Back from vm86. EIP = %lx\n", (unsigned long)ctx->uc_mcontext.gregs[REG_EIP]); } static void test_vm86(unsigned short cs, unsigned short ss) { struct vm86plus_struct v86, req_v86; long ret; memset(&v86, 0, sizeof(v86)); v86.regs.eip = 0; v86.regs.cs = cs; v86.regs.ss = ss; v86.regs.esp = 0xbaadf00d; req_v86 = v86; printf("[RUN]\tcs = 0x%hx, ss = 0x%hx\n", cs, ss); ret = syscall(SYS_vm86, VM86_ENTER, &v86); if (ret == -1 && errno == ENOSYS) { printf("[SKIP]\tvm86 not supported\n"); return; } printf("[OK]\tSurvived vm86 roundtrip. esp = %lx, should be %lx\n", v86.regs.esp, req_v86.regs.esp); } int main(void) { sethandler(SIGSEGV, sigsegv_vm86, SA_ONSTACK); test_vm86(0, 0); test_vm86(0, 3); test_vm86(3, 0); test_vm86(3, 3); return 0; }