[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 0/6] x86/debug: fix guest dr6 value for single stepping and HW breakpoints
Xen has a bug where hardware breakpoint exceptions (DR_TRAP<n>) are erroneously recognized as single-stepping exceptions (DR_STEP). This interferes with userland debugging and allows (otherwise restricted) usermode programs to detect Xen HVM (or PVH). This patch series aim to fix this. The last patch is optional and finishes incomplete plumbing work initiated by commit 21867648033d (x86/debug: Plumb pending_dbg through the monitor and devicemodel interfaces, 2018-05-31). The following Linux x86-64 program demonstrates the bug: --- (snip) --- #include <stddef.h> #include <stdlib.h> #include <assert.h> #include <unistd.h> #include <signal.h> #include <sys/ptrace.h> #include <sys/wait.h> #include <sys/user.h> #include <stdio.h> #define ABORT_ON_ERR(x) if ((x) == -1) abort(); int main(void) { unsigned long cur_rip, cur_eflags, cur_dr6; int wstatus, exit_code; pid_t pid; ABORT_ON_ERR(pid = fork()); if (pid == 0) { ABORT_ON_ERR(ptrace(PTRACE_TRACEME, 0, NULL, NULL)); ABORT_ON_ERR(raise(SIGSTOP)); _exit(0); } /* Wait for first ptrace event */ if (waitpid(pid, &wstatus, 0) != pid) abort(); if (!WIFSTOPPED(wstatus)) abort(); /* Obtain current RIP value and perform sanity check */ cur_rip = ptrace(PTRACE_PEEKUSER, pid, (void *)offsetof(struct user, regs.rip), &cur_rip); cur_dr6 = ptrace(PTRACE_PEEKUSER, pid, (void *)offsetof(struct user, u_debugreg[6]), &cur_dr6); assert(cur_dr6 == 0xffff0ff0UL); /* Set up debug registers and set EFLAGS.TF */ cur_eflags = ptrace(PTRACE_PEEKUSER, pid, (void *)offsetof(struct user, regs.eflags), &cur_eflags); ABORT_ON_ERR(ptrace(PTRACE_POKEUSER, pid, (void *)offsetof(struct user, regs.eflags), (void *)(cur_eflags | 0x100UL))); ABORT_ON_ERR(ptrace(PTRACE_POKEUSER, pid, (void *)offsetof(struct user, u_debugreg[0]), (void *)cur_rip)); ABORT_ON_ERR(ptrace(PTRACE_POKEUSER, pid, (void *)offsetof(struct user, u_debugreg[7]), (void *)1L)); /* Continue execution to trigger hardware breakpoint */ ABORT_ON_ERR(ptrace(PTRACE_CONT, pid, NULL, (unsigned long)0)); if (waitpid(pid, &wstatus, 0) != pid) abort(); if (!(WIFSTOPPED(wstatus) && WSTOPSIG(wstatus) == SIGTRAP)) abort(); /* Detect if Xen has tampered with DR6 */ cur_dr6 = ptrace(PTRACE_PEEKUSER, pid, (void *)offsetof(struct user, u_debugreg[6]), &cur_dr6); fprintf(stderr, "DR6 = 0x%08lx\n", cur_dr6); if (cur_dr6 == 0xffff0ff1UL) { fputs("Running on bare-metal, Xen PV, or non-Xen VMM\n", stdout); exit_code = EXIT_FAILURE; } else { fputs("Running on Xen HVM\n", stdout); exit_code = EXIT_SUCCESS; } /* Tear down debug registers and unset EFLAGS.TF */ cur_eflags = ptrace(PTRACE_PEEKUSER, pid, (void *)offsetof(struct user, regs.eflags), &cur_eflags); ABORT_ON_ERR(ptrace(PTRACE_POKEUSER, pid, (void *)offsetof(struct user, regs.eflags), (void *)(cur_eflags & ~0x100UL))); ABORT_ON_ERR(ptrace(PTRACE_POKEUSER, pid, (void *)offsetof(struct user, u_debugreg[7]), (void *)0L)); /* Continue execution to let child process exit */ ABORT_ON_ERR(ptrace(PTRACE_CONT, pid, NULL, (unsigned long)0)); if (waitpid(pid, &wstatus, 0) != pid) abort(); if (!(WIFEXITED(wstatus) && WEXITSTATUS(wstatus) == 0)) abort(); return exit_code; } --- (snip) --- Jinoh Kang (6): x86/hvm: only populate info->cr2 for #PF in hvm_get_pending_event() x86emul: rename field 'cr2' of struct x86_event to 'extra' x86: don't assume #DB is always caused by singlestep if EFLAGS.TF is set x86/pv: set DR_STEP if single-stepping after ro page fault emulation x86/pv: factor out single-step debug trap injection x86/debug: actually plumb pending_dbg through the monitor and devicemodel interfaces xen/arch/x86/hvm/dm.c | 2 +- xen/arch/x86/hvm/emulate.c | 3 +- xen/arch/x86/hvm/hvm.c | 11 ++++-- xen/arch/x86/hvm/svm/nestedsvm.c | 2 +- xen/arch/x86/hvm/svm/svm.c | 48 ++++++++++++++++++++------ xen/arch/x86/hvm/vmx/vmx.c | 40 ++++++++++++++------- xen/arch/x86/include/asm/domain.h | 14 +++++++- xen/arch/x86/include/asm/hvm/hvm.h | 14 +++++++- xen/arch/x86/mm/shadow/multi.c | 5 +-- xen/arch/x86/pv/emulate.c | 5 +-- xen/arch/x86/pv/ro-page-fault.c | 3 +- xen/arch/x86/pv/traps.c | 18 +++++++--- xen/arch/x86/x86_emulate/x86_emulate.h | 6 ++-- 13 files changed, 128 insertions(+), 43 deletions(-) -- 2.41.0
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |