diff options
Diffstat (limited to 'pkg/sentry/fs/fsutil/inode.go')
-rw-r--r-- | pkg/sentry/fs/fsutil/inode.go | 380 |
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") +} |