diff options
author | Adin Scannell <ascannell@google.com> | 2018-07-16 22:02:03 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2018-07-16 22:02:58 -0700 |
commit | 29e00c943a61dfcfd4ac8d3f6f526eab641c44a6 (patch) | |
tree | f7cdb0c59c8363b3a4e5737e17b1b4e423bfc05a /pkg/sentry/platform/kvm | |
parent | 14d06064d26b1cd9e2ccad08ebe997e704092eb8 (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.go | 22 | ||||
-rw-r--r-- | pkg/sentry/platform/kvm/machine_amd64.go | 22 |
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: |