From c0ab059e7b904197f52ade879711d7fb02ffa8c0 Mon Sep 17 00:00:00 2001 From: Adin Scannell Date: Fri, 8 Jun 2018 17:50:55 -0700 Subject: Fix kernel flags handling and add missing vectors. PiperOrigin-RevId: 199877174 Change-Id: I9d19ea301608c2b989df0a6123abb1e779427853 --- pkg/sentry/platform/ring0/entry_amd64.s | 10 ++++++---- pkg/sentry/platform/ring0/kernel_amd64.go | 21 +++++---------------- pkg/sentry/platform/ring0/offsets_amd64.go | 3 ++- pkg/sentry/platform/ring0/x86.go | 15 +++++++++++++++ 4 files changed, 28 insertions(+), 21 deletions(-) (limited to 'pkg/sentry/platform/ring0') diff --git a/pkg/sentry/platform/ring0/entry_amd64.s b/pkg/sentry/platform/ring0/entry_amd64.s index e8638133b..08c15ad65 100644 --- a/pkg/sentry/platform/ring0/entry_amd64.s +++ b/pkg/sentry/platform/ring0/entry_amd64.s @@ -248,10 +248,12 @@ TEXT ·exception(SB),NOSPLIT,$0 user: SWAP_GS() - XCHGQ CPU_REGISTERS+PTRACE_RAX(GS), AX // Swap for AX (regs). - REGISTERS_SAVE(AX, 0) // Save all except IP, FLAGS, SP, AX. - MOVQ CPU_REGISTERS+PTRACE_RAX(GS), BX // Load saved AX value. - MOVQ BX, PTRACE_RAX(AX) // Save everything else. + ADDQ $-8, SP // Adjust for flags. + MOVQ $_KERNEL_FLAGS, 0(SP); BYTE $0x9d; // Reset flags (POPFQ). + XCHGQ CPU_REGISTERS+PTRACE_RAX(GS), AX // Swap for user regs. + REGISTERS_SAVE(AX, 0) // Save all except IP, FLAGS, SP, AX. + MOVQ CPU_REGISTERS+PTRACE_RAX(GS), BX // Restore original AX. + MOVQ BX, PTRACE_RAX(AX) // Save it. MOVQ BX, PTRACE_ORIGRAX(AX) MOVQ 16(SP), BX; MOVQ BX, PTRACE_RIP(AX) MOVQ 24(SP), CX; MOVQ CX, PTRACE_CS(AX) diff --git a/pkg/sentry/platform/ring0/kernel_amd64.go b/pkg/sentry/platform/ring0/kernel_amd64.go index 37d5484e1..c828af654 100644 --- a/pkg/sentry/platform/ring0/kernel_amd64.go +++ b/pkg/sentry/platform/ring0/kernel_amd64.go @@ -20,20 +20,6 @@ import ( "encoding/binary" ) -const ( - // KernelFlagsSet should always be set in the kernel. - KernelFlagsSet = _RFLAGS_RESERVED - - // UserFlagsSet are always set in userspace. - UserFlagsSet = _RFLAGS_RESERVED | _RFLAGS_IF - - // KernelFlagsClear should always be clear in the kernel. - KernelFlagsClear = _RFLAGS_IF | _RFLAGS_NT | _RFLAGS_IOPL - - // UserFlagsClear are always cleared in userspace. - UserFlagsClear = _RFLAGS_NT | _RFLAGS_IOPL -) - // init initializes architecture-specific state. func (k *Kernel) init(opts KernelOpts) { // Save the root page tables. @@ -85,6 +71,9 @@ func (c *CPU) init() { c.registers.Ss = uint64(Kdata) c.registers.Fs = uint64(Kdata) c.registers.Gs = uint64(Kdata) + + // Set mandatory flags. + c.registers.Eflags = KernelFlagsSet } // StackTop returns the kernel's stack address. @@ -119,7 +108,7 @@ func (c *CPU) TSS() (uint64, uint16, *SegmentDescriptor) { // //go:nosplit func (c *CPU) CR0() uint64 { - return _CR0_PE | _CR0_PG | _CR0_ET + return _CR0_PE | _CR0_PG | _CR0_AM | _CR0_ET } // CR4 returns the CPU's CR4 value. @@ -240,7 +229,7 @@ func start(c *CPU) { // Set the syscall target. wrmsr(_MSR_LSTAR, kernelFunc(sysenter)) - wrmsr(_MSR_SYSCALL_MASK, _RFLAGS_STEP|_RFLAGS_IF|_RFLAGS_DF|_RFLAGS_IOPL|_RFLAGS_AC|_RFLAGS_NT) + wrmsr(_MSR_SYSCALL_MASK, KernelFlagsClear|_RFLAGS_DF) // NOTE: This depends on having the 64-bit segments immediately // following the 32-bit user segments. This is simply the way the diff --git a/pkg/sentry/platform/ring0/offsets_amd64.go b/pkg/sentry/platform/ring0/offsets_amd64.go index 9acd442ba..ca5fd456b 100644 --- a/pkg/sentry/platform/ring0/offsets_amd64.go +++ b/pkg/sentry/platform/ring0/offsets_amd64.go @@ -38,7 +38,8 @@ func Emit(w io.Writer) { fmt.Fprintf(w, "#define CPU_KERNEL_SYSCALL 0x%02x\n", reflect.ValueOf(&c.KernelSyscall).Pointer()-reflect.ValueOf(c).Pointer()) fmt.Fprintf(w, "\n// Bits.\n") - fmt.Fprintf(w, "#define _RFLAGS_IF 0x%02x\n", _RFLAGS_IF) + fmt.Fprintf(w, "#define _RFLAGS_IF 0x%02x\n", _RFLAGS_IF) + fmt.Fprintf(w, "#define _KERNEL_FLAGS 0x%02x\n", KernelFlagsSet) fmt.Fprintf(w, "\n// Vectors.\n") fmt.Fprintf(w, "#define DivideByZero 0x%02x\n", DivideByZero) diff --git a/pkg/sentry/platform/ring0/x86.go b/pkg/sentry/platform/ring0/x86.go index 74b140066..3d437a77c 100644 --- a/pkg/sentry/platform/ring0/x86.go +++ b/pkg/sentry/platform/ring0/x86.go @@ -24,6 +24,7 @@ import ( const ( _CR0_PE = 1 << 0 _CR0_ET = 1 << 4 + _CR0_AM = 1 << 18 _CR0_PG = 1 << 31 _CR4_PSE = 1 << 4 @@ -55,6 +56,20 @@ const ( _MSR_SYSCALL_MASK = 0xc0000084 ) +const ( + // KernelFlagsSet should always be set in the kernel. + KernelFlagsSet = _RFLAGS_RESERVED + + // UserFlagsSet are always set in userspace. + UserFlagsSet = _RFLAGS_RESERVED | _RFLAGS_IF + + // KernelFlagsClear should always be clear in the kernel. + KernelFlagsClear = _RFLAGS_STEP | _RFLAGS_IF | _RFLAGS_IOPL | _RFLAGS_AC | _RFLAGS_NT + + // UserFlagsClear are always cleared in userspace. + UserFlagsClear = _RFLAGS_NT | _RFLAGS_IOPL +) + // Vector is an exception vector. type Vector uintptr -- cgit v1.2.3