diff options
author | gVisor bot <gvisor-bot@google.com> | 2021-04-21 20:41:24 +0000 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-04-21 20:41:24 +0000 |
commit | 588e13090d9f4555342a34c4b552265337a8e47c (patch) | |
tree | 3c121a2f7bb4055aca653f33c264dcdbc9fde670 | |
parent | b0e92a43186ae085a1d374c3c161a6c87ace5ca0 (diff) | |
parent | e3a5da8ce62826f56c0b531590bb472ea717eeac (diff) |
Merge release-20210419.0-15-ge3a5da8ce (automated)
-rw-r--r-- | pkg/sentry/fsimpl/cgroupfs/base.go | 28 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/cgroupfs/cgroupfs.go | 21 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/cgroupfs/cgroupfs_state_autogen.go | 55 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/cgroupfs/job.go | 64 |
4 files changed, 164 insertions, 4 deletions
diff --git a/pkg/sentry/fsimpl/cgroupfs/base.go b/pkg/sentry/fsimpl/cgroupfs/base.go index 39c1013e1..0f54888d8 100644 --- a/pkg/sentry/fsimpl/cgroupfs/base.go +++ b/pkg/sentry/fsimpl/cgroupfs/base.go @@ -18,6 +18,7 @@ import ( "bytes" "fmt" "sort" + "strconv" "sync/atomic" "gvisor.dev/gvisor/pkg/abi/linux" @@ -26,6 +27,7 @@ import ( "gvisor.dev/gvisor/pkg/sentry/kernel" "gvisor.dev/gvisor/pkg/sentry/kernel/auth" "gvisor.dev/gvisor/pkg/sentry/vfs" + "gvisor.dev/gvisor/pkg/syserror" "gvisor.dev/gvisor/pkg/usermem" ) @@ -231,3 +233,29 @@ func (d *tasksData) Write(ctx context.Context, src usermem.IOSequence, offset in // TODO(b/183137098): Payload is the pid for a process to add to this cgroup. return src.NumBytes(), nil } + +// parseInt64FromString interprets src as string encoding a int64 value, and +// returns the parsed value. +func parseInt64FromString(ctx context.Context, src usermem.IOSequence, offset int64) (val, len int64, err error) { + const maxInt64StrLen = 20 // i.e. len(fmt.Sprintf("%d", math.MinInt64)) == 20 + + t := kernel.TaskFromContext(ctx) + src = src.DropFirst64(offset) + + buf := t.CopyScratchBuffer(maxInt64StrLen) + n, err := src.CopyIn(ctx, buf) + if err != nil { + return 0, int64(n), err + } + buf = buf[:n] + + val, err = strconv.ParseInt(string(buf), 10, 64) + if err != nil { + // Note: This also handles zero-len writes if offset is beyond the end + // of src, or src is empty. + ctx.Warningf("cgroupfs.parseInt64FromString: failed to parse %q: %v", string(buf), err) + return 0, int64(n), syserror.EINVAL + } + + return val, int64(n), nil +} diff --git a/pkg/sentry/fsimpl/cgroupfs/cgroupfs.go b/pkg/sentry/fsimpl/cgroupfs/cgroupfs.go index ca8caee5f..bd3e69757 100644 --- a/pkg/sentry/fsimpl/cgroupfs/cgroupfs.go +++ b/pkg/sentry/fsimpl/cgroupfs/cgroupfs.go @@ -81,13 +81,20 @@ const ( controllerCPU = kernel.CgroupControllerType("cpu") controllerCPUAcct = kernel.CgroupControllerType("cpuacct") controllerCPUSet = kernel.CgroupControllerType("cpuset") + controllerJob = kernel.CgroupControllerType("job") controllerMemory = kernel.CgroupControllerType("memory") ) -var allControllers = []kernel.CgroupControllerType{controllerCPU, controllerCPUAcct, controllerCPUSet, controllerMemory} +var allControllers = []kernel.CgroupControllerType{ + controllerCPU, + controllerCPUAcct, + controllerCPUSet, + controllerJob, + controllerMemory, +} // SupportedMountOptions is the set of supported mount options for cgroupfs. -var SupportedMountOptions = []string{"all", "cpu", "cpuacct", "cpuset", "memory"} +var SupportedMountOptions = []string{"all", "cpu", "cpuacct", "cpuset", "job", "memory"} // FilesystemType implements vfs.FilesystemType. // @@ -171,6 +178,10 @@ func (fsType FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt delete(mopts, "cpuset") wantControllers = append(wantControllers, controllerCPUSet) } + if _, ok := mopts["job"]; ok { + delete(mopts, "job") + wantControllers = append(wantControllers, controllerJob) + } if _, ok := mopts["memory"]; ok { delete(mopts, "memory") wantControllers = append(wantControllers, controllerMemory) @@ -235,14 +246,16 @@ func (fsType FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt for _, ty := range wantControllers { var c controller switch ty { - case controllerMemory: - c = newMemoryController(fs, defaults) case controllerCPU: c = newCPUController(fs, defaults) case controllerCPUAcct: c = newCPUAcctController(fs) case controllerCPUSet: c = newCPUSetController(fs) + case controllerJob: + c = newJobController(fs) + case controllerMemory: + c = newMemoryController(fs, defaults) default: panic(fmt.Sprintf("Unreachable: unknown cgroup controller %q", ty)) } diff --git a/pkg/sentry/fsimpl/cgroupfs/cgroupfs_state_autogen.go b/pkg/sentry/fsimpl/cgroupfs/cgroupfs_state_autogen.go index d6f9f6cb4..3142ab6f8 100644 --- a/pkg/sentry/fsimpl/cgroupfs/cgroupfs_state_autogen.go +++ b/pkg/sentry/fsimpl/cgroupfs/cgroupfs_state_autogen.go @@ -557,6 +557,59 @@ func (r *dirRefs) StateLoad(stateSourceObject state.Source) { stateSourceObject.AfterLoad(r.afterLoad) } +func (c *jobController) StateTypeName() string { + return "pkg/sentry/fsimpl/cgroupfs.jobController" +} + +func (c *jobController) StateFields() []string { + return []string{ + "controllerCommon", + "id", + } +} + +func (c *jobController) beforeSave() {} + +// +checklocksignore +func (c *jobController) StateSave(stateSinkObject state.Sink) { + c.beforeSave() + stateSinkObject.Save(0, &c.controllerCommon) + stateSinkObject.Save(1, &c.id) +} + +func (c *jobController) afterLoad() {} + +// +checklocksignore +func (c *jobController) StateLoad(stateSourceObject state.Source) { + stateSourceObject.Load(0, &c.controllerCommon) + stateSourceObject.Load(1, &c.id) +} + +func (d *jobIDData) StateTypeName() string { + return "pkg/sentry/fsimpl/cgroupfs.jobIDData" +} + +func (d *jobIDData) StateFields() []string { + return []string{ + "c", + } +} + +func (d *jobIDData) beforeSave() {} + +// +checklocksignore +func (d *jobIDData) StateSave(stateSinkObject state.Sink) { + d.beforeSave() + stateSinkObject.Save(0, &d.c) +} + +func (d *jobIDData) afterLoad() {} + +// +checklocksignore +func (d *jobIDData) StateLoad(stateSourceObject state.Source) { + stateSourceObject.Load(0, &d.c) +} + func (c *memoryController) StateTypeName() string { return "pkg/sentry/fsimpl/cgroupfs.memoryController" } @@ -627,6 +680,8 @@ func init() { state.Register((*cpuacctUsageSysData)(nil)) state.Register((*cpusetController)(nil)) state.Register((*dirRefs)(nil)) + state.Register((*jobController)(nil)) + state.Register((*jobIDData)(nil)) state.Register((*memoryController)(nil)) state.Register((*memoryUsageInBytesData)(nil)) } diff --git a/pkg/sentry/fsimpl/cgroupfs/job.go b/pkg/sentry/fsimpl/cgroupfs/job.go new file mode 100644 index 000000000..48919c338 --- /dev/null +++ b/pkg/sentry/fsimpl/cgroupfs/job.go @@ -0,0 +1,64 @@ +// Copyright 2021 The gVisor Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cgroupfs + +import ( + "bytes" + "fmt" + + "gvisor.dev/gvisor/pkg/context" + "gvisor.dev/gvisor/pkg/sentry/fsimpl/kernfs" + "gvisor.dev/gvisor/pkg/sentry/kernel/auth" + "gvisor.dev/gvisor/pkg/usermem" +) + +// +stateify savable +type jobController struct { + controllerCommon + id int64 +} + +var _ controller = (*jobController)(nil) + +func newJobController(fs *filesystem) *jobController { + c := &jobController{} + c.controllerCommon.init(controllerJob, fs) + return c +} + +func (c *jobController) AddControlFiles(ctx context.Context, creds *auth.Credentials, _ *cgroupInode, contents map[string]kernfs.Inode) { + contents["job.id"] = c.fs.newControllerWritableFile(ctx, creds, &jobIDData{c: c}) +} + +// +stateify savable +type jobIDData struct { + c *jobController +} + +// Generate implements vfs.DynamicBytesSource.Generate. +func (d *jobIDData) Generate(ctx context.Context, buf *bytes.Buffer) error { + fmt.Fprintf(buf, "%d\n", d.c.id) + return nil +} + +// Write implements vfs.WritableDynamicBytesSource.Write. +func (d *jobIDData) Write(ctx context.Context, src usermem.IOSequence, offset int64) (int64, error) { + val, n, err := parseInt64FromString(ctx, src, offset) + if err != nil { + return n, err + } + d.c.id = val + return n, nil +} |