summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/fs/dev
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/sentry/fs/dev')
-rw-r--r--pkg/sentry/fs/dev/BUILD1
-rw-r--r--pkg/sentry/fs/dev/dev.go29
-rw-r--r--pkg/sentry/fs/dev/fs.go2
-rw-r--r--pkg/sentry/fs/dev/full.go55
-rw-r--r--pkg/sentry/fs/dev/null.go88
-rw-r--r--pkg/sentry/fs/dev/random.go55
6 files changed, 151 insertions, 79 deletions
diff --git a/pkg/sentry/fs/dev/BUILD b/pkg/sentry/fs/dev/BUILD
index b17b5202c..b9cfae05f 100644
--- a/pkg/sentry/fs/dev/BUILD
+++ b/pkg/sentry/fs/dev/BUILD
@@ -32,5 +32,6 @@ go_library(
"//pkg/sentry/safemem",
"//pkg/sentry/usermem",
"//pkg/syserror",
+ "//pkg/waiter",
],
)
diff --git a/pkg/sentry/fs/dev/dev.go b/pkg/sentry/fs/dev/dev.go
index 3e127bf04..f8e8099f7 100644
--- a/pkg/sentry/fs/dev/dev.go
+++ b/pkg/sentry/fs/dev/dev.go
@@ -16,6 +16,8 @@
package dev
import (
+ "math"
+
"gvisor.googlesource.com/gvisor/pkg/sentry/context"
"gvisor.googlesource.com/gvisor/pkg/sentry/fs"
"gvisor.googlesource.com/gvisor/pkg/sentry/fs/ashmem"
@@ -26,13 +28,6 @@ import (
"gvisor.googlesource.com/gvisor/pkg/sentry/usermem"
)
-// Dev is the root node.
-//
-// +stateify savable
-type Dev struct {
- ramfs.Dir
-}
-
func newCharacterDevice(iops fs.InodeOperations, msrc *fs.MountSource) *fs.Inode {
return fs.NewInode(iops, msrc, fs.StableAttr{
DeviceID: devDevice.DeviceID(),
@@ -43,8 +38,7 @@ func newCharacterDevice(iops fs.InodeOperations, msrc *fs.MountSource) *fs.Inode
}
func newDirectory(ctx context.Context, msrc *fs.MountSource) *fs.Inode {
- iops := &ramfs.Dir{}
- iops.InitDir(ctx, map[string]*fs.Inode{}, fs.RootOwner, fs.FilePermsFromMode(0555))
+ iops := ramfs.NewDir(ctx, nil, fs.RootOwner, fs.FilePermsFromMode(0555))
return fs.NewInode(iops, msrc, fs.StableAttr{
DeviceID: devDevice.DeviceID(),
InodeID: devDevice.NextIno(),
@@ -54,8 +48,7 @@ func newDirectory(ctx context.Context, msrc *fs.MountSource) *fs.Inode {
}
func newSymlink(ctx context.Context, target string, msrc *fs.MountSource) *fs.Inode {
- iops := &ramfs.Symlink{}
- iops.InitSymlink(ctx, fs.RootOwner, target)
+ iops := ramfs.NewSymlink(ctx, fs.RootOwner, target)
return fs.NewInode(iops, msrc, fs.StableAttr{
DeviceID: devDevice.DeviceID(),
InodeID: devDevice.NextIno(),
@@ -66,8 +59,6 @@ func newSymlink(ctx context.Context, target string, msrc *fs.MountSource) *fs.In
// New returns the root node of a device filesystem.
func New(ctx context.Context, msrc *fs.MountSource, binderEnabled bool, ashmemEnabled bool) *fs.Inode {
- d := &Dev{}
-
contents := map[string]*fs.Inode{
"fd": newSymlink(ctx, "/proc/self/fd", msrc),
"stdin": newSymlink(ctx, "/proc/self/fd/0", msrc),
@@ -114,11 +105,19 @@ func New(ctx context.Context, msrc *fs.MountSource, binderEnabled bool, ashmemEn
contents["ashmem"] = newCharacterDevice(ashmem, msrc)
}
- d.InitDir(ctx, contents, fs.RootOwner, fs.FilePermsFromMode(0555))
- return fs.NewInode(d, msrc, fs.StableAttr{
+ iops := ramfs.NewDir(ctx, contents, fs.RootOwner, fs.FilePermsFromMode(0555))
+ return fs.NewInode(iops, msrc, fs.StableAttr{
DeviceID: devDevice.DeviceID(),
InodeID: devDevice.NextIno(),
BlockSize: usermem.PageSize,
Type: fs.Directory,
})
}
+
+// readZeros implements fs.FileOperations.Read with infinite null bytes.
+type readZeros struct{}
+
+// Read implements fs.FileOperations.Read.
+func (readZeros) Read(ctx context.Context, file *fs.File, dst usermem.IOSequence, offset int64) (int64, error) {
+ return dst.ZeroOut(ctx, math.MaxInt64)
+}
diff --git a/pkg/sentry/fs/dev/fs.go b/pkg/sentry/fs/dev/fs.go
index d96f4f423..abfe689f0 100644
--- a/pkg/sentry/fs/dev/fs.go
+++ b/pkg/sentry/fs/dev/fs.go
@@ -33,6 +33,8 @@ const ashmemEnabledKey = "ashmem_enabled"
// +stateify savable
type filesystem struct{}
+var _ fs.Filesystem = (*filesystem)(nil)
+
func init() {
fs.RegisterFilesystem(&filesystem{})
}
diff --git a/pkg/sentry/fs/dev/full.go b/pkg/sentry/fs/dev/full.go
index eeda646ab..cbdd40161 100644
--- a/pkg/sentry/fs/dev/full.go
+++ b/pkg/sentry/fs/dev/full.go
@@ -15,41 +15,64 @@
package dev
import (
- "math"
-
"gvisor.googlesource.com/gvisor/pkg/abi/linux"
"gvisor.googlesource.com/gvisor/pkg/sentry/context"
"gvisor.googlesource.com/gvisor/pkg/sentry/fs"
- "gvisor.googlesource.com/gvisor/pkg/sentry/fs/ramfs"
+ "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"
)
// fullDevice is used to implement /dev/full.
//
// +stateify savable
type fullDevice struct {
- ramfs.Entry
+ 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.InodeVirtual `state:"nosave"`
+
+ fsutil.InodeSimpleAttributes
}
+var _ fs.InodeOperations = (*fullDevice)(nil)
+
func newFullDevice(ctx context.Context, owner fs.FileOwner, mode linux.FileMode) *fullDevice {
- f := &fullDevice{}
- f.InitEntry(ctx, owner, fs.FilePermsFromMode(mode))
+ f := &fullDevice{
+ InodeSimpleAttributes: fsutil.NewInodeSimpleAttributes(ctx, owner, fs.FilePermsFromMode(mode), linux.TMPFS_MAGIC),
+ }
return f
}
-// DeprecatedPwritev implements fs.InodeOperations.DeprecatedPwritev by
-// returining ENOSPC.
-func (f *fullDevice) DeprecatedPwritev(_ context.Context, _ usermem.IOSequence, _ int64) (int64, error) {
- return 0, syserror.ENOSPC
+// GetFile implements fs.InodeOperations.GetFile.
+func (f *fullDevice) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.FileFlags) (*fs.File, error) {
+ flags.Pread = true
+ return fs.NewFile(ctx, dirent, flags, &fullFileOperations{}), nil
}
-// DeprecatedPreadv implements fs.InodeOperations.DeprecatedPreadv.
-func (f *fullDevice) DeprecatedPreadv(ctx context.Context, dst usermem.IOSequence, _ int64) (int64, error) {
- return dst.ZeroOut(ctx, math.MaxInt64)
+// +stateify savable
+type fullFileOperations struct {
+ waiter.AlwaysReady `state:"nosave"`
+ fsutil.FileGenericSeek `state:"nosave"`
+ fsutil.FileNoIoctl `state:"nosave"`
+ fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FileNoopFlush `state:"nosave"`
+ fsutil.FileNoopFsync `state:"nosave"`
+ fsutil.FileNoopRelease `state:"nosave"`
+ fsutil.FileNotDirReaddir `state:"nosave"`
+ readZeros `state:"nosave"`
}
-// Truncate should be simply ignored for character devices on linux.
-func (f *fullDevice) Truncate(context.Context, *fs.Inode, int64) error {
- return nil
+var _ fs.FileOperations = (*fullFileOperations)(nil)
+
+// Write implements FileOperations.Write.
+func (fullFileOperations) Write(context.Context, *fs.File, usermem.IOSequence, int64) (int64, error) {
+ return 0, syserror.ENOSPC
}
diff --git a/pkg/sentry/fs/dev/null.go b/pkg/sentry/fs/dev/null.go
index 68090f353..73fd09058 100644
--- a/pkg/sentry/fs/dev/null.go
+++ b/pkg/sentry/fs/dev/null.go
@@ -15,78 +15,104 @@
package dev
import (
- "io"
- "math"
-
"gvisor.googlesource.com/gvisor/pkg/abi/linux"
"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/fs/ramfs"
"gvisor.googlesource.com/gvisor/pkg/sentry/memmap"
"gvisor.googlesource.com/gvisor/pkg/sentry/mm"
"gvisor.googlesource.com/gvisor/pkg/sentry/platform"
- "gvisor.googlesource.com/gvisor/pkg/sentry/usermem"
+ "gvisor.googlesource.com/gvisor/pkg/waiter"
)
// +stateify savable
type nullDevice struct {
- ramfs.Entry
+ 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.InodeVirtual `state:"nosave"`
+
+ fsutil.InodeSimpleAttributes
}
+var _ fs.InodeOperations = (*nullDevice)(nil)
+
func newNullDevice(ctx context.Context, owner fs.FileOwner, mode linux.FileMode) *nullDevice {
- n := &nullDevice{}
- n.InitEntry(ctx, owner, fs.FilePermsFromMode(mode))
+ n := &nullDevice{
+ InodeSimpleAttributes: fsutil.NewInodeSimpleAttributes(ctx, owner, fs.FilePermsFromMode(mode), linux.TMPFS_MAGIC),
+ }
return n
}
-// DeprecatedPreadv reads data from the device.
-func (n *nullDevice) DeprecatedPreadv(ctx context.Context, dst usermem.IOSequence, offset int64) (int64, error) {
- return 0, io.EOF
-}
+// GetFile implements fs.FileOperations.GetFile.
+func (n *nullDevice) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.FileFlags) (*fs.File, error) {
+ flags.Pread = true
+ flags.Pwrite = true
-// DeprecatedPwritev discards writes.
-func (n *nullDevice) DeprecatedPwritev(_ context.Context, src usermem.IOSequence, offset int64) (int64, error) {
- return src.NumBytes(), nil
+ return fs.NewFile(ctx, dirent, flags, &nullFileOperations{}), nil
}
-// Truncate should be simply ignored for character devices on linux.
-func (n *nullDevice) Truncate(context.Context, *fs.Inode, int64) error {
- return nil
+// +stateify savable
+type nullFileOperations struct {
+ waiter.AlwaysReady `state:"nosave"`
+ fsutil.FileGenericSeek `state:"nosave"`
+ fsutil.FileNoIoctl `state:"nosave"`
+ fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FileNoopFlush `state:"nosave"`
+ fsutil.FileNoopFsync `state:"nosave"`
+ fsutil.FileNoopRead `state:"nosave"`
+ fsutil.FileNoopWrite `state:"nosave"`
+ fsutil.FileNoopRelease `state:"nosave"`
+ fsutil.FileNotDirReaddir `state:"nosave"`
}
+var _ fs.FileOperations = (*nullFileOperations)(nil)
+
// +stateify savable
type zeroDevice struct {
nullDevice
}
+var _ fs.InodeOperations = (*zeroDevice)(nil)
+
func newZeroDevice(ctx context.Context, owner fs.FileOwner, mode linux.FileMode) *zeroDevice {
- zd := &zeroDevice{}
- zd.InitEntry(ctx, owner, fs.FilePermsFromMode(mode))
+ zd := &zeroDevice{
+ nullDevice: nullDevice{
+ InodeSimpleAttributes: fsutil.NewInodeSimpleAttributes(ctx, owner, fs.FilePermsFromMode(mode), linux.TMPFS_MAGIC),
+ },
+ }
return zd
}
-// DeprecatedPreadv implements fs.InodeOperations.DeprecatedPreadv.
-func (zd *zeroDevice) DeprecatedPreadv(ctx context.Context, dst usermem.IOSequence, offset int64) (int64, error) {
- return dst.ZeroOut(ctx, math.MaxInt64)
-}
-
-// GetFile overrides ramfs.Entry.GetFile and returns a zeroFile instead.
+// GetFile implements fs.FileOperations.GetFile.
func (zd *zeroDevice) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.FileFlags) (*fs.File, error) {
- // Allow pread(2) and pwrite(2) on this file.
flags.Pread = true
flags.Pwrite = true
- return fs.NewFile(ctx, dirent, flags, &zeroFileOperations{
- FileOperations: &fsutil.Handle{HandleOperations: dirent.Inode.HandleOps()},
- }), nil
+ return fs.NewFile(ctx, dirent, flags, &zeroFileOperations{}), nil
}
// +stateify savable
type zeroFileOperations struct {
- fs.FileOperations
+ waiter.AlwaysReady `state:"nosave"`
+ fsutil.FileGenericSeek `state:"nosave"`
+ fsutil.FileNoopFlush `state:"nosave"`
+ fsutil.FileNoopFsync `state:"nosave"`
+ fsutil.FileNoopRelease `state:"nosave"`
+ fsutil.FileNoopWrite `state:"nosave"`
+ fsutil.FileNotDirReaddir `state:"nosave"`
+ fsutil.FileNoIoctl `state:"nosave"`
+ readZeros `state:"nosave"`
}
+var _ fs.FileOperations = (*zeroFileOperations)(nil)
+
// ConfigureMMap implements fs.FileOperations.ConfigureMMap.
func (*zeroFileOperations) ConfigureMMap(ctx context.Context, file *fs.File, opts *memmap.MMapOpts) error {
m, err := mm.NewSharedAnonMappable(opts.Length, platform.FromContext(ctx))
diff --git a/pkg/sentry/fs/dev/random.go b/pkg/sentry/fs/dev/random.go
index 33e4913e4..837b7793a 100644
--- a/pkg/sentry/fs/dev/random.go
+++ b/pkg/sentry/fs/dev/random.go
@@ -19,37 +19,58 @@ import (
"gvisor.googlesource.com/gvisor/pkg/rand"
"gvisor.googlesource.com/gvisor/pkg/sentry/context"
"gvisor.googlesource.com/gvisor/pkg/sentry/fs"
- "gvisor.googlesource.com/gvisor/pkg/sentry/fs/ramfs"
+ "gvisor.googlesource.com/gvisor/pkg/sentry/fs/fsutil"
"gvisor.googlesource.com/gvisor/pkg/sentry/safemem"
"gvisor.googlesource.com/gvisor/pkg/sentry/usermem"
+ "gvisor.googlesource.com/gvisor/pkg/waiter"
)
// +stateify savable
type randomDevice struct {
- ramfs.Entry
+ 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.InodeVirtual `state:"nosave"`
+
+ fsutil.InodeSimpleAttributes
}
+var _ fs.InodeOperations = (*randomDevice)(nil)
+
func newRandomDevice(ctx context.Context, owner fs.FileOwner, mode linux.FileMode) *randomDevice {
- r := &randomDevice{}
- r.InitEntry(ctx, owner, fs.FilePermsFromMode(mode))
+ r := &randomDevice{
+ InodeSimpleAttributes: fsutil.NewInodeSimpleAttributes(ctx, owner, fs.FilePermsFromMode(mode), linux.TMPFS_MAGIC),
+ }
return r
}
-// DeprecatedPreadv reads random data.
-func (*randomDevice) DeprecatedPreadv(ctx context.Context, dst usermem.IOSequence, offset int64) (int64, error) {
- return dst.CopyOutFrom(ctx, safemem.FromIOReader{rand.Reader})
+// GetFile implements fs.InodeOperations.GetFile.
+func (randomDevice) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.FileFlags) (*fs.File, error) {
+ return fs.NewFile(ctx, dirent, flags, &randomFileOperations{}), nil
}
-// DeprecatedPwritev implements fs.HandleOperations.DeprecatedPwritev.
-func (*randomDevice) DeprecatedPwritev(ctx context.Context, src usermem.IOSequence, offset int64) (int64, error) {
- // On Linux, "Writing to /dev/random or /dev/urandom will update the
- // entropy pool with the data written, but this will not result in a higher
- // entropy count" - random(4). We don't need to support this, but we do
- // need to support the write, so just make it a no-op a la /dev/null.
- return src.NumBytes(), nil
+// +stateify savable
+type randomFileOperations struct {
+ waiter.AlwaysReady `state:"nosave"`
+ fsutil.FileGenericSeek `state:"nosave"`
+ fsutil.FileNotDirReaddir `state:"nosave"`
+ fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FileNoopFsync `state:"nosave"`
+ fsutil.FileNoopFlush `state:"nosave"`
+ fsutil.FileNoIoctl `state:"nosave"`
+ fsutil.FileNoopRelease `state:"nosave"`
+ fsutil.FileNoopWrite `state:"nosave"`
}
-// Truncate should be simply ignored for character devices on linux.
-func (r *randomDevice) Truncate(context.Context, *fs.Inode, int64) error {
- return nil
+var _ fs.FileOperations = (*randomFileOperations)(nil)
+
+// Read implements fs.FileOperations.Read.
+func (randomFileOperations) Read(ctx context.Context, _ *fs.File, dst usermem.IOSequence, _ int64) (int64, error) {
+ return dst.CopyOutFrom(ctx, safemem.FromIOReader{rand.Reader})
}