mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Add support for /proc/[pid]/status to trace procfs.
Updates #4805 PiperOrigin-RevId: 451301995
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user