summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/fs/fsutil/inode.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/sentry/fs/fsutil/inode.go')
-rw-r--r--pkg/sentry/fs/fsutil/inode.go380
1 files changed, 380 insertions, 0 deletions
diff --git a/pkg/sentry/fs/fsutil/inode.go b/pkg/sentry/fs/fsutil/inode.go
new file mode 100644
index 000000000..e1ad07df2
--- /dev/null
+++ b/pkg/sentry/fs/fsutil/inode.go
@@ -0,0 +1,380 @@
+// Copyright 2018 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package fsutil
+
+import (
+ "gvisor.googlesource.com/gvisor/pkg/sentry/context"
+ "gvisor.googlesource.com/gvisor/pkg/sentry/fs"
+ ktime "gvisor.googlesource.com/gvisor/pkg/sentry/kernel/time"
+ "gvisor.googlesource.com/gvisor/pkg/sentry/memmap"
+ "gvisor.googlesource.com/gvisor/pkg/sentry/usermem"
+ "gvisor.googlesource.com/gvisor/pkg/syserror"
+ "gvisor.googlesource.com/gvisor/pkg/tcpip/transport/unix"
+ "gvisor.googlesource.com/gvisor/pkg/waiter"
+)
+
+// NewSimpleInodeOperations constructs fs.InodeOperations from InodeSimpleAttributes.
+func NewSimpleInodeOperations(i InodeSimpleAttributes) fs.InodeOperations {
+ return &simpleInodeOperations{InodeSimpleAttributes: i}
+}
+
+// simpleInodeOperations is a simple implementation of Inode.
+type simpleInodeOperations struct {
+ DeprecatedFileOperations `state:"nosave"`
+ InodeNotDirectory `state:"nosave"`
+ InodeNotSocket `state:"nosave"`
+ InodeNotRenameable `state:"nosave"`
+ InodeNotOpenable `state:"nosave"`
+ InodeNotVirtual `state:"nosave"`
+ InodeNotSymlink `state:"nosave"`
+ InodeNoExtendedAttributes `state:"nosave"`
+ NoMappable `state:"nosave"`
+ NoopWriteOut `state:"nosave"`
+
+ InodeSimpleAttributes
+}
+
+// InodeSimpleAttributes implements a subset of the Inode interface. It provides
+// read-only access to attributes.
+type InodeSimpleAttributes struct {
+ // FSType is the filesystem type reported by StatFS.
+ FSType uint64
+
+ // UAttr are the unstable attributes of the Inode.
+ UAttr fs.UnstableAttr
+}
+
+// Release implements fs.InodeOperations.Release.
+func (i *InodeSimpleAttributes) Release(context.Context) {}
+
+// StatFS implements fs.InodeOperations.StatFS.
+func (i *InodeSimpleAttributes) StatFS(context.Context) (fs.Info, error) {
+ return fs.Info{Type: i.FSType}, nil
+}
+
+// UnstableAttr implements fs.InodeOperations.UnstableAttr.
+func (i *InodeSimpleAttributes) UnstableAttr(context.Context, *fs.Inode) (fs.UnstableAttr, error) {
+ return i.UAttr, nil
+}
+
+// Check implements fs.InodeOperations.Check.
+func (i *InodeSimpleAttributes) Check(ctx context.Context, inode *fs.Inode, p fs.PermMask) bool {
+ return fs.ContextCanAccessFile(ctx, inode, p)
+}
+
+// AddLink implements fs.InodeOperations.AddLink.
+func (*InodeSimpleAttributes) AddLink() {}
+
+// DropLink implements fs.InodeOperations.DropLink.
+func (*InodeSimpleAttributes) DropLink() {}
+
+// NotifyStatusChange implements fs.fs.InodeOperations.
+func (i *InodeSimpleAttributes) NotifyStatusChange(ctx context.Context) {
+ i.UAttr.StatusChangeTime = ktime.NowFromContext(ctx)
+}
+
+// SetPermissions implements fs.InodeOperations.SetPermissions.
+func (*InodeSimpleAttributes) SetPermissions(context.Context, *fs.Inode, fs.FilePermissions) bool {
+ return false
+}
+
+// SetOwner implements fs.InodeOperations.SetOwner.
+func (*InodeSimpleAttributes) SetOwner(context.Context, *fs.Inode, fs.FileOwner) error {
+ return syserror.EINVAL
+}
+
+// SetTimestamps implements fs.InodeOperations.SetTimestamps.
+func (*InodeSimpleAttributes) SetTimestamps(context.Context, *fs.Inode, fs.TimeSpec) error {
+ return syserror.EINVAL
+}
+
+// Truncate implements fs.InodeOperations.Truncate.
+func (*InodeSimpleAttributes) Truncate(context.Context, *fs.Inode, int64) error {
+ return syserror.EINVAL
+}
+
+// InMemoryAttributes implements utilities for updating in-memory unstable
+// attributes and extended attributes. It is not thread-safe.
+//
+// Users need not initialize Xattrs to non-nil (it will be initialized
+// when the first extended attribute is set.
+type InMemoryAttributes struct {
+ Unstable fs.UnstableAttr
+ Xattrs map[string][]byte
+}
+
+// SetPermissions updates the permissions to p.
+func (i *InMemoryAttributes) SetPermissions(ctx context.Context, p fs.FilePermissions) bool {
+ i.Unstable.Perms = p
+ i.Unstable.StatusChangeTime = ktime.NowFromContext(ctx)
+ return true
+}
+
+// SetOwner updates the file owner to owner.
+func (i *InMemoryAttributes) SetOwner(ctx context.Context, owner fs.FileOwner) error {
+ if owner.UID.Ok() {
+ i.Unstable.Owner.UID = owner.UID
+ }
+ if owner.GID.Ok() {
+ i.Unstable.Owner.GID = owner.GID
+ }
+ return nil
+}
+
+// SetTimestamps sets the timestamps to ts.
+func (i *InMemoryAttributes) SetTimestamps(ctx context.Context, ts fs.TimeSpec) error {
+ if ts.ATimeOmit && ts.MTimeOmit {
+ return nil
+ }
+
+ now := ktime.NowFromContext(ctx)
+ if !ts.ATimeOmit {
+ if ts.ATimeSetSystemTime {
+ i.Unstable.AccessTime = now
+ } else {
+ i.Unstable.AccessTime = ts.ATime
+ }
+ }
+ if !ts.MTimeOmit {
+ if ts.MTimeSetSystemTime {
+ i.Unstable.ModificationTime = now
+ } else {
+ i.Unstable.ModificationTime = ts.MTime
+ }
+ }
+ i.Unstable.StatusChangeTime = now
+ return nil
+}
+
+// TouchAccessTime updates access time to the current time.
+func (i *InMemoryAttributes) TouchAccessTime(ctx context.Context) {
+ i.Unstable.AccessTime = ktime.NowFromContext(ctx)
+}
+
+// TouchModificationTime updates modification and status change
+// time to the current time.
+func (i *InMemoryAttributes) TouchModificationTime(ctx context.Context) {
+ now := ktime.NowFromContext(ctx)
+ i.Unstable.ModificationTime = now
+ i.Unstable.StatusChangeTime = now
+}
+
+// TouchStatusChangeTime updates status change time to the current time.
+func (i *InMemoryAttributes) TouchStatusChangeTime(ctx context.Context) {
+ i.Unstable.StatusChangeTime = ktime.NowFromContext(ctx)
+}
+
+// Getxattr returns the extended attribute at name or ENOATTR if
+// it isn't set.
+func (i *InMemoryAttributes) Getxattr(name string) ([]byte, error) {
+ if value, ok := i.Xattrs[name]; ok {
+ return value, nil
+ }
+ return nil, syserror.ENOATTR
+}
+
+// Setxattr sets the extended attribute at name to value.
+func (i *InMemoryAttributes) Setxattr(name string, value []byte) error {
+ if i.Xattrs == nil {
+ i.Xattrs = make(map[string][]byte)
+ }
+ i.Xattrs[name] = value
+ return nil
+}
+
+// Listxattr returns the set of all currently set extended attributes.
+func (i *InMemoryAttributes) Listxattr() (map[string]struct{}, error) {
+ names := make(map[string]struct{}, len(i.Xattrs))
+ for name := range i.Xattrs {
+ names[name] = struct{}{}
+ }
+ return names, nil
+}
+
+// NoMappable returns a nil memmap.Mappable.
+type NoMappable struct{}
+
+// Mappable implements fs.InodeOperations.Mappable.
+func (NoMappable) Mappable(*fs.Inode) memmap.Mappable {
+ return nil
+}
+
+// NoopWriteOut is a no-op implementation of Inode.WriteOut.
+type NoopWriteOut struct{}
+
+// WriteOut is a no-op.
+func (NoopWriteOut) WriteOut(context.Context, *fs.Inode) error {
+ return nil
+}
+
+// InodeNotDirectory can be used by Inodes that are not directories.
+type InodeNotDirectory struct{}
+
+// Lookup implements fs.InodeOperations.Lookup.
+func (InodeNotDirectory) Lookup(context.Context, *fs.Inode, string) (*fs.Dirent, error) {
+ return nil, syserror.ENOTDIR
+}
+
+// Create implements fs.InodeOperations.Create.
+func (InodeNotDirectory) Create(context.Context, *fs.Inode, string, fs.FileFlags, fs.FilePermissions) (*fs.File, error) {
+ return nil, syserror.ENOTDIR
+}
+
+// CreateLink implements fs.InodeOperations.CreateLink.
+func (InodeNotDirectory) CreateLink(context.Context, *fs.Inode, string, string) error {
+ return syserror.ENOTDIR
+}
+
+// CreateHardLink implements fs.InodeOperations.CreateHardLink.
+func (InodeNotDirectory) CreateHardLink(context.Context, *fs.Inode, *fs.Inode, string) error {
+ return syserror.ENOTDIR
+}
+
+// CreateDirectory implements fs.InodeOperations.CreateDirectory.
+func (InodeNotDirectory) CreateDirectory(context.Context, *fs.Inode, string, fs.FilePermissions) error {
+ return syserror.ENOTDIR
+}
+
+// Bind implements fs.InodeOperations.Bind.
+func (InodeNotDirectory) Bind(context.Context, *fs.Inode, string, unix.BoundEndpoint, fs.FilePermissions) error {
+ return syserror.ENOTDIR
+}
+
+// CreateFifo implements fs.InodeOperations.CreateFifo.
+func (InodeNotDirectory) CreateFifo(context.Context, *fs.Inode, string, fs.FilePermissions) error {
+ return syserror.ENOTDIR
+}
+
+// Remove implements fs.InodeOperations.Remove.
+func (InodeNotDirectory) Remove(context.Context, *fs.Inode, string) error {
+ return syserror.ENOTDIR
+}
+
+// RemoveDirectory implements fs.InodeOperations.RemoveDirectory.
+func (InodeNotDirectory) RemoveDirectory(context.Context, *fs.Inode, string) error {
+ return syserror.ENOTDIR
+}
+
+// InodeNotSocket can be used by Inodes that are not sockets.
+type InodeNotSocket struct{}
+
+// BoundEndpoint implements fs.InodeOperations.BoundEndpoint.
+func (InodeNotSocket) BoundEndpoint(*fs.Inode, string) unix.BoundEndpoint {
+ return nil
+}
+
+// InodeNotRenameable can be used by Inodes that cannot be renamed.
+type InodeNotRenameable struct{}
+
+// Rename implements fs.InodeOperations.Rename.
+func (InodeNotRenameable) Rename(context.Context, *fs.Inode, string, *fs.Inode, string) error {
+ return syserror.EINVAL
+}
+
+// InodeNotOpenable can be used by Inodes that cannot be opened.
+type InodeNotOpenable struct{}
+
+// GetFile implements fs.InodeOperations.GetFile.
+func (InodeNotOpenable) GetFile(context.Context, *fs.Dirent, fs.FileFlags) (*fs.File, error) {
+ return nil, syserror.EIO
+}
+
+// InodeNotVirtual can be used by Inodes that are not virtual.
+type InodeNotVirtual struct{}
+
+// IsVirtual implements fs.InodeOperations.IsVirtual.
+func (InodeNotVirtual) IsVirtual() bool {
+ return false
+}
+
+// InodeNotSymlink can be used by Inodes that are not symlinks.
+type InodeNotSymlink struct{}
+
+// Readlink implements fs.InodeOperations.Readlink.
+func (InodeNotSymlink) Readlink(context.Context, *fs.Inode) (string, error) {
+ return "", syserror.ENOLINK
+}
+
+// Getlink implements fs.InodeOperations.Getlink.
+func (InodeNotSymlink) Getlink(context.Context, *fs.Inode) (*fs.Dirent, error) {
+ return nil, syserror.ENOLINK
+}
+
+// InodeNoExtendedAttributes can be used by Inodes that do not support
+// extended attributes.
+type InodeNoExtendedAttributes struct{}
+
+// Getxattr implements fs.InodeOperations.Getxattr.
+func (InodeNoExtendedAttributes) Getxattr(*fs.Inode, string) ([]byte, error) {
+ return nil, syserror.EOPNOTSUPP
+}
+
+// Setxattr implements fs.InodeOperations.Setxattr.
+func (InodeNoExtendedAttributes) Setxattr(*fs.Inode, string, []byte) error {
+ return syserror.EOPNOTSUPP
+}
+
+// Listxattr implements fs.InodeOperations.Listxattr.
+func (InodeNoExtendedAttributes) Listxattr(*fs.Inode) (map[string]struct{}, error) {
+ return nil, syserror.EOPNOTSUPP
+}
+
+// DeprecatedFileOperations panics if any deprecated Inode method is called.
+type DeprecatedFileOperations struct{}
+
+// Readiness implements fs.InodeOperations.Waitable.Readiness.
+func (DeprecatedFileOperations) Readiness(waiter.EventMask) waiter.EventMask {
+ panic("not implemented")
+}
+
+// EventRegister implements fs.InodeOperations.Waitable.EventRegister.
+func (DeprecatedFileOperations) EventRegister(*waiter.Entry, waiter.EventMask) {
+ panic("not implemented")
+}
+
+// EventUnregister implements fs.InodeOperations.Waitable.EventUnregister.
+func (DeprecatedFileOperations) EventUnregister(*waiter.Entry) {
+ panic("not implemented")
+}
+
+// DeprecatedPreadv implements fs.InodeOperations.DeprecatedPreadv.
+func (DeprecatedFileOperations) DeprecatedPreadv(context.Context, usermem.IOSequence, int64) (int64, error) {
+ panic("not implemented")
+}
+
+// DeprecatedPwritev implements fs.InodeOperations.DeprecatedPwritev.
+func (DeprecatedFileOperations) DeprecatedPwritev(context.Context, usermem.IOSequence, int64) (int64, error) {
+ panic("not implemented")
+}
+
+// DeprecatedReaddir implements fs.InodeOperations.DeprecatedReaddir.
+func (DeprecatedFileOperations) DeprecatedReaddir(context.Context, *fs.DirCtx, int) (int, error) {
+ panic("not implemented")
+}
+
+// DeprecatedFsync implements fs.InodeOperations.DeprecatedFsync.
+func (DeprecatedFileOperations) DeprecatedFsync() error {
+ panic("not implemented")
+}
+
+// DeprecatedFlush implements fs.InodeOperations.DeprecatedFlush.
+func (DeprecatedFileOperations) DeprecatedFlush() error {
+ panic("not implemented")
+}
+
+// DeprecatedMappable implements fs.InodeOperations.DeprecatedMappable.
+func (DeprecatedFileOperations) DeprecatedMappable(context.Context, *fs.Inode) (memmap.Mappable, bool) {
+ panic("not implemented")
+}