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

Updates #4805

PiperOrigin-RevId: 451301995
This commit is contained in:
Ayush Ranjan
2022-05-26 20:34:16 -07:00
committed by gVisor bot
parent 37076bc16f
commit 565fbe2151
2 changed files with 61 additions and 5 deletions
+41 -3
View File
@@ -38,11 +38,26 @@ type FDInfo struct {
Path string `json:"path,omitempty"`
}
// UIDGID contains information for /proc/[pid]/status/{uid,gid}.
type UIDGID struct {
Real uint32 `json:"real,omitempty"`
Effective uint32 `json:"effective,omitempty"`
Saved uint32 `json:"saved,omitempty"`
}
// Status contains information for /proc/[pid]/status.
type Status struct {
Comm string `json:"comm,omitempty"`
PID int32 `json:"pid,omitempty"`
UID UIDGID `json:"uid,omitempty"`
GID UIDGID `json:"gid,omitempty"`
VMSize uint64 `json:"vm_size,omitempty"`
VMRSS uint64 `json:"vm_rss,omitempty"`
}
// ProcessProcfsDump contains the procfs dump for one process. For more details
// on fields that directly correspond to /proc fields, see proc(5).
type ProcessProcfsDump struct {
// PID is the process ID.
PID int32 `json:"pid,omitempty"`
// Exe is the symlink target of /proc/[pid]/exe.
Exe string `json:"exe,omitempty"`
// Args is /proc/[pid]/cmdline split into an array.
@@ -63,6 +78,8 @@ type ProcessProcfsDump struct {
Limits map[string]limits.Limit `json:"limits,omitempty"`
// Cgroup is /proc/[pid]/cgroup split into an array.
Cgroup []kernel.TaskCgroupEntry `json:"cgroup,omitempty"`
// Status is /proc/[pid]/status.
Status Status `json:"status,omitempty"`
}
// getMM returns t's MemoryManager. On success, the MemoryManager's users count
@@ -183,6 +200,27 @@ func getFDLimit(ctx context.Context, pid kernel.ThreadID) (limits.Limit, error)
return limits.Limit{}, fmt.Errorf("could not find limit set for pid %s", pid)
}
func getStatus(t *kernel.Task, mm *mm.MemoryManager, pid kernel.ThreadID) Status {
creds := t.Credentials()
uns := creds.UserNamespace
return Status{
Comm: t.Name(),
PID: int32(pid),
UID: UIDGID{
Real: uint32(creds.RealKUID.In(uns).OrOverflow()),
Effective: uint32(creds.EffectiveKUID.In(uns).OrOverflow()),
Saved: uint32(creds.SavedKUID.In(uns).OrOverflow()),
},
GID: UIDGID{
Real: uint32(creds.RealKGID.In(uns).OrOverflow()),
Effective: uint32(creds.EffectiveKGID.In(uns).OrOverflow()),
Saved: uint32(creds.SavedKGID.In(uns).OrOverflow()),
},
VMSize: mm.VirtualMemorySize() >> 10,
VMRSS: mm.ResidentSetSize() >> 10,
}
}
// Dump returns a procfs dump for process pid. t must be a task in process pid.
func Dump(t *kernel.Task, pid kernel.ThreadID) (ProcessProcfsDump, error) {
ctx := t.AsyncContext()
@@ -199,7 +237,6 @@ func Dump(t *kernel.Task, pid kernel.ThreadID) (ProcessProcfsDump, error) {
}
return ProcessProcfsDump{
PID: int32(pid),
Exe: getExecutablePath(ctx, pid, mm),
Args: getMetadataArray(ctx, pid, mm, proc.Cmdline),
Env: getMetadataArray(ctx, pid, mm, proc.Environ),
@@ -213,5 +250,6 @@ func Dump(t *kernel.Task, pid kernel.ThreadID) (ProcessProcfsDump, error) {
// We don't need to worry about fake cgroup controllers as that is not
// supported in runsc.
Cgroup: t.GetCgroupEntries(),
Status: getStatus(t, mm, pid),
}, nil
}
+20 -2
View File
@@ -339,8 +339,8 @@ func TestProcfsDump(t *testing.T) {
}
// Sleep should be PID 1.
if procfsDump[0].PID != 1 {
t.Errorf("expected sleep process to be pid 1, got %d", procfsDump[0].PID)
if procfsDump[0].Status.PID != 1 {
t.Errorf("expected sleep process to be pid 1, got %d", procfsDump[0].Status.PID)
}
// Check that bin/sleep is part of the executable path.
@@ -412,4 +412,22 @@ func TestProcfsDump(t *testing.T) {
}
}
}
if wantName := "sleep"; procfsDump[0].Status.Comm != wantName {
t.Errorf("expected Comm to be %q, but got %q", wantName, procfsDump[0].Status.Comm)
}
if uid := procfsDump[0].Status.UID; uid.Real != 0 || uid.Effective != 0 || uid.Saved != 0 {
t.Errorf("expected UIDs to be 0 (root), got %+v", uid)
}
if gid := procfsDump[0].Status.GID; gid.Real != 0 || gid.Effective != 0 || gid.Saved != 0 {
t.Errorf("expected GIDs to be 0 (root), got %+v", gid)
}
if procfsDump[0].Status.VMSize == 0 {
t.Errorf("expected VMSize to be set")
}
if procfsDump[0].Status.VMRSS == 0 {
t.Errorf("expected VMSize to be set")
}
}