From ec422a66093e09d2884e3d504a453196a2af5403 Mon Sep 17 00:00:00 2001 From: Ayush Ranjan Date: Thu, 19 May 2022 12:15:08 -0700 Subject: [PATCH] Add support for /proc/[pid]/cwd to trace procfs. Added test for this field. Updates #4805 PiperOrigin-RevId: 449805258 --- runsc/boot/procfs/BUILD | 1 + runsc/boot/procfs/dump.go | 26 ++++++++++++++++++++++++++ runsc/container/trace_test.go | 5 +++++ 3 files changed, 32 insertions(+) diff --git a/runsc/boot/procfs/BUILD b/runsc/boot/procfs/BUILD index 82ce12fa8..4b7950206 100644 --- a/runsc/boot/procfs/BUILD +++ b/runsc/boot/procfs/BUILD @@ -12,5 +12,6 @@ go_library( "//pkg/sentry/fsimpl/proc", "//pkg/sentry/kernel", "//pkg/sentry/mm", + "//pkg/sentry/vfs", ], ) diff --git a/runsc/boot/procfs/dump.go b/runsc/boot/procfs/dump.go index 81a386271..79faf8561 100644 --- a/runsc/boot/procfs/dump.go +++ b/runsc/boot/procfs/dump.go @@ -26,6 +26,7 @@ import ( "gvisor.dev/gvisor/pkg/sentry/fsimpl/proc" "gvisor.dev/gvisor/pkg/sentry/kernel" "gvisor.dev/gvisor/pkg/sentry/mm" + "gvisor.dev/gvisor/pkg/sentry/vfs" ) // ProcessProcfsDump contains the procfs dump for one process. @@ -38,6 +39,8 @@ type ProcessProcfsDump struct { Args []string `json:"args,omitempty"` // Env is /proc/[pid]/environ split into an array. Env []string `json:"env,omitempty"` + // CWD is the symlink target of /proc/[pid]/cwd. + CWD string `json:"cwd,omitempty"` } // getMM returns t's MemoryManager. On success, the MemoryManager's users count @@ -77,6 +80,28 @@ func getMetadataArray(ctx context.Context, pid kernel.ThreadID, mm *mm.MemoryMan return strings.Split(strings.TrimSuffix(buf.String(), "\000"), "\000") } +func getCWD(ctx context.Context, t *kernel.Task, pid kernel.ThreadID) string { + cwdDentry := t.FSContext().WorkingDirectoryVFS2() + if !cwdDentry.Ok() { + log.Warningf("No CWD dentry found for PID %s", pid) + return "" + } + + root := vfs.RootFromContext(ctx) + if !root.Ok() { + log.Warningf("no root could be found from context for PID %s", pid) + return "" + } + defer root.DecRef(ctx) + + vfsObj := cwdDentry.Mount().Filesystem().VirtualFilesystem() + name, err := vfsObj.PathnameWithDeleted(ctx, root, cwdDentry) + if err != nil { + log.Warningf("PathnameWithDeleted failed to find CWD: %v", err) + } + return name +} + // 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() @@ -92,5 +117,6 @@ func Dump(t *kernel.Task, pid kernel.ThreadID) (ProcessProcfsDump, error) { Exe: getExecutablePath(ctx, pid, mm), Args: getMetadataArray(ctx, pid, mm, proc.Cmdline), Env: getMetadataArray(ctx, pid, mm, proc.Environ), + CWD: getCWD(ctx, t, pid), }, nil } diff --git a/runsc/container/trace_test.go b/runsc/container/trace_test.go index 1bb4a9469..3ad45ef52 100644 --- a/runsc/container/trace_test.go +++ b/runsc/container/trace_test.go @@ -302,6 +302,7 @@ func TestProcfsDump(t *testing.T) { spec, conf := sleepSpecConf(t) testEnv := "GVISOR_IS_GREAT=true" spec.Process.Env = append(spec.Process.Env, testEnv) + spec.Process.Cwd = "/" _, bundleDir, cleanup, err := testutil.SetupContainer(spec, conf) if err != nil { t.Fatalf("error setting up container: %v", err) @@ -360,4 +361,8 @@ func TestProcfsDump(t *testing.T) { if !testEnvFound { t.Errorf("expected to find %q env but did not find it, got env %+v", testEnv, procfsDump[0].Env) } + + if spec.Process.Cwd != procfsDump[0].CWD { + t.Errorf("expected CWD %q, got %q", spec.Process.Cwd, procfsDump[0].CWD) + } }