Skip to content

Commit 38cd0ae

Browse files
konstantin-s-bogomgvisor-bot
authored andcommitted
Don't panic on KVM initialization if can't create new vCPU.
This should be an indication to the user to set greater memory limits, a clean exit with an error should do that. PiperOrigin-RevId: 759294902
1 parent d30c58e commit 38cd0ae

File tree

4 files changed

+38
-12
lines changed

4 files changed

+38
-12
lines changed

pkg/sentry/platform/kvm/machine.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
"gvisor.dev/gvisor/pkg/ring0"
3333
"gvisor.dev/gvisor/pkg/ring0/pagetables"
3434
"gvisor.dev/gvisor/pkg/seccomp"
35+
"gvisor.dev/gvisor/pkg/sentry/platform"
3536
ktime "gvisor.dev/gvisor/pkg/sentry/time"
3637
"gvisor.dev/gvisor/pkg/sighandling"
3738
"gvisor.dev/gvisor/pkg/sync"
@@ -227,10 +228,15 @@ type dieState struct {
227228
// createVCPU creates and returns a new vCPU.
228229
//
229230
// Precondition: mu must be held.
230-
func (m *machine) createVCPU(id int) *vCPU {
231+
func (m *machine) createVCPU(id int) (*vCPU, error) {
231232
// Create the vCPU.
232233
fd, errno := hostsyscall.RawSyscall(unix.SYS_IOCTL, uintptr(m.fd), KVM_CREATE_VCPU, uintptr(id))
233-
if errno != 0 {
234+
if errno == unix.ENOMEM {
235+
return nil, &platform.InitializationError{
236+
Err: fmt.Errorf("error creating new vCPU(id=%d): %v", id, errno),
237+
Errno: errno,
238+
}
239+
} else if errno != 0 {
234240
panic(fmt.Sprintf("error creating new vCPU(id=%d): %v", id, errno))
235241
}
236242

@@ -259,7 +265,7 @@ func (m *machine) createVCPU(id int) *vCPU {
259265
panic(fmt.Sprintf("error initializing vCPU(id=%d) state: %v", id, err))
260266
}
261267

262-
return c // Done.
268+
return c, nil // Done.
263269
}
264270

265271
// forceMappingEntireAddressSpace forces mapping the entire process address

pkg/sentry/platform/kvm/machine_amd64.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,12 @@ func (m *machine) initArchState() error {
5050

5151
// Initialize all vCPUs to minimize kvm ioctl-s allowed by seccomp filters.
5252
m.mu.Lock()
53+
defer m.mu.Unlock()
5354
for i := 0; i < m.maxVCPUs; i++ {
54-
m.createVCPU(i)
55+
if _, err := m.createVCPU(i); err != nil {
56+
return err
57+
}
5558
}
56-
m.mu.Unlock()
5759

5860
return nil
5961
}

pkg/sentry/platform/kvm/machine_arm64_unsafe.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,19 @@ func (m *machine) initArchState() error {
4949
panic(fmt.Sprintf("error setting KVM_ARM_PREFERRED_TARGET failed: %v", errno))
5050
}
5151

52-
// Initialize all vCPUs on ARM64, while this does not happen on x86_64.
53-
// The reason for the difference is that ARM64 and x86_64 have different KVM timer mechanisms.
54-
// If we create vCPU dynamically on ARM64, the timer for vCPU would mess up for a short time.
52+
// Initialize all vCPUs on ARM64 (we also do this on x86_64, but for
53+
// ARM64 it is especially important as it has a different KVM timer
54+
// mechanism).
55+
// If we create vCPU dynamically on ARM64, the timer for vCPU would mess
56+
// up for a short time.
5557
// For more detail, please refer to https://github.com/google/gvisor/issues/5739
5658
m.mu.Lock()
59+
defer m.mu.Unlock()
5760
for i := 0; i < m.maxVCPUs; i++ {
58-
m.createVCPU(i)
61+
if _, err := m.createVCPU(i); err != nil {
62+
return err
63+
}
5964
}
60-
m.mu.Unlock()
6165
return nil
6266
}
6367

pkg/sentry/platform/platform.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,15 +254,29 @@ type Context interface {
254254
PrepareSleep()
255255
}
256256

257-
// ContextError is one of the possible errors returned by Context.Switch().
258-
type ContextError struct {
257+
type qualifiedError struct {
259258
// Err is the underlying error.
260259
Err error
261260
// Errno is an approximation of what type of error this is supposed to
262261
// be as defined by the linux errnos.
263262
Errno unix.Errno
264263
}
265264

265+
func (e *qualifiedError) Error() string {
266+
return e.Err.Error()
267+
}
268+
269+
// InitializationError is returned by Platform.New() when the platform fails
270+
// to initialize.
271+
type InitializationError qualifiedError
272+
273+
func (e *InitializationError) Error() string {
274+
return e.Err.Error()
275+
}
276+
277+
// ContextError is one of the possible errors returned by Context.Switch().
278+
type ContextError qualifiedError
279+
266280
func (e *ContextError) Error() string {
267281
return e.Err.Error()
268282
}

0 commit comments

Comments
 (0)