Port sentry control Cat method to VFS2.

And re-enable the cat container_test.

Updates #6742

PiperOrigin-RevId: 449578758
This commit is contained in:
Nicolas Lacasse
2022-05-18 14:34:18 -07:00
committed by gVisor bot
parent 4dcac904e1
commit 295fd0a977
3 changed files with 68 additions and 65 deletions
+1
View File
@@ -29,6 +29,7 @@ go_library(
"//pkg/context",
"//pkg/eventchannel",
"//pkg/fd",
"//pkg/fspath",
"//pkg/log",
"//pkg/sentry/fdimport",
"//pkg/sentry/fs",
+22 -19
View File
@@ -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
}
+45 -46
View File
@@ -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) {