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)) + } +}