Add support for /proc/[pid]/cgroup to trace procfs.

Updates #4805

PiperOrigin-RevId: 451297968
This commit is contained in:
Ayush Ranjan
2022-05-26 20:02:32 -07:00
committed by gVisor bot
parent 6103b4b3b6
commit 37076bc16f
3 changed files with 42 additions and 14 deletions
+21 -14
View File
@@ -177,20 +177,21 @@ func (t *Task) MigrateCgroup(dst Cgroup) error {
return nil
}
// taskCgroupEntry represents a line in /proc/<pid>/cgroup, and is used to
// TaskCgroupEntry represents a line in /proc/<pid>/cgroup, and is used to
// format a cgroup for display.
type taskCgroupEntry struct {
hierarchyID uint32
controllers string
path string
type TaskCgroupEntry struct {
HierarchyID uint32 `json:"hierarchy_id,omitempty"`
Controllers string `json:"controllers,omitempty"`
Path string `json:"path,omitempty"`
}
// GenerateProcTaskCgroup writes the contents of /proc/<pid>/cgroup for t to buf.
func (t *Task) GenerateProcTaskCgroup(buf *bytes.Buffer) {
// GetCgroupEntries generates the contents of /proc/<pid>/cgroup as
// a TaskCgroupEntry array.
func (t *Task) GetCgroupEntries() []TaskCgroupEntry {
t.mu.Lock()
defer t.mu.Unlock()
cgEntries := make([]taskCgroupEntry, 0, len(t.cgroups))
cgEntries := make([]TaskCgroupEntry, 0, len(t.cgroups))
for c := range t.cgroups {
ctls := c.Controllers()
ctlNames := make([]string, 0, len(ctls))
@@ -208,16 +209,22 @@ func (t *Task) GenerateProcTaskCgroup(buf *bytes.Buffer) {
ctlNames = append(ctlNames, string(ctl.Type()))
}
cgEntries = append(cgEntries, taskCgroupEntry{
hierarchyID: c.HierarchyID(),
controllers: strings.Join(ctlNames, ","),
path: c.Path(),
cgEntries = append(cgEntries, TaskCgroupEntry{
HierarchyID: c.HierarchyID(),
Controllers: strings.Join(ctlNames, ","),
Path: c.Path(),
})
}
sort.Slice(cgEntries, func(i, j int) bool { return cgEntries[i].hierarchyID > cgEntries[j].hierarchyID })
sort.Slice(cgEntries, func(i, j int) bool { return cgEntries[i].HierarchyID > cgEntries[j].HierarchyID })
return cgEntries
}
// GenerateProcTaskCgroup writes the contents of /proc/<pid>/cgroup for t to buf.
func (t *Task) GenerateProcTaskCgroup(buf *bytes.Buffer) {
cgEntries := t.GetCgroupEntries()
for _, cgE := range cgEntries {
fmt.Fprintf(buf, "%d:%s:%s\n", cgE.hierarchyID, cgE.controllers, cgE.path)
fmt.Fprintf(buf, "%d:%s:%s\n", cgE.HierarchyID, cgE.Controllers, cgE.Path)
}
}
+5
View File
@@ -61,6 +61,8 @@ type ProcessProcfsDump struct {
// Limits constains resource limits for this process. Currently only
// RLIMIT_NOFILE is supported.
Limits map[string]limits.Limit `json:"limits,omitempty"`
// Cgroup is /proc/[pid]/cgroup split into an array.
Cgroup []kernel.TaskCgroupEntry `json:"cgroup,omitempty"`
}
// getMM returns t's MemoryManager. On success, the MemoryManager's users count
@@ -208,5 +210,8 @@ func Dump(t *kernel.Task, pid kernel.ThreadID) (ProcessProcfsDump, error) {
Limits: map[string]limits.Limit{
"RLIMIT_NOFILE": fdLimit,
},
// We don't need to worry about fake cgroup controllers as that is not
// supported in runsc.
Cgroup: t.GetCgroupEntries(),
}, nil
}
+16
View File
@@ -23,6 +23,7 @@ import (
specs "github.com/opencontainers/runtime-spec/specs-go"
"google.golang.org/protobuf/proto"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/limits"
"gvisor.dev/gvisor/pkg/sentry/seccheck"
"gvisor.dev/gvisor/pkg/sentry/seccheck/checkers/remote/test"
@@ -304,6 +305,7 @@ func TestProcfsDump(t *testing.T) {
spec.Process.Rlimits = []specs.POSIXRlimit{
{Type: "RLIMIT_NOFILE", Hard: fdLimit.Max, Soft: fdLimit.Cur},
}
conf.Cgroupfs = true
_, bundleDir, cleanup, err := testutil.SetupContainer(spec, conf)
if err != nil {
t.Fatalf("error setting up container: %v", err)
@@ -396,4 +398,18 @@ func TestProcfsDump(t *testing.T) {
if got := procfsDump[0].Limits["RLIMIT_NOFILE"]; got != fdLimit {
t.Errorf("expected FD limit to be %+v, but got %+v", fdLimit, got)
}
wantCgroup := []kernel.TaskCgroupEntry{
kernel.TaskCgroupEntry{HierarchyID: 2, Controllers: "memory", Path: "/"},
kernel.TaskCgroupEntry{HierarchyID: 1, Controllers: "cpu", Path: "/"},
}
if len(procfsDump[0].Cgroup) != len(wantCgroup) {
t.Errorf("expected 2 cgroup controllers, got %+v", procfsDump[0].Cgroup)
} else {
for i, cgroup := range procfsDump[0].Cgroup {
if cgroup != wantCgroup[i] {
t.Errorf("expected %+v, got %+v", wantCgroup[i], cgroup)
}
}
}
}