From 2e0ff5d9d0455217fa9c0f1d38a07d44808a3821 Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Tue, 7 Jun 2022 14:08:11 -0700 Subject: [PATCH] platform/kvm: Disable async preemption while mapping initial virtual regions. All new mappings are handled from the SIGSYS signal handler and we have to guarantee that the signal handler doesn't race with the code that handles initial regions. PiperOrigin-RevId: 453521202 --- pkg/sentry/platform/kvm/machine.go | 5 +++++ pkg/sentry/platform/kvm/machine_unsafe.go | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/pkg/sentry/platform/kvm/machine.go b/pkg/sentry/platform/kvm/machine.go index 2b71ec75f..1da52b07b 100644 --- a/pkg/sentry/platform/kvm/machine.go +++ b/pkg/sentry/platform/kvm/machine.go @@ -318,6 +318,10 @@ func newMachine(vm int) (*machine, error) { } } + // handleBluepillFault takes the slot spinlock and it is called from + // seccompMmapHandler, so here we have to guarantee that mmap is not + // called while we hold the slot spinlock. + disableAsyncPreemption() applyVirtualRegions(func(vr virtualRegion) { if excludeVirtualRegion(vr) { return // skip region. @@ -331,6 +335,7 @@ func newMachine(vm int) (*machine, error) { mapRegion(vr, 0) }) + enableAsyncPreemption() // Initialize architecture state. if err := m.initArchState(); err != nil { diff --git a/pkg/sentry/platform/kvm/machine_unsafe.go b/pkg/sentry/platform/kvm/machine_unsafe.go index 0bfad3881..ba53cb09c 100644 --- a/pkg/sentry/platform/kvm/machine_unsafe.go +++ b/pkg/sentry/platform/kvm/machine_unsafe.go @@ -240,3 +240,23 @@ func seccompMmapHandler(context unsafe.Pointer) { } seccompMmapHandlerCnt.Add(-1) } + +// disableAsyncPreemption disables asynchronous preemption of go-routines. +func disableAsyncPreemption() { + set := linux.MakeSignalSet(linux.SIGURG) + _, _, errno := unix.RawSyscall6(unix.SYS_RT_SIGPROCMASK, linux.SIG_BLOCK, + uintptr(unsafe.Pointer(&set)), 0, linux.SignalSetSize, 0, 0) + if errno != 0 { + panic(fmt.Sprintf("sigprocmask failed: %d", errno)) + } +} + +// enableAsyncPreemption enables asynchronous preemption of go-routines. +func enableAsyncPreemption() { + set := linux.MakeSignalSet(linux.SIGURG) + _, _, errno := unix.RawSyscall6(unix.SYS_RT_SIGPROCMASK, linux.SIG_UNBLOCK, + uintptr(unsafe.Pointer(&set)), 0, linux.SignalSetSize, 0, 0) + if errno != 0 { + panic(fmt.Sprintf("sigprocmask failed: %d", errno)) + } +}