diff options
author | Adin Scannell <ascannell@google.com> | 2018-06-11 17:56:18 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2018-06-11 17:57:19 -0700 |
commit | 09b0a9c320bd777bc52384bd0ec91ecfc61e481d (patch) | |
tree | 6a8370138e46b1439412a8707d103c40eedab86c /pkg/sentry | |
parent | ea4a468fbaacd55597ce89e3eabd2bb42746427b (diff) |
Handle all exception vectors.
PiperOrigin-RevId: 200144655
Change-Id: I5a753c74b75007b7714d6fe34aa0d2e845dc5c41
Diffstat (limited to 'pkg/sentry')
-rw-r--r-- | pkg/sentry/platform/kvm/machine_amd64.go | 48 | ||||
-rw-r--r-- | pkg/sentry/platform/ring0/kernel_amd64.go | 9 |
2 files changed, 49 insertions, 8 deletions
diff --git a/pkg/sentry/platform/kvm/machine_amd64.go b/pkg/sentry/platform/kvm/machine_amd64.go index 7ac289756..52896eefe 100644 --- a/pkg/sentry/platform/kvm/machine_amd64.go +++ b/pkg/sentry/platform/kvm/machine_amd64.go @@ -137,6 +137,18 @@ func (c *vCPU) initArchState() error { return c.setSystemTime() } +// nonCanonical generates a canonical address return. +// +//go:nosplit +func nonCanonical(addr uint64, signal int32) (*arch.SignalInfo, usermem.AccessType, error) { + info := &arch.SignalInfo{ + Signo: signal, + Code: arch.SignalInfoKernel, + } + info.SetAddr(addr) // Include address. + return info, usermem.NoAccess, platform.ErrContextSignal +} + // fault generates an appropriate fault return. // //go:nosplit @@ -169,6 +181,17 @@ func (c *vCPU) fault(signal int32) (*arch.SignalInfo, usermem.AccessType, error) // SwitchToUser unpacks architectural-details. func (c *vCPU) SwitchToUser(switchOpts ring0.SwitchOpts) (*arch.SignalInfo, usermem.AccessType, error) { + // Check for canonical addresses. + if regs := switchOpts.Registers; !ring0.IsCanonical(regs.Rip) { + return nonCanonical(regs.Rip, int32(syscall.SIGSEGV)) + } else if !ring0.IsCanonical(regs.Rsp) { + return nonCanonical(regs.Rsp, int32(syscall.SIGBUS)) + } else if !ring0.IsCanonical(regs.Fs_base) { + return nonCanonical(regs.Fs_base, int32(syscall.SIGBUS)) + } else if !ring0.IsCanonical(regs.Gs_base) { + return nonCanonical(regs.Gs_base, int32(syscall.SIGBUS)) + } + // Assign PCIDs. if c.PCIDs != nil { var requireFlushPCID bool // Force a flush? @@ -205,7 +228,11 @@ func (c *vCPU) SwitchToUser(switchOpts ring0.SwitchOpts) (*arch.SignalInfo, user info.SetAddr(switchOpts.Registers.Rip) // Include address. return info, usermem.AccessType{}, platform.ErrContextSignal - case ring0.GeneralProtectionFault: + case ring0.GeneralProtectionFault, + ring0.SegmentNotPresent, + ring0.BoundRangeExceeded, + ring0.InvalidTSS, + ring0.StackSegmentFault: info := &arch.SignalInfo{ Signo: int32(syscall.SIGSEGV), Code: arch.SignalInfoKernel, @@ -229,7 +256,16 @@ func (c *vCPU) SwitchToUser(switchOpts ring0.SwitchOpts) (*arch.SignalInfo, user info.SetAddr(switchOpts.Registers.Rip) // Include address. return info, usermem.AccessType{}, platform.ErrContextSignal - case ring0.X87FloatingPointException: + case ring0.Overflow: + info := &arch.SignalInfo{ + Signo: int32(syscall.SIGFPE), + Code: 1, // FPE_INTOVF (integer overflow). + } + info.SetAddr(switchOpts.Registers.Rip) // Include address. + return info, usermem.AccessType{}, platform.ErrContextSignal + + case ring0.X87FloatingPointException, + ring0.SIMDFloatingPointException: info := &arch.SignalInfo{ Signo: int32(syscall.SIGFPE), Code: 7, // FPE_FLTINV (invalid operation). @@ -237,7 +273,7 @@ func (c *vCPU) SwitchToUser(switchOpts ring0.SwitchOpts) (*arch.SignalInfo, user info.SetAddr(switchOpts.Registers.Rip) // Include address. return info, usermem.AccessType{}, platform.ErrContextSignal - case ring0.Vector(bounce): + case ring0.Vector(bounce): // ring0.VirtualizationException return nil, usermem.NoAccess, platform.ErrContextInterrupt case ring0.AlignmentCheck: @@ -255,6 +291,12 @@ func (c *vCPU) SwitchToUser(switchOpts ring0.SwitchOpts) (*arch.SignalInfo, user // directly into the instance. return c.fault(int32(syscall.SIGBUS)) + case ring0.DeviceNotAvailable, + ring0.DoubleFault, + ring0.CoprocessorSegmentOverrun, + ring0.MachineCheck, + ring0.SecurityException: + fallthrough default: panic(fmt.Sprintf("unexpected vector: 0x%x", vector)) } diff --git a/pkg/sentry/platform/ring0/kernel_amd64.go b/pkg/sentry/platform/ring0/kernel_amd64.go index c828af654..117e86104 100644 --- a/pkg/sentry/platform/ring0/kernel_amd64.go +++ b/pkg/sentry/platform/ring0/kernel_amd64.go @@ -162,17 +162,16 @@ func IsCanonical(addr uint64) bool { // code that uses IP-relative addressing inside of absolute addresses. That's // the case for amd64, but may not be the case for other architectures. // +// Precondition: the Rip, Rsp, Fs and Gs registers must be canonical. + +// //go:nosplit func (c *CPU) SwitchToUser(switchOpts SwitchOpts) (vector Vector) { - // Check for canonical addresses. - regs := switchOpts.Registers - if !IsCanonical(regs.Rip) || !IsCanonical(regs.Rsp) || !IsCanonical(regs.Fs_base) || !IsCanonical(regs.Gs_base) { - return GeneralProtectionFault - } userCR3 := switchOpts.PageTables.CR3(!switchOpts.Flush, switchOpts.UserPCID) kernelCR3 := c.kernel.PageTables.CR3(true, switchOpts.KernelPCID) // Sanitize registers. + regs := switchOpts.Registers regs.Eflags &= ^uint64(UserFlagsClear) regs.Eflags |= UserFlagsSet regs.Cs = uint64(Ucode64) // Required for iret. |