Print this page
8956 Implement KPTI
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>

*** 30,40 **** /* Copyright (c) 1987, 1988 Microsoft Corporation */ /* All Rights Reserved */ /* */ /* ! * Copyright 2017 Joyent, Inc. */ #include <sys/types.h> #include <sys/sysmacros.h> #include <sys/param.h> --- 30,40 ---- /* Copyright (c) 1987, 1988 Microsoft Corporation */ /* All Rights Reserved */ /* */ /* ! * Copyright 2018 Joyent, Inc. */ #include <sys/types.h> #include <sys/sysmacros.h> #include <sys/param.h>
*** 478,488 **** int mstate; int sicode = 0; int watchcode; int watchpage; caddr_t vaddr; - int singlestep_twiddle; size_t sz; int ta; #ifdef __amd64 uchar_t instr; #endif --- 478,487 ----
*** 1089,1150 **** (void) die(type, rp, addr, cpuid); break; case T_SGLSTP: /* single step/hw breakpoint exception */ ! /* Now evaluate how we got here */ ! if (lwp != NULL && (lwp->lwp_pcb.pcb_drstat & DR_SINGLESTEP)) { /* ! * i386 single-steps even through lcalls which ! * change the privilege level. So we take a trap at ! * the first instruction in privileged mode. ! * ! * Set a flag to indicate that upon completion of ! * the system call, deal with the single-step trap. ! * ! * The same thing happens for sysenter, too. */ ! singlestep_twiddle = 0; ! if (rp->r_pc == (uintptr_t)sys_sysenter || ! rp->r_pc == (uintptr_t)brand_sys_sysenter) { ! singlestep_twiddle = 1; ! #if defined(__amd64) ! /* ! * Since we are already on the kernel's ! * %gs, on 64-bit systems the sysenter case ! * needs to adjust the pc to avoid ! * executing the swapgs instruction at the ! * top of the handler. ! */ ! if (rp->r_pc == (uintptr_t)sys_sysenter) ! rp->r_pc = (uintptr_t) ! _sys_sysenter_post_swapgs; ! else ! rp->r_pc = (uintptr_t) ! _brand_sys_sysenter_post_swapgs; ! #endif ! } ! #if defined(__i386) ! else if (rp->r_pc == (uintptr_t)sys_call || ! rp->r_pc == (uintptr_t)brand_sys_call) { ! singlestep_twiddle = 1; ! } ! #endif ! else { ! /* not on sysenter/syscall; uregs available */ ! if (tudebug && tudebugbpt) ! showregs(type, rp, (caddr_t)0); ! } ! if (singlestep_twiddle) { rp->r_ps &= ~PS_T; /* turn off trace */ lwp->lwp_pcb.pcb_flags |= DEBUG_PENDING; ct->t_post_sys = 1; aston(curthread); goto cleanup; } } ! /* XXX - needs review on debugger interface? */ if (boothowto & RB_DEBUG) debug_enter((char *)NULL); else (void) die(type, rp, addr, cpuid); break; --- 1088,1126 ---- (void) die(type, rp, addr, cpuid); break; case T_SGLSTP: /* single step/hw breakpoint exception */ ! #if !defined(__xpv) /* ! * We'd never normally get here, as kmdb handles its own single ! * step traps. There is one nasty exception though, as ! * described in more detail in sys_sysenter(). Note that ! * checking for all four locations covers both the KPTI and the ! * non-KPTI cases correctly: the former will never be found at ! * (brand_)sys_sysenter, and vice versa. */ ! if (lwp != NULL && (lwp->lwp_pcb.pcb_drstat & DR_SINGLESTEP)) { ! if (rp->r_pc == (greg_t)brand_sys_sysenter || ! rp->r_pc == (greg_t)sys_sysenter || ! rp->r_pc == (greg_t)tr_brand_sys_sysenter || ! rp->r_pc == (greg_t)tr_sys_sysenter) { ! ! rp->r_pc += 0x3; /* sizeof (swapgs) */ ! rp->r_ps &= ~PS_T; /* turn off trace */ lwp->lwp_pcb.pcb_flags |= DEBUG_PENDING; ct->t_post_sys = 1; aston(curthread); goto cleanup; + } else { + if (tudebug && tudebugbpt) + showregs(type, rp, (caddr_t)0); } } ! #endif /* !__xpv */ ! if (boothowto & RB_DEBUG) debug_enter((char *)NULL); else (void) die(type, rp, addr, cpuid); break;
*** 1736,1748 **** #else printf("cr0: %b cr4: %b\n", (uint_t)getcr0(), FMT_CR0, (uint_t)getcr4(), FMT_CR4); #endif /* __lint */ ! printf("cr2: %lx", getcr2()); #if !defined(__xpv) ! printf("cr3: %lx", getcr3()); #if defined(__amd64) printf("cr8: %lx\n", getcr8()); #endif #endif printf("\n"); --- 1712,1724 ---- #else printf("cr0: %b cr4: %b\n", (uint_t)getcr0(), FMT_CR0, (uint_t)getcr4(), FMT_CR4); #endif /* __lint */ ! printf("cr2: %lx ", getcr2()); #if !defined(__xpv) ! printf("cr3: %lx ", getcr3()); #if defined(__amd64) printf("cr8: %lx\n", getcr8()); #endif #endif printf("\n");
*** 1844,1854 **** } #endif /* __i386 */ /* ! * Test to see if the instruction is part of _sys_rtt. * * Again on the hypervisor if we try to IRET to user land with a bad code * or stack selector we will get vectored through xen_failsafe_callback. * In which case we assume we got here via _sys_rtt since we only allow * IRET to user land to take place in _sys_rtt. --- 1820,1831 ---- } #endif /* __i386 */ /* ! * Test to see if the instruction is part of _sys_rtt (or the KPTI trampolines ! * which are used by _sys_rtt). * * Again on the hypervisor if we try to IRET to user land with a bad code * or stack selector we will get vectored through xen_failsafe_callback. * In which case we assume we got here via _sys_rtt since we only allow * IRET to user land to take place in _sys_rtt.
*** 1856,1865 **** --- 1833,1855 ---- static int instr_is_sys_rtt(caddr_t pc) { extern void _sys_rtt(), _sys_rtt_end(); + #if !defined(__xpv) + extern void tr_sysc_ret_start(), tr_sysc_ret_end(); + extern void tr_intr_ret_start(), tr_intr_ret_end(); + + if ((uintptr_t)pc >= (uintptr_t)tr_sysc_ret_start && + (uintptr_t)pc <= (uintptr_t)tr_sysc_ret_end) + return (1); + + if ((uintptr_t)pc >= (uintptr_t)tr_intr_ret_start && + (uintptr_t)pc <= (uintptr_t)tr_intr_ret_end) + return (1); + #endif + if ((uintptr_t)pc < (uintptr_t)_sys_rtt || (uintptr_t)pc > (uintptr_t)_sys_rtt_end) return (0); return (1);