summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/platform/kvm
diff options
context:
space:
mode:
authorAdin Scannell <ascannell@google.com>2018-07-16 22:02:03 -0700
committerShentubot <shentubot@google.com>2018-07-16 22:02:58 -0700
commit29e00c943a61dfcfd4ac8d3f6f526eab641c44a6 (patch)
treef7cdb0c59c8363b3a4e5737e17b1b4e423bfc05a /pkg/sentry/platform/kvm
parent14d06064d26b1cd9e2ccad08ebe997e704092eb8 (diff)
Add CPUID faulting for ptrace and KVM.
PiperOrigin-RevId: 204858314 Change-Id: I8252bf8de3232a7a27af51076139b585e73276d4
Diffstat (limited to 'pkg/sentry/platform/kvm')
-rw-r--r--pkg/sentry/platform/kvm/machine.go22
-rw-r--r--pkg/sentry/platform/kvm/machine_amd64.go22
2 files changed, 33 insertions, 11 deletions
diff --git a/pkg/sentry/platform/kvm/machine.go b/pkg/sentry/platform/kvm/machine.go
index abdc51431..68e099d1b 100644
--- a/pkg/sentry/platform/kvm/machine.go
+++ b/pkg/sentry/platform/kvm/machine.go
@@ -141,11 +141,6 @@ func (m *machine) newVCPU() *vCPU {
panic(fmt.Sprintf("error setting signal mask: %v", err))
}
- // Initialize architecture state.
- if err := c.initArchState(); err != nil {
- panic(fmt.Sprintf("error initialization vCPU state: %v", err))
- }
-
// Map the run data.
runData, err := mapRunData(int(fd))
if err != nil {
@@ -153,6 +148,11 @@ func (m *machine) newVCPU() *vCPU {
}
c.runData = runData
+ // Initialize architecture state.
+ if err := c.initArchState(); err != nil {
+ panic(fmt.Sprintf("error initialization vCPU state: %v", err))
+ }
+
return c // Done.
}
@@ -168,12 +168,6 @@ func newMachine(vm int) (*machine, error) {
PageTables: pagetables.New(newAllocator()),
})
- // Initialize architecture state.
- if err := m.initArchState(); err != nil {
- m.Destroy()
- return nil, err
- }
-
// Apply the physical mappings. Note that these mappings may point to
// guest physical addresses that are not actually available. These
// physical pages are mapped on demand, see kernel_unsafe.go.
@@ -221,6 +215,12 @@ func newMachine(vm int) (*machine, error) {
}
})
+ // Initialize architecture state.
+ if err := m.initArchState(); err != nil {
+ m.Destroy()
+ return nil, err
+ }
+
// Ensure the machine is cleaned up properly.
runtime.SetFinalizer(m, (*machine).Destroy)
return m, nil
diff --git a/pkg/sentry/platform/kvm/machine_amd64.go b/pkg/sentry/platform/kvm/machine_amd64.go
index 9af4f3f3d..bcd29a947 100644
--- a/pkg/sentry/platform/kvm/machine_amd64.go
+++ b/pkg/sentry/platform/kvm/machine_amd64.go
@@ -19,6 +19,7 @@ package kvm
import (
"fmt"
"reflect"
+ "runtime/debug"
"syscall"
"gvisor.googlesource.com/gvisor/pkg/sentry/arch"
@@ -39,6 +40,21 @@ func (m *machine) initArchState() error {
uintptr(reservedMemory-(3*usermem.PageSize))); errno != 0 {
return errno
}
+
+ // Enable CPUID faulting, if possible. Note that this also serves as a
+ // basic platform sanity tests, since we will enter guest mode for the
+ // first time here. The recovery is necessary, since if we fail to read
+ // the platform info register, we will retry to host mode and
+ // ultimately need to handle a segmentation fault.
+ old := debug.SetPanicOnFault(true)
+ defer func() {
+ recover()
+ debug.SetPanicOnFault(old)
+ }()
+ m.retryInGuest(func() {
+ ring0.SetCPUIDFaulting(true)
+ })
+
return nil
}
@@ -238,6 +254,12 @@ func (c *vCPU) SwitchToUser(switchOpts ring0.SwitchOpts) (*arch.SignalInfo, user
Code: arch.SignalInfoKernel,
}
info.SetAddr(switchOpts.Registers.Rip) // Include address.
+ if vector == ring0.GeneralProtectionFault {
+ // When CPUID faulting is enabled, we will generate a #GP(0) when
+ // userspace executes a CPUID instruction. This is handled above,
+ // because we need to be able to map and read user memory.
+ return info, usermem.AccessType{}, platform.ErrContextSignalCPUID
+ }
return info, usermem.AccessType{}, platform.ErrContextSignal
case ring0.InvalidOpcode: