summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/kernel/pipe
diff options
context:
space:
mode:
authorNicolas Lacasse <nlacasse@google.com>2019-01-14 20:33:29 -0800
committerShentubot <shentubot@google.com>2019-01-14 20:34:28 -0800
commitdc8450b5676d4c4ac9bcfa23cabd862e0060527d (patch)
treea4ef1ad59764f46f674b7003221ba8ae399b9e65 /pkg/sentry/kernel/pipe
parent343ebe9789087b099ea7feae19879f5c24e59bf1 (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.go40
-rw-r--r--pkg/sentry/kernel/pipe/node_test.go36
-rw-r--r--pkg/sentry/kernel/pipe/pipe.go31
-rw-r--r--pkg/sentry/kernel/pipe/reader_writer.go10
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
}