diff options
author | Nicolas Lacasse <nlacasse@google.com> | 2019-01-14 20:33:29 -0800 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2019-01-14 20:34:28 -0800 |
commit | dc8450b5676d4c4ac9bcfa23cabd862e0060527d (patch) | |
tree | a4ef1ad59764f46f674b7003221ba8ae399b9e65 /pkg/sentry/kernel/pipe | |
parent | 343ebe9789087b099ea7feae19879f5c24e59bf1 (diff) |
Remove fs.Handle, ramfs.Entry, and all the DeprecatedFileOperations.
More helper structs have been added to the fsutil package to make it easier to
implement fs.InodeOperations and fs.FileOperations.
PiperOrigin-RevId: 229305982
Change-Id: Ib6f8d3862f4216745116857913dbfa351530223b
Diffstat (limited to 'pkg/sentry/kernel/pipe')
-rw-r--r-- | pkg/sentry/kernel/pipe/node.go | 40 | ||||
-rw-r--r-- | pkg/sentry/kernel/pipe/node_test.go | 36 | ||||
-rw-r--r-- | pkg/sentry/kernel/pipe/pipe.go | 31 | ||||
-rw-r--r-- | pkg/sentry/kernel/pipe/reader_writer.go | 10 |
4 files changed, 57 insertions, 60 deletions
diff --git a/pkg/sentry/kernel/pipe/node.go b/pkg/sentry/kernel/pipe/node.go index 4b0e00b85..1336b6293 100644 --- a/pkg/sentry/kernel/pipe/node.go +++ b/pkg/sentry/kernel/pipe/node.go @@ -17,17 +17,30 @@ package pipe import ( "sync" + "gvisor.googlesource.com/gvisor/pkg/abi/linux" "gvisor.googlesource.com/gvisor/pkg/amutex" "gvisor.googlesource.com/gvisor/pkg/sentry/context" "gvisor.googlesource.com/gvisor/pkg/sentry/fs" + "gvisor.googlesource.com/gvisor/pkg/sentry/fs/fsutil" "gvisor.googlesource.com/gvisor/pkg/syserror" ) -// inodeOperations wraps fs.InodeOperations operations with common pipe opening semantics. +// inodeOperations implements fs.InodeOperations for pipes. // // +stateify savable type inodeOperations struct { - fs.InodeOperations + fsutil.InodeGenericChecker `state:"nosave"` + fsutil.InodeNoExtendedAttributes `state:"nosave"` + fsutil.InodeNoopRelease `state:"nosave"` + fsutil.InodeNoopTruncate `state:"nosave"` + fsutil.InodeNoopWriteOut `state:"nosave"` + fsutil.InodeNotDirectory `state:"nosave"` + fsutil.InodeNotMappable `state:"nosave"` + fsutil.InodeNotSocket `state:"nosave"` + fsutil.InodeNotSymlink `state:"nosave"` + fsutil.InodeNotVirtual `state:"nosave"` + + fsutil.InodeSimpleAttributes // mu protects the fields below. mu sync.Mutex `state:"nosave"` @@ -46,12 +59,15 @@ type inodeOperations struct { wWakeup chan struct{} `state:"nosave"` } -// NewInodeOperations creates a new pipe fs.InodeOperations. -func NewInodeOperations(base fs.InodeOperations, p *Pipe) fs.InodeOperations { +var _ fs.InodeOperations = (*inodeOperations)(nil) + +// NewInodeOperations returns a new fs.InodeOperations for a given pipe. +func NewInodeOperations(ctx context.Context, perms fs.FilePermissions, p *Pipe) *inodeOperations { return &inodeOperations{ - InodeOperations: base, - p: p, + InodeSimpleAttributes: fsutil.NewInodeSimpleAttributes(ctx, fs.FileOwnerFromContext(ctx), perms, linux.PIPEFS_MAGIC), + p: p, } + } // GetFile implements fs.InodeOperations.GetFile. Named pipes have special blocking @@ -164,18 +180,6 @@ func (i *inodeOperations) waitFor(wakeupChan *chan struct{}, sleeper amutex.Slee } } -// Truncate implements fs.InodeOperations.Truncate -// -// This method is required to override the default i.InodeOperations.Truncate -// which may return ErrInvalidOperation, this allows open related -// syscalls to set the O_TRUNC flag without returning an error by -// calling Truncate directly during openat. The ftruncate and truncate -// system calls will check that the file is an actual file and return -// EINVAL because it's a PIPE, making this behavior consistent with linux. -func (i *inodeOperations) Truncate(context.Context, *fs.Inode, int64) error { - return nil -} - // newHandleLocked signals a new pipe reader or writer depending on where // 'wakeupChan' points. This unblocks any corresponding reader or writer // waiting for the other end of the channel to be opened, see Fifo.waitFor. diff --git a/pkg/sentry/kernel/pipe/node_test.go b/pkg/sentry/kernel/pipe/node_test.go index eda551594..ad103b195 100644 --- a/pkg/sentry/kernel/pipe/node_test.go +++ b/pkg/sentry/kernel/pipe/node_test.go @@ -53,6 +53,10 @@ type openResult struct { error } +var perms fs.FilePermissions = fs.FilePermissions{ + User: fs.PermMask{Read: true, Write: true}, +} + func testOpenOrDie(ctx context.Context, t *testing.T, n fs.InodeOperations, flags fs.FileFlags, doneChan chan<- struct{}) (*fs.File, error) { file, err := n.GetFile(ctx, nil, flags) if err != nil { @@ -93,8 +97,8 @@ func assertRecvBlocks(t *testing.T, c <-chan struct{}, blockDuration time.Durati } func TestReadOpenBlocksForWriteOpen(t *testing.T) { - f := NewInodeOperations(nil, newNamedPipe(t)) ctx := newSleeperContext(t) + f := NewInodeOperations(ctx, perms, newNamedPipe(t)) rDone := make(chan struct{}) go testOpenOrDie(ctx, t, f, fs.FileFlags{Read: true}, rDone) @@ -111,8 +115,8 @@ func TestReadOpenBlocksForWriteOpen(t *testing.T) { } func TestWriteOpenBlocksForReadOpen(t *testing.T) { - f := NewInodeOperations(nil, newNamedPipe(t)) ctx := newSleeperContext(t) + f := NewInodeOperations(ctx, perms, newNamedPipe(t)) wDone := make(chan struct{}) go testOpenOrDie(ctx, t, f, fs.FileFlags{Write: true}, wDone) @@ -129,8 +133,8 @@ func TestWriteOpenBlocksForReadOpen(t *testing.T) { } func TestMultipleWriteOpenDoesntCountAsReadOpen(t *testing.T) { - f := NewInodeOperations(nil, newNamedPipe(t)) ctx := newSleeperContext(t) + f := NewInodeOperations(ctx, perms, newNamedPipe(t)) rDone1 := make(chan struct{}) rDone2 := make(chan struct{}) @@ -151,8 +155,8 @@ func TestMultipleWriteOpenDoesntCountAsReadOpen(t *testing.T) { } func TestClosedReaderBlocksWriteOpen(t *testing.T) { - f := NewInodeOperations(nil, newNamedPipe(t)) ctx := newSleeperContext(t) + f := NewInodeOperations(ctx, perms, newNamedPipe(t)) rFile, _ := testOpenOrDie(ctx, t, f, fs.FileFlags{Read: true, NonBlocking: true}, nil) rFile.DecRef() @@ -172,8 +176,8 @@ func TestClosedReaderBlocksWriteOpen(t *testing.T) { } func TestReadWriteOpenNeverBlocks(t *testing.T) { - f := NewInodeOperations(nil, newNamedPipe(t)) ctx := newSleeperContext(t) + f := NewInodeOperations(ctx, perms, newNamedPipe(t)) rwDone := make(chan struct{}) // Open for read-write never wait for a reader or writer, even if the @@ -183,8 +187,8 @@ func TestReadWriteOpenNeverBlocks(t *testing.T) { } func TestReadWriteOpenUnblocksReadOpen(t *testing.T) { - f := NewInodeOperations(nil, newNamedPipe(t)) ctx := newSleeperContext(t) + f := NewInodeOperations(ctx, perms, newNamedPipe(t)) rDone := make(chan struct{}) go testOpenOrDie(ctx, t, f, fs.FileFlags{Read: true}, rDone) @@ -197,8 +201,8 @@ func TestReadWriteOpenUnblocksReadOpen(t *testing.T) { } func TestReadWriteOpenUnblocksWriteOpen(t *testing.T) { - f := NewInodeOperations(nil, newNamedPipe(t)) ctx := newSleeperContext(t) + f := NewInodeOperations(ctx, perms, newNamedPipe(t)) wDone := make(chan struct{}) go testOpenOrDie(ctx, t, f, fs.FileFlags{Write: true}, wDone) @@ -211,8 +215,8 @@ func TestReadWriteOpenUnblocksWriteOpen(t *testing.T) { } func TestBlockedOpenIsCancellable(t *testing.T) { - f := NewInodeOperations(nil, newNamedPipe(t)) ctx := newSleeperContext(t) + f := NewInodeOperations(ctx, perms, newNamedPipe(t)) done := make(chan openResult) go testOpen(ctx, t, f, fs.FileFlags{Read: true}, done) @@ -233,18 +237,18 @@ func TestBlockedOpenIsCancellable(t *testing.T) { } } -func TestNonblockingReadOpenNoWriters(t *testing.T) { - f := NewInodeOperations(nil, newNamedPipe(t)) +func TestNonblockingReadOpenFileNoWriters(t *testing.T) { ctx := newSleeperContext(t) + f := NewInodeOperations(ctx, perms, newNamedPipe(t)) if _, err := testOpen(ctx, t, f, fs.FileFlags{Read: true, NonBlocking: true}, nil); err != nil { t.Fatalf("Nonblocking open for read failed with error %v.", err) } } -func TestNonblockingWriteOpenNoReaders(t *testing.T) { - f := NewInodeOperations(nil, newNamedPipe(t)) +func TestNonblockingWriteOpenFileNoReaders(t *testing.T) { ctx := newSleeperContext(t) + f := NewInodeOperations(ctx, perms, newNamedPipe(t)) if _, err := testOpen(ctx, t, f, fs.FileFlags{Write: true, NonBlocking: true}, nil); err != syserror.ENXIO { t.Fatalf("Nonblocking open for write failed unexpected error %v.", err) @@ -252,8 +256,8 @@ func TestNonblockingWriteOpenNoReaders(t *testing.T) { } func TestNonBlockingReadOpenWithWriter(t *testing.T) { - f := NewInodeOperations(nil, newNamedPipe(t)) ctx := newSleeperContext(t) + f := NewInodeOperations(ctx, perms, newNamedPipe(t)) wDone := make(chan struct{}) go testOpenOrDie(ctx, t, f, fs.FileFlags{Write: true}, wDone) @@ -271,8 +275,8 @@ func TestNonBlockingReadOpenWithWriter(t *testing.T) { } func TestNonBlockingWriteOpenWithReader(t *testing.T) { - f := NewInodeOperations(nil, newNamedPipe(t)) ctx := newSleeperContext(t) + f := NewInodeOperations(ctx, perms, newNamedPipe(t)) rDone := make(chan struct{}) go testOpenOrDie(ctx, t, f, fs.FileFlags{Read: true}, rDone) @@ -290,8 +294,8 @@ func TestNonBlockingWriteOpenWithReader(t *testing.T) { } func TestAnonReadOpen(t *testing.T) { - f := NewInodeOperations(nil, newAnonPipe(t)) ctx := newSleeperContext(t) + f := NewInodeOperations(ctx, perms, newAnonPipe(t)) if _, err := testOpen(ctx, t, f, fs.FileFlags{Read: true}, nil); err != nil { t.Fatalf("open anon pipe for read failed: %v", err) @@ -299,8 +303,8 @@ func TestAnonReadOpen(t *testing.T) { } func TestAnonWriteOpen(t *testing.T) { - f := NewInodeOperations(nil, newAnonPipe(t)) ctx := newSleeperContext(t) + f := NewInodeOperations(ctx, perms, newAnonPipe(t)) if _, err := testOpen(ctx, t, f, fs.FileFlags{Write: true}, nil); err != nil { t.Fatalf("open anon pipe for write failed: %v", err) diff --git a/pkg/sentry/kernel/pipe/pipe.go b/pkg/sentry/kernel/pipe/pipe.go index 126054826..fad077d2d 100644 --- a/pkg/sentry/kernel/pipe/pipe.go +++ b/pkg/sentry/kernel/pipe/pipe.go @@ -25,11 +25,9 @@ import ( "sync/atomic" "syscall" - "gvisor.googlesource.com/gvisor/pkg/abi/linux" "gvisor.googlesource.com/gvisor/pkg/ilist" "gvisor.googlesource.com/gvisor/pkg/sentry/context" "gvisor.googlesource.com/gvisor/pkg/sentry/fs" - "gvisor.googlesource.com/gvisor/pkg/sentry/fs/fsutil" "gvisor.googlesource.com/gvisor/pkg/sentry/usermem" "gvisor.googlesource.com/gvisor/pkg/syserror" "gvisor.googlesource.com/gvisor/pkg/waiter" @@ -50,7 +48,7 @@ type Pipe struct { isNamed bool // The dirent backing this pipe. Shared by all readers and writers. - dirent *fs.Dirent + Dirent *fs.Dirent // The buffered byte queue. data ilist.List @@ -97,28 +95,19 @@ func NewPipe(ctx context.Context, isNamed bool, sizeBytes, atomicIOBytes int) *P // Build the fs.Dirent of this pipe, shared by all fs.Files associated // with this pipe. + perms := fs.FilePermissions{ + User: fs.PermMask{Read: true, Write: true}, + } + iops := NewInodeOperations(ctx, perms, p) ino := pipeDevice.NextIno() - base := fsutil.NewSimpleInodeOperations(fsutil.InodeSimpleAttributes{ - FSType: linux.PIPEFS_MAGIC, - UAttr: fs.WithCurrentTime(ctx, fs.UnstableAttr{ - Owner: fs.FileOwnerFromContext(ctx), - Perms: fs.FilePermissions{ - User: fs.PermMask{Read: true, Write: true}, - }, - Links: 1, - }), - }) sattr := fs.StableAttr{ Type: fs.Pipe, DeviceID: pipeDevice.DeviceID(), InodeID: ino, BlockSize: int64(atomicIOBytes), } - // There is no real filesystem backing this pipe, so we pass in a nil - // Filesystem. - sb := fs.NewNonCachingMountSource(nil, fs.MountSourceFlags{}) - p.dirent = fs.NewDirent(fs.NewInode(NewInodeOperations(base, p), sb, sattr), fmt.Sprintf("pipe:[%d]", ino)) - + ms := fs.NewPseudoMountSource() + p.Dirent = fs.NewDirent(fs.NewInode(iops, ms, sattr), fmt.Sprintf("pipe:[%d]", ino)) return p } @@ -135,7 +124,7 @@ func NewConnectedPipe(ctx context.Context, sizeBytes int, atomicIOBytes int) (*f // ROpen opens the pipe for reading. func (p *Pipe) ROpen(ctx context.Context) *fs.File { p.rOpen() - return fs.NewFile(ctx, p.dirent, fs.FileFlags{Read: true}, &Reader{ + return fs.NewFile(ctx, p.Dirent, fs.FileFlags{Read: true}, &Reader{ ReaderWriter: ReaderWriter{Pipe: p}, }) } @@ -143,7 +132,7 @@ func (p *Pipe) ROpen(ctx context.Context) *fs.File { // WOpen opens the pipe for writing. func (p *Pipe) WOpen(ctx context.Context) *fs.File { p.wOpen() - return fs.NewFile(ctx, p.dirent, fs.FileFlags{Write: true}, &Writer{ + return fs.NewFile(ctx, p.Dirent, fs.FileFlags{Write: true}, &Writer{ ReaderWriter: ReaderWriter{Pipe: p}, }) } @@ -152,7 +141,7 @@ func (p *Pipe) WOpen(ctx context.Context) *fs.File { func (p *Pipe) RWOpen(ctx context.Context) *fs.File { p.rOpen() p.wOpen() - return fs.NewFile(ctx, p.dirent, fs.FileFlags{Read: true, Write: true}, &ReaderWriter{ + return fs.NewFile(ctx, p.Dirent, fs.FileFlags{Read: true, Write: true}, &ReaderWriter{ Pipe: p, }) } diff --git a/pkg/sentry/kernel/pipe/reader_writer.go b/pkg/sentry/kernel/pipe/reader_writer.go index 36be1efc3..028175530 100644 --- a/pkg/sentry/kernel/pipe/reader_writer.go +++ b/pkg/sentry/kernel/pipe/reader_writer.go @@ -35,11 +35,11 @@ import ( // // +stateify savable type ReaderWriter struct { - fsutil.PipeSeek `state:"nosave"` - fsutil.NotDirReaddir `state:"nosave"` - fsutil.NoFsync `state:"nosave"` - fsutil.NoopFlush `state:"nosave"` - fsutil.NoMMap `state:"nosave"` + fsutil.FilePipeSeek `state:"nosave"` + fsutil.FileNotDirReaddir `state:"nosave"` + fsutil.FileNoFsync `state:"nosave"` + fsutil.FileNoopFlush `state:"nosave"` + fsutil.FileNoMMap `state:"nosave"` *Pipe } |