summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--pkg/sentry/fsimpl/cgroupfs/cgroupfs.go24
-rw-r--r--pkg/sentry/fsimpl/cgroupfs/cgroupfs_state_autogen.go29
-rw-r--r--pkg/sentry/fsimpl/cgroupfs/cpu.go20
-rw-r--r--pkg/sentry/fsimpl/cgroupfs/memory.go18
4 files changed, 84 insertions, 7 deletions
diff --git a/pkg/sentry/fsimpl/cgroupfs/cgroupfs.go b/pkg/sentry/fsimpl/cgroupfs/cgroupfs.go
index 3d4005fd8..6061bace2 100644
--- a/pkg/sentry/fsimpl/cgroupfs/cgroupfs.go
+++ b/pkg/sentry/fsimpl/cgroupfs/cgroupfs.go
@@ -94,6 +94,14 @@ var SupportedMountOptions = []string{"all", "cpu", "cpuacct", "cpuset", "memory"
// +stateify savable
type FilesystemType struct{}
+// InternalData contains internal data passed in to the cgroupfs mount via
+// vfs.GetFilesystemOptions.InternalData.
+//
+// +stateify savable
+type InternalData struct {
+ DefaultControlValues map[string]int64
+}
+
// filesystem implements vfs.FilesystemImpl.
//
// +stateify savable
@@ -218,13 +226,19 @@ func (fsType FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
fs.MaxCachedDentries = maxCachedDentries
fs.VFSFilesystem().Init(vfsObj, &fsType, fs)
+ var defaults map[string]int64
+ if opts.InternalData != nil {
+ ctx.Debugf("cgroupfs.FilesystemType.GetFilesystem: default control values: %v", defaults)
+ defaults = opts.InternalData.(*InternalData).DefaultControlValues
+ }
+
for _, ty := range wantControllers {
var c controller
switch ty {
case controllerMemory:
- c = newMemoryController(fs)
+ c = newMemoryController(fs, defaults)
case controllerCPU:
- c = newCPUController(fs)
+ c = newCPUController(fs, defaults)
case controllerCPUAcct:
c = newCPUAcctController(fs)
case controllerCPUSet:
@@ -235,6 +249,12 @@ func (fsType FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
fs.controllers = append(fs.controllers, c)
}
+ if len(defaults) != 0 {
+ // Internal data is always provided at sentry startup and unused values
+ // indicate a problem with the sandbox config. Fail fast.
+ panic(fmt.Sprintf("cgroupfs.FilesystemType.GetFilesystem: unknown internal mount data: %v", defaults))
+ }
+
// Controllers usually appear in alphabetical order when displayed. Sort it
// here now, so it never needs to be sorted elsewhere.
sort.Slice(fs.controllers, func(i, j int) bool { return fs.controllers[i].Type() < fs.controllers[j].Type() })
diff --git a/pkg/sentry/fsimpl/cgroupfs/cgroupfs_state_autogen.go b/pkg/sentry/fsimpl/cgroupfs/cgroupfs_state_autogen.go
index 9e2e9de36..02afef1e4 100644
--- a/pkg/sentry/fsimpl/cgroupfs/cgroupfs_state_autogen.go
+++ b/pkg/sentry/fsimpl/cgroupfs/cgroupfs_state_autogen.go
@@ -136,6 +136,31 @@ func (fsType *FilesystemType) afterLoad() {}
func (fsType *FilesystemType) StateLoad(stateSourceObject state.Source) {
}
+func (i *InternalData) StateTypeName() string {
+ return "pkg/sentry/fsimpl/cgroupfs.InternalData"
+}
+
+func (i *InternalData) StateFields() []string {
+ return []string{
+ "DefaultControlValues",
+ }
+}
+
+func (i *InternalData) beforeSave() {}
+
+// +checklocksignore
+func (i *InternalData) StateSave(stateSinkObject state.Sink) {
+ i.beforeSave()
+ stateSinkObject.Save(0, &i.DefaultControlValues)
+}
+
+func (i *InternalData) afterLoad() {}
+
+// +checklocksignore
+func (i *InternalData) StateLoad(stateSourceObject state.Source) {
+ stateSourceObject.Load(0, &i.DefaultControlValues)
+}
+
func (fs *filesystem) StateTypeName() string {
return "pkg/sentry/fsimpl/cgroupfs.filesystem"
}
@@ -414,6 +439,7 @@ func (c *memoryController) StateTypeName() string {
func (c *memoryController) StateFields() []string {
return []string{
"controllerCommon",
+ "limitBytes",
}
}
@@ -423,6 +449,7 @@ func (c *memoryController) beforeSave() {}
func (c *memoryController) StateSave(stateSinkObject state.Sink) {
c.beforeSave()
stateSinkObject.Save(0, &c.controllerCommon)
+ stateSinkObject.Save(1, &c.limitBytes)
}
func (c *memoryController) afterLoad() {}
@@ -430,6 +457,7 @@ func (c *memoryController) afterLoad() {}
// +checklocksignore
func (c *memoryController) StateLoad(stateSourceObject state.Source) {
stateSourceObject.Load(0, &c.controllerCommon)
+ stateSourceObject.Load(1, &c.limitBytes)
}
func (d *memoryUsageInBytesData) StateTypeName() string {
@@ -459,6 +487,7 @@ func init() {
state.Register((*cgroupProcsData)(nil))
state.Register((*tasksData)(nil))
state.Register((*FilesystemType)(nil))
+ state.Register((*InternalData)(nil))
state.Register((*filesystem)(nil))
state.Register((*implStatFS)(nil))
state.Register((*dir)(nil))
diff --git a/pkg/sentry/fsimpl/cgroupfs/cpu.go b/pkg/sentry/fsimpl/cgroupfs/cpu.go
index 4641d613c..24d86a277 100644
--- a/pkg/sentry/fsimpl/cgroupfs/cpu.go
+++ b/pkg/sentry/fsimpl/cgroupfs/cpu.go
@@ -28,22 +28,36 @@ type cpuController struct {
controllerCommon
// CFS bandwidth control parameters, values in microseconds.
- cfsPeriod uint64
+ cfsPeriod int64
cfsQuota int64
// CPU shares, values should be (num core * 1024).
- shares uint64
+ shares int64
}
var _ controller = (*cpuController)(nil)
-func newCPUController(fs *filesystem) *cpuController {
+func newCPUController(fs *filesystem, defaults map[string]int64) *cpuController {
// Default values for controller parameters from Linux.
c := &cpuController{
cfsPeriod: 100000,
cfsQuota: -1,
shares: 1024,
}
+
+ if val, ok := defaults["cpu.cfs_period_us"]; ok {
+ c.cfsPeriod = val
+ delete(defaults, "cpu.cfs_period_us")
+ }
+ if val, ok := defaults["cpu.cfs_quota_us"]; ok {
+ c.cfsQuota = val
+ delete(defaults, "cpu.cfs_quota_us")
+ }
+ if val, ok := defaults["cpu.shares"]; ok {
+ c.shares = val
+ delete(defaults, "cpu.shares")
+ }
+
c.controllerCommon.init(controllerCPU, fs)
return c
}
diff --git a/pkg/sentry/fsimpl/cgroupfs/memory.go b/pkg/sentry/fsimpl/cgroupfs/memory.go
index eaf40a753..485c98376 100644
--- a/pkg/sentry/fsimpl/cgroupfs/memory.go
+++ b/pkg/sentry/fsimpl/cgroupfs/memory.go
@@ -17,7 +17,9 @@ package cgroupfs
import (
"bytes"
"fmt"
+ "math"
+ "gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/kernfs"
"gvisor.dev/gvisor/pkg/sentry/kernel"
@@ -28,12 +30,23 @@ import (
// +stateify savable
type memoryController struct {
controllerCommon
+
+ limitBytes int64
}
var _ controller = (*memoryController)(nil)
-func newMemoryController(fs *filesystem) *memoryController {
- c := &memoryController{}
+func newMemoryController(fs *filesystem, defaults map[string]int64) *memoryController {
+ c := &memoryController{
+ // Linux sets this to (PAGE_COUNTER_MAX * PAGE_SIZE) by default, which
+ // is ~ 2**63 on a 64-bit system. So essentially, inifinity. The exact
+ // value isn't very important.
+ limitBytes: math.MaxInt64,
+ }
+ if val, ok := defaults["memory.limit_in_bytes"]; ok {
+ c.limitBytes = val
+ delete(defaults, "memory.limit_in_bytes")
+ }
c.controllerCommon.init(controllerMemory, fs)
return c
}
@@ -41,6 +54,7 @@ func newMemoryController(fs *filesystem) *memoryController {
// AddControlFiles implements controller.AddControlFiles.
func (c *memoryController) AddControlFiles(ctx context.Context, creds *auth.Credentials, _ *cgroupInode, contents map[string]kernfs.Inode) {
contents["memory.usage_in_bytes"] = c.fs.newControllerFile(ctx, creds, &memoryUsageInBytesData{})
+ contents["memory.limit_in_bytes"] = c.fs.newStaticControllerFile(ctx, creds, linux.FileMode(0644), fmt.Sprintf("%d\n", c.limitBytes))
}
// +stateify savable