summaryrefslogtreecommitdiffhomepage
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/sentry/fs/ashmem/area.go9
-rw-r--r--pkg/sentry/fs/binder/binder.go7
-rw-r--r--pkg/sentry/fs/dev/full.go19
-rw-r--r--pkg/sentry/fs/dev/null.go40
-rw-r--r--pkg/sentry/fs/dev/random.go19
-rw-r--r--pkg/sentry/fs/fdpipe/pipe.go15
-rw-r--r--pkg/sentry/fs/file.go12
-rw-r--r--pkg/sentry/fs/file_operations.go6
-rw-r--r--pkg/sentry/fs/file_overlay.go26
-rw-r--r--pkg/sentry/fs/filetest/filetest.go17
-rw-r--r--pkg/sentry/fs/fsutil/file.go35
-rw-r--r--pkg/sentry/fs/fsutil/inode.go19
-rw-r--r--pkg/sentry/fs/gofer/file.go16
-rw-r--r--pkg/sentry/fs/host/file.go5
-rw-r--r--pkg/sentry/fs/inotify.go5
-rw-r--r--pkg/sentry/fs/proc/exec_args.go19
-rw-r--r--pkg/sentry/fs/proc/fds.go21
-rw-r--r--pkg/sentry/fs/proc/proc.go3
-rw-r--r--pkg/sentry/fs/proc/rpcinet_proc.go17
-rw-r--r--pkg/sentry/fs/proc/seqfile/seqfile.go17
-rw-r--r--pkg/sentry/fs/proc/sys.go19
-rw-r--r--pkg/sentry/fs/proc/sys_net.go34
-rw-r--r--pkg/sentry/fs/proc/task.go41
-rw-r--r--pkg/sentry/fs/proc/uid_gid_map.go17
-rw-r--r--pkg/sentry/fs/proc/uptime.go19
-rw-r--r--pkg/sentry/fs/ramfs/dir.go3
-rw-r--r--pkg/sentry/fs/ramfs/socket.go21
-rw-r--r--pkg/sentry/fs/ramfs/symlink.go21
-rw-r--r--pkg/sentry/fs/timerfd/timerfd.go13
-rw-r--r--pkg/sentry/fs/tmpfs/file_regular.go15
-rw-r--r--pkg/sentry/fs/tty/dir.go15
-rw-r--r--pkg/sentry/fs/tty/master.go11
-rw-r--r--pkg/sentry/fs/tty/slave.go11
-rw-r--r--pkg/sentry/kernel/epoll/epoll.go13
-rw-r--r--pkg/sentry/kernel/eventfd/eventfd.go15
-rw-r--r--pkg/sentry/kernel/pipe/reader_writer.go11
-rw-r--r--pkg/sentry/loader/vdso.go17
-rw-r--r--pkg/sentry/socket/epsocket/epsocket.go11
-rw-r--r--pkg/sentry/socket/hostinet/socket.go11
-rw-r--r--pkg/sentry/socket/netlink/socket.go11
-rw-r--r--pkg/sentry/socket/rpcinet/socket.go11
-rw-r--r--pkg/sentry/socket/unix/unix.go11
-rw-r--r--pkg/sentry/syscalls/linux/sys_stat.go37
43 files changed, 422 insertions, 293 deletions
diff --git a/pkg/sentry/fs/ashmem/area.go b/pkg/sentry/fs/ashmem/area.go
index 710b5185f..651cbc164 100644
--- a/pkg/sentry/fs/ashmem/area.go
+++ b/pkg/sentry/fs/ashmem/area.go
@@ -42,10 +42,11 @@ const (
//
// +stateify savable
type Area struct {
- waiter.AlwaysReady `state:"nosave"`
- fsutil.FileNoFsync `state:"nosave"`
- fsutil.FileNoopFlush `state:"nosave"`
- fsutil.FileNotDirReaddir `state:"nosave"`
+ waiter.AlwaysReady `state:"nosave"`
+ fsutil.FileNoFsync `state:"nosave"`
+ fsutil.FileNoopFlush `state:"nosave"`
+ fsutil.FileNotDirReaddir `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
ad *Device
diff --git a/pkg/sentry/fs/binder/binder.go b/pkg/sentry/fs/binder/binder.go
index 188353961..a41b5dcae 100644
--- a/pkg/sentry/fs/binder/binder.go
+++ b/pkg/sentry/fs/binder/binder.go
@@ -85,9 +85,10 @@ func (bd *Device) GetFile(ctx context.Context, d *fs.Dirent, flags fs.FileFlags)
//
// +stateify savable
type Proc struct {
- waiter.AlwaysReady `state:"nosave"`
- fsutil.FileNoFsync `state:"nosave"`
- fsutil.FileNotDirReaddir `state:"nosave"`
+ waiter.AlwaysReady `state:"nosave"`
+ fsutil.FileNoFsync `state:"nosave"`
+ fsutil.FileNotDirReaddir `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
bd *Device
task *kernel.Task
diff --git a/pkg/sentry/fs/dev/full.go b/pkg/sentry/fs/dev/full.go
index 0cb513004..82da9aae9 100644
--- a/pkg/sentry/fs/dev/full.go
+++ b/pkg/sentry/fs/dev/full.go
@@ -59,15 +59,16 @@ func (f *fullDevice) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.Fi
// +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"`
+ 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"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
+ readZeros `state:"nosave"`
}
var _ fs.FileOperations = (*fullFileOperations)(nil)
diff --git a/pkg/sentry/fs/dev/null.go b/pkg/sentry/fs/dev/null.go
index 83f43c203..5d306d352 100644
--- a/pkg/sentry/fs/dev/null.go
+++ b/pkg/sentry/fs/dev/null.go
@@ -60,16 +60,17 @@ func (n *nullDevice) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.Fi
// +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"`
+ 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"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
}
var _ fs.FileOperations = (*nullFileOperations)(nil)
@@ -100,15 +101,16 @@ func (zd *zeroDevice) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.F
// +stateify savable
type zeroFileOperations struct {
- 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"`
+ 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"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
+ readZeros `state:"nosave"`
}
var _ fs.FileOperations = (*zeroFileOperations)(nil)
diff --git a/pkg/sentry/fs/dev/random.go b/pkg/sentry/fs/dev/random.go
index b9b78db7a..ffd5cf6c3 100644
--- a/pkg/sentry/fs/dev/random.go
+++ b/pkg/sentry/fs/dev/random.go
@@ -57,15 +57,16 @@ func (*randomDevice) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.Fi
// +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"`
+ 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"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
}
var _ fs.FileOperations = (*randomFileOperations)(nil)
diff --git a/pkg/sentry/fs/fdpipe/pipe.go b/pkg/sentry/fs/fdpipe/pipe.go
index b4d11cb45..98483ab68 100644
--- a/pkg/sentry/fs/fdpipe/pipe.go
+++ b/pkg/sentry/fs/fdpipe/pipe.go
@@ -37,13 +37,14 @@ import (
//
// +stateify savable
type pipeOperations struct {
- fsutil.FilePipeSeek `state:"nosave"`
- fsutil.FileNotDirReaddir `state:"nosave"`
- fsutil.FileNoFsync `state:"nosave"`
- fsutil.FileNoopFlush `state:"nosave"`
- fsutil.FileNoMMap `state:"nosave"`
- fsutil.FileNoIoctl `state:"nosave"`
- waiter.Queue `state:"nosave"`
+ fsutil.FilePipeSeek `state:"nosave"`
+ fsutil.FileNotDirReaddir `state:"nosave"`
+ fsutil.FileNoFsync `state:"nosave"`
+ fsutil.FileNoopFlush `state:"nosave"`
+ fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FileNoIoctl `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
+ waiter.Queue `state:"nosave"`
// flags are the flags used to open the pipe.
flags fs.FileFlags `state:".(fs.FileFlags)"`
diff --git a/pkg/sentry/fs/file.go b/pkg/sentry/fs/file.go
index 01c18647c..2c2126f17 100644
--- a/pkg/sentry/fs/file.go
+++ b/pkg/sentry/fs/file.go
@@ -408,6 +408,18 @@ func (f *File) ConfigureMMap(ctx context.Context, opts *memmap.MMapOpts) error {
return f.FileOperations.ConfigureMMap(ctx, f, opts)
}
+// UnstableAttr calls f.FileOperations.UnstableAttr with f as the File.
+//
+// Returns syserror.ErrInterrupted if interrupted.
+func (f *File) UnstableAttr(ctx context.Context) (UnstableAttr, error) {
+ if !f.mu.Lock(ctx) {
+ return UnstableAttr{}, syserror.ErrInterrupted
+ }
+ defer f.mu.Unlock()
+
+ return f.FileOperations.UnstableAttr(ctx, f)
+}
+
// MappedName implements memmap.MappingIdentity.MappedName.
func (f *File) MappedName(ctx context.Context) string {
root := RootFromContext(ctx)
diff --git a/pkg/sentry/fs/file_operations.go b/pkg/sentry/fs/file_operations.go
index 81c6e2b5d..e0fa5135f 100644
--- a/pkg/sentry/fs/file_operations.go
+++ b/pkg/sentry/fs/file_operations.go
@@ -96,6 +96,12 @@ type FileOperations interface {
// memmap.Mappable.
ConfigureMMap(ctx context.Context, file *File, opts *memmap.MMapOpts) error
+ // UnstableAttr returns the "unstable" attributes of the inode represented
+ // by the file. Most implementations can embed
+ // fsutil.FileUseInodeUnstableAttr, which delegates to
+ // InodeOperations.UnstableAttr.
+ UnstableAttr(ctx context.Context, file *File) (UnstableAttr, error)
+
// Ioctl implements the ioctl(2) linux syscall.
//
// io provides access to the virtual memory space to which pointers in args
diff --git a/pkg/sentry/fs/file_overlay.go b/pkg/sentry/fs/file_overlay.go
index 4efe85832..e1f02f0f4 100644
--- a/pkg/sentry/fs/file_overlay.go
+++ b/pkg/sentry/fs/file_overlay.go
@@ -339,6 +339,32 @@ func (*overlayFileOperations) ConfigureMMap(ctx context.Context, file *File, opt
return nil
}
+// UnstableAttr implements fs.FileOperations.UnstableAttr.
+func (f *overlayFileOperations) UnstableAttr(ctx context.Context, file *File) (UnstableAttr, error) {
+ // Hot path. Avoid defers.
+ f.upperMu.Lock()
+ if f.upper != nil {
+ attr, err := f.upper.UnstableAttr(ctx)
+ f.upperMu.Unlock()
+ return attr, err
+ }
+ f.upperMu.Unlock()
+
+ // It's possible that copy-up has occurred, but we haven't opened a upper
+ // file yet. If this is the case, just use the upper inode's UnstableAttr
+ // rather than opening a file.
+ o := file.Dirent.Inode.overlay
+ o.copyMu.RLock()
+ if o.upper != nil {
+ attr, err := o.upper.UnstableAttr(ctx)
+ o.copyMu.RUnlock()
+ return attr, err
+ }
+ o.copyMu.RUnlock()
+
+ return f.lower.UnstableAttr(ctx)
+}
+
// Ioctl implements fs.FileOperations.Ioctl and always returns ENOTTY.
func (*overlayFileOperations) Ioctl(ctx context.Context, io usermem.IO, args arch.SyscallArguments) (uintptr, error) {
return 0, syserror.ENOTTY
diff --git a/pkg/sentry/fs/filetest/filetest.go b/pkg/sentry/fs/filetest/filetest.go
index 40d84d9f2..388a1ce36 100644
--- a/pkg/sentry/fs/filetest/filetest.go
+++ b/pkg/sentry/fs/filetest/filetest.go
@@ -31,14 +31,15 @@ import (
// TestFileOperations is an implementation of the File interface. It provides all
// required methods.
type TestFileOperations struct {
- fsutil.FileNoopRelease `state:"nosave"`
- fsutil.FilePipeSeek `state:"nosave"`
- fsutil.FileNotDirReaddir `state:"nosave"`
- fsutil.FileNoFsync `state:"nosave"`
- fsutil.FileNoopFlush `state:"nosave"`
- fsutil.FileNoMMap `state:"nosave"`
- fsutil.FileNoIoctl `state:"nosave"`
- waiter.AlwaysReady `state:"nosave"`
+ fsutil.FileNoopRelease `state:"nosave"`
+ fsutil.FilePipeSeek `state:"nosave"`
+ fsutil.FileNotDirReaddir `state:"nosave"`
+ fsutil.FileNoFsync `state:"nosave"`
+ fsutil.FileNoopFlush `state:"nosave"`
+ fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FileNoIoctl `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
+ waiter.AlwaysReady `state:"nosave"`
}
// NewTestFile creates and initializes a new test file.
diff --git a/pkg/sentry/fs/fsutil/file.go b/pkg/sentry/fs/fsutil/file.go
index ce329b37a..df34dc788 100644
--- a/pkg/sentry/fs/fsutil/file.go
+++ b/pkg/sentry/fs/fsutil/file.go
@@ -224,7 +224,7 @@ func (FileNoIoctl) Ioctl(ctx context.Context, io usermem.IO, args arch.SyscallAr
}
// DirFileOperations implements most of fs.FileOperations for directories,
-// except for Readdir which the embedding type must implement.
+// except for Readdir and UnstableAttr which the embedding type must implement.
type DirFileOperations struct {
waiter.AlwaysReady
FileGenericSeek
@@ -250,7 +250,8 @@ func (*DirFileOperations) Write(context.Context, *fs.File, usermem.IOSequence, i
//
// +stateify savable
type StaticDirFileOperations struct {
- DirFileOperations
+ DirFileOperations `state:"nosave"`
+ FileUseInodeUnstableAttr `state:"nosave"`
// dentryMap is a SortedDentryMap used to implement Readdir.
dentryMap *fs.SortedDentryMap
@@ -291,16 +292,17 @@ func (sdfo *StaticDirFileOperations) Readdir(ctx context.Context, file *fs.File,
//
// +stateify savable
type NoReadWriteFile struct {
- waiter.AlwaysReady `state:"nosave"`
- FileGenericSeek `state:"nosave"`
- FileNoIoctl `state:"nosave"`
- FileNoMMap `state:"nosave"`
- FileNoopFsync `state:"nosave"`
- FileNoopFlush `state:"nosave"`
- FileNoopRelease `state:"nosave"`
- FileNoRead `state:"nosave"`
- FileNoWrite `state:"nosave"`
- FileNotDirReaddir `state:"nosave"`
+ waiter.AlwaysReady `state:"nosave"`
+ FileGenericSeek `state:"nosave"`
+ FileNoIoctl `state:"nosave"`
+ FileNoMMap `state:"nosave"`
+ FileNoopFsync `state:"nosave"`
+ FileNoopFlush `state:"nosave"`
+ FileNoopRelease `state:"nosave"`
+ FileNoRead `state:"nosave"`
+ FileNoWrite `state:"nosave"`
+ FileNotDirReaddir `state:"nosave"`
+ FileUseInodeUnstableAttr `state:"nosave"`
}
var _ fs.FileOperations = (*NoReadWriteFile)(nil)
@@ -365,3 +367,12 @@ type FileNoopRead struct{}
func (FileNoopRead) Read(context.Context, *fs.File, usermem.IOSequence, int64) (int64, error) {
return 0, nil
}
+
+// FileUseInodeUnstableAttr implements fs.FileOperations.UnstableAttr by calling
+// InodeOperations.UnstableAttr.
+type FileUseInodeUnstableAttr struct{}
+
+// UnstableAttr implements fs.FileOperations.UnstableAttr.
+func (FileUseInodeUnstableAttr) UnstableAttr(ctx context.Context, file *fs.File) (fs.UnstableAttr, error) {
+ return file.Dirent.Inode.UnstableAttr(ctx)
+}
diff --git a/pkg/sentry/fs/fsutil/inode.go b/pkg/sentry/fs/fsutil/inode.go
index 37490e5b2..468171a9b 100644
--- a/pkg/sentry/fs/fsutil/inode.go
+++ b/pkg/sentry/fs/fsutil/inode.go
@@ -238,15 +238,16 @@ func (i *InodeSimpleExtendedAttributes) Listxattr(_ *fs.Inode) (map[string]struc
//
// +stateify savable
type staticFile struct {
- waiter.AlwaysReady `state:"nosave"`
- FileGenericSeek `state:"nosave"`
- FileNoIoctl `state:"nosave"`
- FileNoMMap `state:"nosave"`
- FileNoopFsync `state:"nosave"`
- FileNoopFlush `state:"nosave"`
- FileNoopRelease `state:"nosave"`
- FileNoopWrite `state:"nosave"`
- FileNotDirReaddir `state:"nosave"`
+ waiter.AlwaysReady `state:"nosave"`
+ FileGenericSeek `state:"nosave"`
+ FileNoIoctl `state:"nosave"`
+ FileNoMMap `state:"nosave"`
+ FileNoopFsync `state:"nosave"`
+ FileNoopFlush `state:"nosave"`
+ FileNoopRelease `state:"nosave"`
+ FileNoopWrite `state:"nosave"`
+ FileNotDirReaddir `state:"nosave"`
+ FileUseInodeUnstableAttr `state:"nosave"`
FileStaticContentReader
}
diff --git a/pkg/sentry/fs/gofer/file.go b/pkg/sentry/fs/gofer/file.go
index e49ae2201..80d1e08a6 100644
--- a/pkg/sentry/fs/gofer/file.go
+++ b/pkg/sentry/fs/gofer/file.go
@@ -310,6 +310,22 @@ func (f *fileOperations) ConfigureMMap(ctx context.Context, file *fs.File, opts
return f.inodeOperations.configureMMap(file, opts)
}
+// UnstableAttr implements fs.FileOperations.UnstableAttr.
+func (f *fileOperations) UnstableAttr(ctx context.Context, file *fs.File) (fs.UnstableAttr, error) {
+ s := f.inodeOperations.session()
+ if s.cachePolicy.cacheUAttrs(file.Dirent.Inode) {
+ return f.inodeOperations.cachingInodeOps.UnstableAttr(ctx, file.Dirent.Inode)
+ }
+ // Use f.handles.File, which represents 9P fids that have been opened,
+ // instead of inodeFileState.file, which represents 9P fids that have not.
+ // This may be significantly more efficient in some implementations.
+ _, valid, pattr, err := getattr(ctx, f.handles.File)
+ if err != nil {
+ return fs.UnstableAttr{}, err
+ }
+ return unstable(ctx, valid, pattr, s.mounter, s.client), nil
+}
+
// Seek implements fs.FileOperations.Seek.
func (f *fileOperations) Seek(ctx context.Context, file *fs.File, whence fs.SeekWhence, offset int64) (int64, error) {
return fsutil.SeekWithDirCursor(ctx, file, whence, offset, &f.dirCursor)
diff --git a/pkg/sentry/fs/host/file.go b/pkg/sentry/fs/host/file.go
index d67a0795f..2a8f285ff 100644
--- a/pkg/sentry/fs/host/file.go
+++ b/pkg/sentry/fs/host/file.go
@@ -36,8 +36,9 @@ import (
//
// +stateify savable
type fileOperations struct {
- fsutil.FileNoIoctl `state:"nosave"`
- fsutil.FileNoopRelease `state:"nosave"`
+ fsutil.FileNoIoctl `state:"nosave"`
+ fsutil.FileNoopRelease `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
// iops are the Inode operations for this file.
iops *inodeOperations `state:"wait"`
diff --git a/pkg/sentry/fs/inotify.go b/pkg/sentry/fs/inotify.go
index 5d6a7074b..59fa662f3 100644
--- a/pkg/sentry/fs/inotify.go
+++ b/pkg/sentry/fs/inotify.go
@@ -186,6 +186,11 @@ func (*Inotify) ConfigureMMap(context.Context, *File, *memmap.MMapOpts) error {
return syserror.ENODEV
}
+// UnstableAttr implements FileOperations.UnstableAttr.
+func (i *Inotify) UnstableAttr(ctx context.Context, file *File) (UnstableAttr, error) {
+ return file.Dirent.Inode.UnstableAttr(ctx)
+}
+
// Ioctl implements fs.FileOperations.Ioctl.
func (i *Inotify) Ioctl(ctx context.Context, io usermem.IO, args arch.SyscallArguments) (uintptr, error) {
switch args[1].Int() {
diff --git a/pkg/sentry/fs/proc/exec_args.go b/pkg/sentry/fs/proc/exec_args.go
index 9daad5d2b..fc21dfbbd 100644
--- a/pkg/sentry/fs/proc/exec_args.go
+++ b/pkg/sentry/fs/proc/exec_args.go
@@ -77,15 +77,16 @@ func (i *execArgInode) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.
// +stateify savable
type execArgFile struct {
- waiter.AlwaysReady `state:"nosave"`
- fsutil.FileGenericSeek `state:"nosave"`
- fsutil.FileNoIoctl `state:"nosave"`
- fsutil.FileNoMMap `state:"nosave"`
- fsutil.FileNotDirReaddir `state:"nosave"`
- fsutil.FileNoopRelease `state:"nosave"`
- fsutil.FileNoopFlush `state:"nosave"`
- fsutil.FileNoopFsync `state:"nosave"`
- fsutil.FileNoopWrite `state:"nosave"`
+ waiter.AlwaysReady `state:"nosave"`
+ fsutil.FileGenericSeek `state:"nosave"`
+ fsutil.FileNoIoctl `state:"nosave"`
+ fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FileNotDirReaddir `state:"nosave"`
+ fsutil.FileNoopRelease `state:"nosave"`
+ fsutil.FileNoopFlush `state:"nosave"`
+ fsutil.FileNoopFsync `state:"nosave"`
+ fsutil.FileNoopWrite `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
// arg is the type of exec argument this file contains.
arg execArgType
diff --git a/pkg/sentry/fs/proc/fds.go b/pkg/sentry/fs/proc/fds.go
index 3c471bad9..939ebaba1 100644
--- a/pkg/sentry/fs/proc/fds.go
+++ b/pkg/sentry/fs/proc/fds.go
@@ -91,7 +91,7 @@ func readDescriptors(t *kernel.Task, c *fs.DirCtx, offset int64, toDentAttr func
// fd implements fs.InodeOperations for a file in /proc/TID/fd/.
type fd struct {
ramfs.Symlink
- *fs.File
+ file *fs.File
}
var _ fs.InodeOperations = (*fd)(nil)
@@ -103,7 +103,7 @@ func newFd(t *kernel.Task, f *fs.File, msrc *fs.MountSource) *fs.Inode {
fd := &fd{
// RootOwner overridden by taskOwnedInodeOps.UnstableAttrs().
Symlink: *ramfs.NewSymlink(t, fs.RootOwner, ""),
- File: f,
+ file: f,
}
return newProcInode(fd, msrc, fs.Symlink, t)
}
@@ -112,8 +112,8 @@ func newFd(t *kernel.Task, f *fs.File, msrc *fs.MountSource) *fs.Inode {
// arguments are ignored.
func (f *fd) GetFile(context.Context, *fs.Dirent, fs.FileFlags) (*fs.File, error) {
// Take a reference on the fs.File.
- f.File.IncRef()
- return f.File, nil
+ f.file.IncRef()
+ return f.file, nil
}
// Readlink returns the current target.
@@ -122,14 +122,14 @@ func (f *fd) Readlink(ctx context.Context, _ *fs.Inode) (string, error) {
if root != nil {
defer root.DecRef()
}
- n, _ := f.Dirent.FullName(root)
+ n, _ := f.file.Dirent.FullName(root)
return n, nil
}
// Getlink implements fs.InodeOperations.Getlink.
func (f *fd) Getlink(context.Context, *fs.Inode) (*fs.Dirent, error) {
- f.Dirent.IncRef()
- return f.Dirent, nil
+ f.file.Dirent.IncRef()
+ return f.file.Dirent, nil
}
// Truncate is ignored.
@@ -139,12 +139,12 @@ func (f *fd) Truncate(context.Context, *fs.Inode, int64) error {
func (f *fd) Release(ctx context.Context) {
f.Symlink.Release(ctx)
- f.File.DecRef()
+ f.file.DecRef()
}
// Close releases the reference on the file.
func (f *fd) Close() error {
- f.DecRef()
+ f.file.DecRef()
return nil
}
@@ -212,7 +212,8 @@ func (f *fdDir) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.FileFla
// +stateify savable
type fdDirFile struct {
- fsutil.DirFileOperations `state:"nosave"`
+ fsutil.DirFileOperations `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
isInfoFile bool
diff --git a/pkg/sentry/fs/proc/proc.go b/pkg/sentry/fs/proc/proc.go
index c9e659533..64e1e1998 100644
--- a/pkg/sentry/fs/proc/proc.go
+++ b/pkg/sentry/fs/proc/proc.go
@@ -191,7 +191,8 @@ func (p *proc) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.FileFlag
//
// +stateify savable
type rootProcFile struct {
- fsutil.DirFileOperations `state:"nosave"`
+ fsutil.DirFileOperations `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
iops *proc
}
diff --git a/pkg/sentry/fs/proc/rpcinet_proc.go b/pkg/sentry/fs/proc/rpcinet_proc.go
index 65faa21f2..81f64a28b 100644
--- a/pkg/sentry/fs/proc/rpcinet_proc.go
+++ b/pkg/sentry/fs/proc/rpcinet_proc.go
@@ -60,14 +60,15 @@ func (i *rpcInetInode) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.
// rpcInetFile implements fs.FileOperations as RPCs.
type rpcInetFile 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"`
+ 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"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
inode *rpcInetInode
}
diff --git a/pkg/sentry/fs/proc/seqfile/seqfile.go b/pkg/sentry/fs/proc/seqfile/seqfile.go
index 16fc6789e..0a0eb45e2 100644
--- a/pkg/sentry/fs/proc/seqfile/seqfile.go
+++ b/pkg/sentry/fs/proc/seqfile/seqfile.go
@@ -183,14 +183,15 @@ func (s *SeqFile) updateSourceLocked(ctx context.Context, record int) {
//
// +stateify savable
type seqFileOperations 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"`
+ 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"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
seqFile *SeqFile
}
diff --git a/pkg/sentry/fs/proc/sys.go b/pkg/sentry/fs/proc/sys.go
index ee6b9f262..a7bc9198e 100644
--- a/pkg/sentry/fs/proc/sys.go
+++ b/pkg/sentry/fs/proc/sys.go
@@ -134,15 +134,16 @@ var _ fs.InodeOperations = (*hostname)(nil)
// +stateify savable
type hostnameFile struct {
- waiter.AlwaysReady `state:"nosave"`
- fsutil.FileNoIoctl `state:"nosave"`
- fsutil.FileNoMMap `state:"nosave"`
- fsutil.FileNoSeek `state:"nosave"`
- fsutil.FileNoopFlush `state:"nosave"`
- fsutil.FileNoopFsync `state:"nosave"`
- fsutil.FileNoopRelease `state:"nosave"`
- fsutil.FileNotDirReaddir `state:"nosave"`
- fsutil.FileNoWrite `state:"nosave"`
+ waiter.AlwaysReady `state:"nosave"`
+ fsutil.FileNoIoctl `state:"nosave"`
+ fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FileNoSeek `state:"nosave"`
+ fsutil.FileNoopFlush `state:"nosave"`
+ fsutil.FileNoopFsync `state:"nosave"`
+ fsutil.FileNoopRelease `state:"nosave"`
+ fsutil.FileNotDirReaddir `state:"nosave"`
+ fsutil.FileNoWrite `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
}
// Read implements fs.FileOperations.Read.
diff --git a/pkg/sentry/fs/proc/sys_net.go b/pkg/sentry/fs/proc/sys_net.go
index 42e9bc47f..728a46a74 100644
--- a/pkg/sentry/fs/proc/sys_net.go
+++ b/pkg/sentry/fs/proc/sys_net.go
@@ -85,14 +85,15 @@ func (m *tcpMemInode) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.F
// +stateify savable
type tcpMemFile struct {
- waiter.AlwaysReady `state:"nosave"`
- fsutil.FileGenericSeek `state:"nosave"`
- fsutil.FileNoIoctl `state:"nosave"`
- fsutil.FileNoMMap `state:"nosave"`
- fsutil.FileNoopRelease `state:"nosave"`
- fsutil.FileNoopFlush `state:"nosave"`
- fsutil.FileNoopFsync `state:"nosave"`
- fsutil.FileNotDirReaddir `state:"nosave"`
+ waiter.AlwaysReady `state:"nosave"`
+ fsutil.FileGenericSeek `state:"nosave"`
+ fsutil.FileNoIoctl `state:"nosave"`
+ fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FileNoopRelease `state:"nosave"`
+ fsutil.FileNoopFlush `state:"nosave"`
+ fsutil.FileNoopFsync `state:"nosave"`
+ fsutil.FileNotDirReaddir `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
tcpMemInode *tcpMemInode
}
@@ -197,14 +198,15 @@ func (s *tcpSack) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.FileF
// +stateify savable
type tcpSackFile struct {
- waiter.AlwaysReady `state:"nosave"`
- fsutil.FileGenericSeek `state:"nosave"`
- fsutil.FileNoIoctl `state:"nosave"`
- fsutil.FileNoMMap `state:"nosave"`
- fsutil.FileNoopRelease `state:"nosave"`
- fsutil.FileNoopFlush `state:"nosave"`
- fsutil.FileNoopFsync `state:"nosave"`
- fsutil.FileNotDirReaddir `state:"nosave"`
+ waiter.AlwaysReady `state:"nosave"`
+ fsutil.FileGenericSeek `state:"nosave"`
+ fsutil.FileNoIoctl `state:"nosave"`
+ fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FileNoopRelease `state:"nosave"`
+ fsutil.FileNoopFlush `state:"nosave"`
+ fsutil.FileNoopFsync `state:"nosave"`
+ fsutil.FileNotDirReaddir `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
tcpSack *tcpSack
diff --git a/pkg/sentry/fs/proc/task.go b/pkg/sentry/fs/proc/task.go
index 4b1f84942..0edcdfce2 100644
--- a/pkg/sentry/fs/proc/task.go
+++ b/pkg/sentry/fs/proc/task.go
@@ -142,7 +142,8 @@ func (s *subtasks) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.File
// +stateify savable
type subtasksFile struct {
- fsutil.DirFileOperations `state:"nosave"`
+ fsutil.DirFileOperations `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
t *kernel.Task
pidns *kernel.PIDNamespace
@@ -669,15 +670,16 @@ func (c *comm) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.FileFlag
// +stateify savable
type commFile 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"`
- fsutil.FileNoWrite `state:"nosave"`
+ 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"`
+ fsutil.FileNoWrite `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
t *kernel.Task
}
@@ -724,15 +726,16 @@ func (a *auxvec) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.FileFl
// +stateify savable
type auxvecFile 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"`
- fsutil.FileNoWrite `state:"nosave"`
+ 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"`
+ fsutil.FileNoWrite `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
t *kernel.Task
}
diff --git a/pkg/sentry/fs/proc/uid_gid_map.go b/pkg/sentry/fs/proc/uid_gid_map.go
index 0c68bbfc9..d433632cf 100644
--- a/pkg/sentry/fs/proc/uid_gid_map.go
+++ b/pkg/sentry/fs/proc/uid_gid_map.go
@@ -81,14 +81,15 @@ func (imio *idMapInodeOperations) GetFile(ctx context.Context, dirent *fs.Dirent
// +stateify savable
type idMapFileOperations 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"`
+ 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"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
iops *idMapInodeOperations
}
diff --git a/pkg/sentry/fs/proc/uptime.go b/pkg/sentry/fs/proc/uptime.go
index 40d0fd1fd..d7ae26fcf 100644
--- a/pkg/sentry/fs/proc/uptime.go
+++ b/pkg/sentry/fs/proc/uptime.go
@@ -54,15 +54,16 @@ func (u *uptime) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.FileFl
// +stateify savable
type uptimeFile 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"`
- fsutil.FileNoWrite `state:"nosave"`
+ 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"`
+ fsutil.FileNoWrite `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
startTime ktime.Time
}
diff --git a/pkg/sentry/fs/ramfs/dir.go b/pkg/sentry/fs/ramfs/dir.go
index a3b33c0f8..011cf3a16 100644
--- a/pkg/sentry/fs/ramfs/dir.go
+++ b/pkg/sentry/fs/ramfs/dir.go
@@ -388,7 +388,8 @@ func (*Dir) Rename(ctx context.Context, oldParent *fs.Inode, oldName string, new
//
// +stateify savable
type dirFileOperations struct {
- fsutil.DirFileOperations `state:"nosave"`
+ fsutil.DirFileOperations `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
// dirCursor contains the name of the last directory entry that was
// serialized.
diff --git a/pkg/sentry/fs/ramfs/socket.go b/pkg/sentry/fs/ramfs/socket.go
index 2c1295897..5bcb6c364 100644
--- a/pkg/sentry/fs/ramfs/socket.go
+++ b/pkg/sentry/fs/ramfs/socket.go
@@ -67,16 +67,17 @@ func (s *Socket) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.FileFl
// +stateify savable
type socketFileOperations struct {
- waiter.AlwaysReady `state:"nosave"`
- fsutil.FileNoIoctl `state:"nosave"`
- fsutil.FileNoMMap `state:"nosave"`
- fsutil.FileNoopFlush `state:"nosave"`
- fsutil.FileNoopFsync `state:"nosave"`
- fsutil.FileNoopRelease `state:"nosave"`
- fsutil.FileNoRead `state:"nosave"`
- fsutil.FileNoSeek `state:"nosave"`
- fsutil.FileNotDirReaddir `state:"nosave"`
- fsutil.FileNoWrite `state:"nosave"`
+ waiter.AlwaysReady `state:"nosave"`
+ fsutil.FileNoIoctl `state:"nosave"`
+ fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FileNoopFlush `state:"nosave"`
+ fsutil.FileNoopFsync `state:"nosave"`
+ fsutil.FileNoopRelease `state:"nosave"`
+ fsutil.FileNoRead `state:"nosave"`
+ fsutil.FileNoSeek `state:"nosave"`
+ fsutil.FileNotDirReaddir `state:"nosave"`
+ fsutil.FileNoWrite `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
}
var _ fs.FileOperations = (*socketFileOperations)(nil)
diff --git a/pkg/sentry/fs/ramfs/symlink.go b/pkg/sentry/fs/ramfs/symlink.go
index 47dae380b..35dabdad2 100644
--- a/pkg/sentry/fs/ramfs/symlink.go
+++ b/pkg/sentry/fs/ramfs/symlink.go
@@ -88,16 +88,17 @@ func (s *Symlink) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.FileF
// +stateify savable
type symlinkFileOperations struct {
- waiter.AlwaysReady `state:"nosave"`
- fsutil.FileNoIoctl `state:"nosave"`
- fsutil.FileNoMMap `state:"nosave"`
- fsutil.FileNoopFlush `state:"nosave"`
- fsutil.FileNoopFsync `state:"nosave"`
- fsutil.FileNoopRelease `state:"nosave"`
- fsutil.FileNoRead `state:"nosave"`
- fsutil.FileNoSeek `state:"nosave"`
- fsutil.FileNotDirReaddir `state:"nosave"`
- fsutil.FileNoWrite `state:"nosave"`
+ waiter.AlwaysReady `state:"nosave"`
+ fsutil.FileNoIoctl `state:"nosave"`
+ fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FileNoopFlush `state:"nosave"`
+ fsutil.FileNoopFsync `state:"nosave"`
+ fsutil.FileNoopRelease `state:"nosave"`
+ fsutil.FileNoRead `state:"nosave"`
+ fsutil.FileNoSeek `state:"nosave"`
+ fsutil.FileNotDirReaddir `state:"nosave"`
+ fsutil.FileNoWrite `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
}
var _ fs.FileOperations = (*symlinkFileOperations)(nil)
diff --git a/pkg/sentry/fs/timerfd/timerfd.go b/pkg/sentry/fs/timerfd/timerfd.go
index b26466b9d..ef9a08854 100644
--- a/pkg/sentry/fs/timerfd/timerfd.go
+++ b/pkg/sentry/fs/timerfd/timerfd.go
@@ -33,12 +33,13 @@ import (
//
// +stateify savable
type TimerOperations struct {
- fsutil.FileZeroSeek `state:"nosave"`
- fsutil.FileNotDirReaddir `state:"nosave"`
- fsutil.FileNoFsync `state:"nosave"`
- fsutil.FileNoopFlush `state:"nosave"`
- fsutil.FileNoMMap `state:"nosave"`
- fsutil.FileNoIoctl `state:"nosave"`
+ fsutil.FileZeroSeek `state:"nosave"`
+ fsutil.FileNotDirReaddir `state:"nosave"`
+ fsutil.FileNoFsync `state:"nosave"`
+ fsutil.FileNoopFlush `state:"nosave"`
+ fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FileNoIoctl `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
events waiter.Queue `state:"zerovalue"`
timer *ktime.Timer
diff --git a/pkg/sentry/fs/tmpfs/file_regular.go b/pkg/sentry/fs/tmpfs/file_regular.go
index be6298130..d0c9b8bea 100644
--- a/pkg/sentry/fs/tmpfs/file_regular.go
+++ b/pkg/sentry/fs/tmpfs/file_regular.go
@@ -28,13 +28,14 @@ import (
//
// +stateify savable
type regularFileOperations struct {
- waiter.AlwaysReady `state:"nosave"`
- fsutil.FileNoopRelease `state:"nosave"`
- fsutil.FileGenericSeek `state:"nosave"`
- fsutil.FileNotDirReaddir `state:"nosave"`
- fsutil.FileNoopFsync `state:"nosave"`
- fsutil.FileNoopFlush `state:"nosave"`
- fsutil.FileNoIoctl `state:"nosave"`
+ waiter.AlwaysReady `state:"nosave"`
+ fsutil.FileNoopRelease `state:"nosave"`
+ fsutil.FileGenericSeek `state:"nosave"`
+ fsutil.FileNotDirReaddir `state:"nosave"`
+ fsutil.FileNoopFsync `state:"nosave"`
+ fsutil.FileNoopFlush `state:"nosave"`
+ fsutil.FileNoIoctl `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
// iops is the InodeOperations of a regular tmpfs file. It is
// guaranteed to be the same as file.Dirent.Inode.InodeOperations,
diff --git a/pkg/sentry/fs/tty/dir.go b/pkg/sentry/fs/tty/dir.go
index 11bf736d6..33b4c6438 100644
--- a/pkg/sentry/fs/tty/dir.go
+++ b/pkg/sentry/fs/tty/dir.go
@@ -285,13 +285,14 @@ func (d *dirInodeOperations) masterClose(t *Terminal) {
//
// +stateify savable
type dirFileOperations struct {
- waiter.AlwaysReady `state:"nosave"`
- fsutil.FileNoopRelease `state:"nosave"`
- fsutil.FileGenericSeek `state:"nosave"`
- fsutil.FileNoFsync `state:"nosave"`
- fsutil.FileNoopFlush `state:"nosave"`
- fsutil.FileNoMMap `state:"nosave"`
- fsutil.FileNoIoctl `state:"nosave"`
+ waiter.AlwaysReady `state:"nosave"`
+ fsutil.FileNoopRelease `state:"nosave"`
+ fsutil.FileGenericSeek `state:"nosave"`
+ fsutil.FileNoFsync `state:"nosave"`
+ fsutil.FileNoopFlush `state:"nosave"`
+ fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FileNoIoctl `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
// di is the inode operations.
di *dirInodeOperations
diff --git a/pkg/sentry/fs/tty/master.go b/pkg/sentry/fs/tty/master.go
index b5e13ab36..7c256abb0 100644
--- a/pkg/sentry/fs/tty/master.go
+++ b/pkg/sentry/fs/tty/master.go
@@ -95,11 +95,12 @@ func (mi *masterInodeOperations) GetFile(ctx context.Context, d *fs.Dirent, flag
//
// +stateify savable
type masterFileOperations struct {
- fsutil.FilePipeSeek `state:"nosave"`
- fsutil.FileNotDirReaddir `state:"nosave"`
- fsutil.FileNoFsync `state:"nosave"`
- fsutil.FileNoopFlush `state:"nosave"`
- fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FilePipeSeek `state:"nosave"`
+ fsutil.FileNotDirReaddir `state:"nosave"`
+ fsutil.FileNoFsync `state:"nosave"`
+ fsutil.FileNoopFlush `state:"nosave"`
+ fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
// d is the containing dir.
d *dirInodeOperations
diff --git a/pkg/sentry/fs/tty/slave.go b/pkg/sentry/fs/tty/slave.go
index 6dbce90b4..e8368bcdd 100644
--- a/pkg/sentry/fs/tty/slave.go
+++ b/pkg/sentry/fs/tty/slave.go
@@ -84,11 +84,12 @@ func (si *slaveInodeOperations) GetFile(ctx context.Context, d *fs.Dirent, flags
//
// +stateify savable
type slaveFileOperations struct {
- fsutil.FilePipeSeek `state:"nosave"`
- fsutil.FileNotDirReaddir `state:"nosave"`
- fsutil.FileNoFsync `state:"nosave"`
- fsutil.FileNoopFlush `state:"nosave"`
- fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FilePipeSeek `state:"nosave"`
+ fsutil.FileNotDirReaddir `state:"nosave"`
+ fsutil.FileNoFsync `state:"nosave"`
+ fsutil.FileNoopFlush `state:"nosave"`
+ fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
// si is the inode operations.
si *slaveInodeOperations
diff --git a/pkg/sentry/kernel/epoll/epoll.go b/pkg/sentry/kernel/epoll/epoll.go
index 61c0fb7c5..befefb11c 100644
--- a/pkg/sentry/kernel/epoll/epoll.go
+++ b/pkg/sentry/kernel/epoll/epoll.go
@@ -98,12 +98,13 @@ func (p *pollEntry) WeakRefGone() {
//
// +stateify savable
type EventPoll struct {
- fsutil.FilePipeSeek `state:"zerovalue"`
- fsutil.FileNotDirReaddir `state:"zerovalue"`
- fsutil.FileNoFsync `state:"zerovalue"`
- fsutil.FileNoopFlush `state:"zerovalue"`
- fsutil.FileNoMMap `state:"zerovalue"`
- fsutil.FileNoIoctl `state:"zerovalue"`
+ fsutil.FilePipeSeek `state:"zerovalue"`
+ fsutil.FileNotDirReaddir `state:"zerovalue"`
+ fsutil.FileNoFsync `state:"zerovalue"`
+ fsutil.FileNoopFlush `state:"zerovalue"`
+ fsutil.FileNoMMap `state:"zerovalue"`
+ fsutil.FileNoIoctl `state:"zerovalue"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
// Wait queue is used to notify interested parties when the event poll
// object itself becomes readable or writable.
diff --git a/pkg/sentry/kernel/eventfd/eventfd.go b/pkg/sentry/kernel/eventfd/eventfd.go
index 2d43c986d..b448ad813 100644
--- a/pkg/sentry/kernel/eventfd/eventfd.go
+++ b/pkg/sentry/kernel/eventfd/eventfd.go
@@ -38,13 +38,14 @@ import (
//
// +stateify savable
type EventOperations struct {
- fsutil.FileNoopRelease `state:"nosave"`
- fsutil.FilePipeSeek `state:"nosave"`
- fsutil.FileNotDirReaddir `state:"nosave"`
- fsutil.FileNoFsync `state:"nosave"`
- fsutil.FileNoopFlush `state:"nosave"`
- fsutil.FileNoMMap `state:"nosave"`
- fsutil.FileNoIoctl `state:"nosave"`
+ fsutil.FileNoopRelease `state:"nosave"`
+ fsutil.FilePipeSeek `state:"nosave"`
+ fsutil.FileNotDirReaddir `state:"nosave"`
+ fsutil.FileNoFsync `state:"nosave"`
+ fsutil.FileNoopFlush `state:"nosave"`
+ fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FileNoIoctl `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
// Mutex that protects accesses to the fields of this event.
mu sync.Mutex `state:"nosave"`
diff --git a/pkg/sentry/kernel/pipe/reader_writer.go b/pkg/sentry/kernel/pipe/reader_writer.go
index 028175530..1090432d7 100644
--- a/pkg/sentry/kernel/pipe/reader_writer.go
+++ b/pkg/sentry/kernel/pipe/reader_writer.go
@@ -35,11 +35,12 @@ import (
//
// +stateify savable
type ReaderWriter struct {
- fsutil.FilePipeSeek `state:"nosave"`
- fsutil.FileNotDirReaddir `state:"nosave"`
- fsutil.FileNoFsync `state:"nosave"`
- fsutil.FileNoopFlush `state:"nosave"`
- fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FilePipeSeek `state:"nosave"`
+ fsutil.FileNotDirReaddir `state:"nosave"`
+ fsutil.FileNoFsync `state:"nosave"`
+ fsutil.FileNoopFlush `state:"nosave"`
+ fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
*Pipe
}
diff --git a/pkg/sentry/loader/vdso.go b/pkg/sentry/loader/vdso.go
index fabf0cbe4..18b7e90d8 100644
--- a/pkg/sentry/loader/vdso.go
+++ b/pkg/sentry/loader/vdso.go
@@ -52,14 +52,15 @@ func (f *fileContext) Value(key interface{}) interface{} {
// byteReader implements fs.FileOperations for reading from a []byte source.
type byteReader struct {
- waiter.AlwaysReady `state:"nosave"`
- fsutil.FileNoFsync `state:"nosave"`
- fsutil.FileNoIoctl `state:"nosave"`
- fsutil.FileNoMMap `state:"nosave"`
- fsutil.FileNoopFlush `state:"nosave"`
- fsutil.FileNoopRelease `state:"nosave"`
- fsutil.FileNotDirReaddir `state:"nosave"`
- fsutil.FilePipeSeek `state:"nosave"`
+ waiter.AlwaysReady `state:"nosave"`
+ fsutil.FileNoFsync `state:"nosave"`
+ fsutil.FileNoIoctl `state:"nosave"`
+ fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FileNoopFlush `state:"nosave"`
+ fsutil.FileNoopRelease `state:"nosave"`
+ fsutil.FileNotDirReaddir `state:"nosave"`
+ fsutil.FilePipeSeek `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
data []byte
}
diff --git a/pkg/sentry/socket/epsocket/epsocket.go b/pkg/sentry/socket/epsocket/epsocket.go
index 5bcafad98..78f43178f 100644
--- a/pkg/sentry/socket/epsocket/epsocket.go
+++ b/pkg/sentry/socket/epsocket/epsocket.go
@@ -210,11 +210,12 @@ type commonEndpoint interface {
//
// +stateify savable
type SocketOperations struct {
- fsutil.FilePipeSeek `state:"nosave"`
- fsutil.FileNotDirReaddir `state:"nosave"`
- fsutil.FileNoFsync `state:"nosave"`
- fsutil.FileNoopFlush `state:"nosave"`
- fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FilePipeSeek `state:"nosave"`
+ fsutil.FileNotDirReaddir `state:"nosave"`
+ fsutil.FileNoFsync `state:"nosave"`
+ fsutil.FileNoopFlush `state:"nosave"`
+ fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
socket.SendReceiveTimeout
*waiter.Queue
diff --git a/pkg/sentry/socket/hostinet/socket.go b/pkg/sentry/socket/hostinet/socket.go
index a0a8a3220..be63823d8 100644
--- a/pkg/sentry/socket/hostinet/socket.go
+++ b/pkg/sentry/socket/hostinet/socket.go
@@ -46,11 +46,12 @@ const (
// socketOperations implements fs.FileOperations and socket.Socket for a socket
// implemented using a host socket.
type socketOperations struct {
- fsutil.FilePipeSeek `state:"nosave"`
- fsutil.FileNotDirReaddir `state:"nosave"`
- fsutil.FileNoFsync `state:"nosave"`
- fsutil.FileNoopFlush `state:"nosave"`
- fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FilePipeSeek `state:"nosave"`
+ fsutil.FileNotDirReaddir `state:"nosave"`
+ fsutil.FileNoFsync `state:"nosave"`
+ fsutil.FileNoopFlush `state:"nosave"`
+ fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
socket.SendReceiveTimeout
family int // Read-only.
diff --git a/pkg/sentry/socket/netlink/socket.go b/pkg/sentry/socket/netlink/socket.go
index 7223773ad..2503a67c5 100644
--- a/pkg/sentry/socket/netlink/socket.go
+++ b/pkg/sentry/socket/netlink/socket.go
@@ -65,11 +65,12 @@ var netlinkSocketDevice = device.NewAnonDevice()
//
// +stateify savable
type Socket struct {
- fsutil.FilePipeSeek `state:"nosave"`
- fsutil.FileNotDirReaddir `state:"nosave"`
- fsutil.FileNoFsync `state:"nosave"`
- fsutil.FileNoopFlush `state:"nosave"`
- fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FilePipeSeek `state:"nosave"`
+ fsutil.FileNotDirReaddir `state:"nosave"`
+ fsutil.FileNoFsync `state:"nosave"`
+ fsutil.FileNoopFlush `state:"nosave"`
+ fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
socket.SendReceiveTimeout
// ports provides netlink port allocation.
diff --git a/pkg/sentry/socket/rpcinet/socket.go b/pkg/sentry/socket/rpcinet/socket.go
index 548a22f32..896b5b7ce 100644
--- a/pkg/sentry/socket/rpcinet/socket.go
+++ b/pkg/sentry/socket/rpcinet/socket.go
@@ -45,11 +45,12 @@ import (
// socketOperations implements fs.FileOperations and socket.Socket for a socket
// implemented using a host socket.
type socketOperations struct {
- fsutil.FilePipeSeek `state:"nosave"`
- fsutil.FileNotDirReaddir `state:"nosave"`
- fsutil.FileNoFsync `state:"nosave"`
- fsutil.FileNoopFlush `state:"nosave"`
- fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FilePipeSeek `state:"nosave"`
+ fsutil.FileNotDirReaddir `state:"nosave"`
+ fsutil.FileNoFsync `state:"nosave"`
+ fsutil.FileNoopFlush `state:"nosave"`
+ fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
socket.SendReceiveTimeout
family int // Read-only.
diff --git a/pkg/sentry/socket/unix/unix.go b/pkg/sentry/socket/unix/unix.go
index c857a0f33..92411c901 100644
--- a/pkg/sentry/socket/unix/unix.go
+++ b/pkg/sentry/socket/unix/unix.go
@@ -45,11 +45,12 @@ import (
//
// +stateify savable
type SocketOperations struct {
- fsutil.FilePipeSeek `state:"nosave"`
- fsutil.FileNotDirReaddir `state:"nosave"`
- fsutil.FileNoFsync `state:"nosave"`
- fsutil.FileNoopFlush `state:"nosave"`
- fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FilePipeSeek `state:"nosave"`
+ fsutil.FileNotDirReaddir `state:"nosave"`
+ fsutil.FileNoFsync `state:"nosave"`
+ fsutil.FileNoopFlush `state:"nosave"`
+ fsutil.FileNoMMap `state:"nosave"`
+ fsutil.FileUseInodeUnstableAttr `state:"nosave"`
refs.AtomicRefCount
socket.SendReceiveTimeout
diff --git a/pkg/sentry/syscalls/linux/sys_stat.go b/pkg/sentry/syscalls/linux/sys_stat.go
index bdfb9b3ef..02634b2dd 100644
--- a/pkg/sentry/syscalls/linux/sys_stat.go
+++ b/pkg/sentry/syscalls/linux/sys_stat.go
@@ -60,7 +60,7 @@ func Fstatat(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
}
defer file.DecRef()
- return 0, nil, stat(t, file.Dirent, false, statAddr)
+ return 0, nil, fstat(t, file, statAddr)
}
return 0, nil, fileOpOn(t, fd, path, flags&linux.AT_SYMLINK_NOFOLLOW == 0, func(root *fs.Dirent, d *fs.Dirent) error {
@@ -98,7 +98,7 @@ func Fstat(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
}
defer file.DecRef()
- return 0, nil, stat(t, file.Dirent, false /* dirPath */, statAddr)
+ return 0, nil, fstat(t, file, statAddr)
}
// stat implements stat from the given *fs.Dirent.
@@ -110,9 +110,26 @@ func stat(t *kernel.Task, d *fs.Dirent, dirPath bool, statAddr usermem.Addr) err
if err != nil {
return err
}
+ return copyOutStat(t, statAddr, d.Inode.StableAttr, uattr)
+}
+
+// fstat implements fstat for the given *fs.File.
+func fstat(t *kernel.Task, f *fs.File, statAddr usermem.Addr) error {
+ uattr, err := f.UnstableAttr(t)
+ if err != nil {
+ return err
+ }
+ return copyOutStat(t, statAddr, f.Dirent.Inode.StableAttr, uattr)
+}
+// copyOutStat copies the attributes (sattr, uattr) to the struct stat at
+// address dst in t's address space. It encodes the stat struct to bytes
+// manually, as stat() is a very common syscall for many applications, and
+// t.CopyObjectOut has noticeable performance impact due to its many slice
+// allocations and use of reflection.
+func copyOutStat(t *kernel.Task, dst usermem.Addr, sattr fs.StableAttr, uattr fs.UnstableAttr) error {
var mode uint32
- switch d.Inode.StableAttr.Type {
+ switch sattr.Type {
case fs.RegularFile, fs.SpecialFile:
mode |= linux.ModeRegular
case fs.Symlink:
@@ -129,16 +146,12 @@ func stat(t *kernel.Task, d *fs.Dirent, dirPath bool, statAddr usermem.Addr) err
mode |= linux.ModeSocket
}
- // We encode the stat struct to bytes manually, as stat() is a very
- // common syscall for many applications, and t.CopyObjectOut has
- // noticeable performance impact due to its many slice allocations and
- // use of reflection.
b := t.CopyScratchBuffer(int(linux.SizeOfStat))[:0]
// Dev (uint64)
- b = binary.AppendUint64(b, usermem.ByteOrder, uint64(d.Inode.StableAttr.DeviceID))
+ b = binary.AppendUint64(b, usermem.ByteOrder, uint64(sattr.DeviceID))
// Ino (uint64)
- b = binary.AppendUint64(b, usermem.ByteOrder, uint64(d.Inode.StableAttr.InodeID))
+ b = binary.AppendUint64(b, usermem.ByteOrder, uint64(sattr.InodeID))
// Nlink (uint64)
b = binary.AppendUint64(b, usermem.ByteOrder, uattr.Links)
// Mode (uint32)
@@ -150,11 +163,11 @@ func stat(t *kernel.Task, d *fs.Dirent, dirPath bool, statAddr usermem.Addr) err
// Padding (uint32)
b = binary.AppendUint32(b, usermem.ByteOrder, 0)
// Rdev (uint64)
- b = binary.AppendUint64(b, usermem.ByteOrder, uint64(linux.MakeDeviceID(d.Inode.StableAttr.DeviceFileMajor, d.Inode.StableAttr.DeviceFileMinor)))
+ b = binary.AppendUint64(b, usermem.ByteOrder, uint64(linux.MakeDeviceID(sattr.DeviceFileMajor, sattr.DeviceFileMinor)))
// Size (uint64)
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(uattr.Size))
// Blksize (uint64)
- b = binary.AppendUint64(b, usermem.ByteOrder, uint64(d.Inode.StableAttr.BlockSize))
+ b = binary.AppendUint64(b, usermem.ByteOrder, uint64(sattr.BlockSize))
// Blocks (uint64)
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(uattr.Usage/512))
@@ -173,7 +186,7 @@ func stat(t *kernel.Task, d *fs.Dirent, dirPath bool, statAddr usermem.Addr) err
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(ctime.Sec))
b = binary.AppendUint64(b, usermem.ByteOrder, uint64(ctime.Nsec))
- _, err = t.CopyOutBytes(statAddr, b)
+ _, err := t.CopyOutBytes(dst, b)
return err
}