From 295fd0a9771f3411600f1066b4e1f06e444928c7 Mon Sep 17 00:00:00 2001 From: Nicolas Lacasse Date: Wed, 18 May 2022 14:32:06 -0700 Subject: [PATCH] Port sentry control Cat method to VFS2. And re-enable the cat container_test. Updates #6742 PiperOrigin-RevId: 449578758 --- pkg/sentry/control/BUILD | 1 + pkg/sentry/control/fs.go | 41 +++++++------- runsc/container/container_test.go | 91 +++++++++++++++---------------- 3 files changed, 68 insertions(+), 65 deletions(-) diff --git a/pkg/sentry/control/BUILD b/pkg/sentry/control/BUILD index 3d72b65a3..d42c2a84b 100644 --- a/pkg/sentry/control/BUILD +++ b/pkg/sentry/control/BUILD @@ -29,6 +29,7 @@ go_library( "//pkg/context", "//pkg/eventchannel", "//pkg/fd", + "//pkg/fspath", "//pkg/log", "//pkg/sentry/fdimport", "//pkg/sentry/fs", diff --git a/pkg/sentry/control/fs.go b/pkg/sentry/control/fs.go index d19b21f2d..9121eed3b 100644 --- a/pkg/sentry/control/fs.go +++ b/pkg/sentry/control/fs.go @@ -19,9 +19,12 @@ import ( "io" "os" + "gvisor.dev/gvisor/pkg/abi/linux" "gvisor.dev/gvisor/pkg/context" - "gvisor.dev/gvisor/pkg/sentry/fs" + "gvisor.dev/gvisor/pkg/fspath" "gvisor.dev/gvisor/pkg/sentry/kernel" + "gvisor.dev/gvisor/pkg/sentry/kernel/auth" + "gvisor.dev/gvisor/pkg/sentry/vfs" "gvisor.dev/gvisor/pkg/urpc" "gvisor.dev/gvisor/pkg/usermem" ) @@ -57,37 +60,37 @@ func (f *Fs) Cat(o *CatOpts, _ *struct{}) error { return nil } -// fileReader encapsulates a fs.File and provides an io.Reader interface. -type fileReader struct { - ctx context.Context - file *fs.File +// fdReader provides an io.Reader interface for a vfs.FileDescription. +type fdReader struct { + ctx context.Context + fd *vfs.FileDescription } // Read implements io.Reader.Read. -func (f *fileReader) Read(p []byte) (int, error) { - n, err := f.file.Readv(f.ctx, usermem.BytesIOSequence(p)) +func (f *fdReader) Read(p []byte) (int, error) { + n, err := f.fd.Read(f.ctx, usermem.BytesIOSequence(p), vfs.ReadOptions{}) return int(n), err } func cat(k *kernel.Kernel, path string, output *os.File) error { ctx := k.SupervisorContext() - mns := k.GlobalInit().Leader().MountNamespace() + creds := auth.NewRootCredentials(k.RootUserNamespace()) + mns := k.GlobalInit().Leader().MountNamespaceVFS2() root := mns.Root() defer root.DecRef(ctx) - remainingTraversals := uint(fs.DefaultTraversalLimit) - d, err := mns.FindInode(ctx, root, nil, path, &remainingTraversals) + fd, err := k.VFS().OpenAt(ctx, creds, &vfs.PathOperation{ + Root: root, + Start: root, + Path: fspath.Parse(path), + }, &vfs.OpenOptions{ + Flags: linux.O_RDONLY, + }) if err != nil { - return fmt.Errorf("cannot find file %s: %v", path, err) + return fmt.Errorf("failed to open file %s: %v", path, err) } - defer d.DecRef(ctx) + defer fd.DecRef(ctx) - file, err := d.Inode.GetFile(ctx, d, fs.FileFlags{Read: true}) - if err != nil { - return fmt.Errorf("cannot get file for path %s: %v", path, err) - } - defer file.DecRef(ctx) - - _, err = io.Copy(output, &fileReader{ctx: ctx, file: file}) + _, err = io.Copy(output, &fdReader{ctx: ctx, fd: fd}) return err } diff --git a/runsc/container/container_test.go b/runsc/container/container_test.go index c0f045414..518387554 100644 --- a/runsc/container/container_test.go +++ b/runsc/container/container_test.go @@ -2533,60 +2533,59 @@ func TestRlimitsExec(t *testing.T) { } // TestCat creates a file and checks that cat generates the expected output. -// TODO(gvisor.dev/issue/6742): Add VFS2 support. -// func TestCat(t *testing.T) { -// f, err := ioutil.TempFile(testutil.TmpDir(), "test-case") -// if err != nil { -// t.Fatalf("ioutil.TempFile failed: %v", err) -// } -// defer os.RemoveAll(f.Name()) +func TestCat(t *testing.T) { + f, err := ioutil.TempFile(testutil.TmpDir(), "test-case") + if err != nil { + t.Fatalf("ioutil.TempFile failed: %v", err) + } + defer os.RemoveAll(f.Name()) -// content := "test-cat" -// if _, err := f.WriteString(content); err != nil { -// t.Fatalf("f.WriteString(): %v", err) -// } -// f.Close() + content := "test-cat" + if _, err := f.WriteString(content); err != nil { + t.Fatalf("f.WriteString(): %v", err) + } + f.Close() -// spec, conf := sleepSpecConf(t) -// _, bundleDir, cleanup, err := testutil.SetupContainer(spec, conf) -// if err != nil { -// t.Fatalf("error setting up container: %v", err) -// } -// defer cleanup() + spec, conf := sleepSpecConf(t) + _, bundleDir, cleanup, err := testutil.SetupContainer(spec, conf) + if err != nil { + t.Fatalf("error setting up container: %v", err) + } + defer cleanup() -// args := Args{ -// ID: testutil.RandomContainerID(), -// Spec: spec, -// BundleDir: bundleDir, -// } + args := Args{ + ID: testutil.RandomContainerID(), + Spec: spec, + BundleDir: bundleDir, + } -// cont, err := New(conf, args) -// if err != nil { -// t.Fatalf("Creating container: %v", err) -// } -// defer cont.Destroy() + cont, err := New(conf, args) + if err != nil { + t.Fatalf("Creating container: %v", err) + } + defer cont.Destroy() -// if err := cont.Start(conf); err != nil { -// t.Fatalf("starting container: %v", err) -// } + if err := cont.Start(conf); err != nil { + t.Fatalf("starting container: %v", err) + } -// r, w, err := os.Pipe() -// if err != nil { -// t.Fatalf("os.Create(): %v", err) -// } + r, w, err := os.Pipe() + if err != nil { + t.Fatalf("os.Create(): %v", err) + } -// if err := cont.Cat([]string{f.Name()}, w); err != nil { -// t.Fatalf("error cat from container: %v", err) -// } + if err := cont.Cat([]string{f.Name()}, w); err != nil { + t.Fatalf("error cat from container: %v", err) + } -// buf := make([]byte, 1024) -// if _, err := r.Read(buf); err != nil { -// t.Fatalf("Read out: %v", err) -// } -// if got, want := string(buf), content; !strings.Contains(got, want) { -// t.Errorf("out got %s, want include %s", buf, want) -// } -// } + buf := make([]byte, 1024) + if _, err := r.Read(buf); err != nil { + t.Fatalf("Read out: %v", err) + } + if got, want := string(buf), content; !strings.Contains(got, want) { + t.Errorf("out got %s, want include %s", buf, want) + } +} // TestUsage checks that usage generates the expected memory usage. func TestUsage(t *testing.T) {