summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--pkg/sentry/control/proc.go2
-rw-r--r--pkg/sentry/kernel/kernel.go9
-rwxr-xr-xpkg/sentry/kernel/kernel_state_autogen.go4
-rwxr-xr-xpkg/sentry/vfs/dentry.go4
-rwxr-xr-xpkg/sentry/vfs/device.go3
-rwxr-xr-xpkg/sentry/vfs/filesystem.go2
-rwxr-xr-xpkg/sentry/vfs/filesystem_type.go1
-rwxr-xr-xpkg/sentry/vfs/mount.go4
-rwxr-xr-xpkg/sentry/vfs/mount_unsafe.go8
-rwxr-xr-xpkg/sentry/vfs/vfs.go35
-rwxr-xr-xpkg/sentry/vfs/vfs_state_autogen.go162
11 files changed, 207 insertions, 27 deletions
diff --git a/pkg/sentry/control/proc.go b/pkg/sentry/control/proc.go
index 8973754c8..5457ba5e7 100644
--- a/pkg/sentry/control/proc.go
+++ b/pkg/sentry/control/proc.go
@@ -199,7 +199,7 @@ func (proc *Proc) execAsync(args *ExecArgs) (*kernel.ThreadGroup, kernel.ThreadI
}
paths := fs.GetPath(initArgs.Envv)
- vfsObj := proc.Kernel.VFS
+ vfsObj := proc.Kernel.VFS()
file, err := ResolveExecutablePath(ctx, vfsObj, initArgs.WorkingDirectory, initArgs.Argv[0], paths)
if err != nil {
return nil, 0, nil, fmt.Errorf("error finding executable %q in PATH %v: %v", initArgs.Argv[0], paths, err)
diff --git a/pkg/sentry/kernel/kernel.go b/pkg/sentry/kernel/kernel.go
index 2665f057c..ea21af33f 100644
--- a/pkg/sentry/kernel/kernel.go
+++ b/pkg/sentry/kernel/kernel.go
@@ -246,7 +246,7 @@ type Kernel struct {
SpecialOpts
// VFS keeps the filesystem state used across the kernel.
- VFS *vfs.VirtualFilesystem
+ vfs vfs.VirtualFilesystem
}
// InitKernelArgs holds arguments to Init.
@@ -815,7 +815,7 @@ func (k *Kernel) CreateProcess(args CreateProcessArgs) (*ThreadGroup, ThreadID,
FollowFinalSymlink: true,
}
var err error
- wd, err = k.VFS.GetDentryAt(ctx, args.Credentials, &pop, &vfs.GetDentryOptions{
+ wd, err = k.VFS().GetDentryAt(ctx, args.Credentials, &pop, &vfs.GetDentryOptions{
CheckSearchable: true,
})
if err != nil {
@@ -1506,3 +1506,8 @@ func (k *Kernel) EmitUnimplementedEvent(ctx context.Context) {
Registers: t.Arch().StateData().Proto(),
})
}
+
+// VFS returns the virtual filesystem for the kernel.
+func (k *Kernel) VFS() *vfs.VirtualFilesystem {
+ return &k.vfs
+}
diff --git a/pkg/sentry/kernel/kernel_state_autogen.go b/pkg/sentry/kernel/kernel_state_autogen.go
index edbaf9db8..8948ca886 100755
--- a/pkg/sentry/kernel/kernel_state_autogen.go
+++ b/pkg/sentry/kernel/kernel_state_autogen.go
@@ -156,7 +156,7 @@ func (x *Kernel) save(m state.Map) {
m.Save("nextSocketEntry", &x.nextSocketEntry)
m.Save("DirentCacheLimiter", &x.DirentCacheLimiter)
m.Save("SpecialOpts", &x.SpecialOpts)
- m.Save("VFS", &x.VFS)
+ m.Save("vfs", &x.vfs)
}
func (x *Kernel) afterLoad() {}
@@ -189,7 +189,7 @@ func (x *Kernel) load(m state.Map) {
m.Load("nextSocketEntry", &x.nextSocketEntry)
m.Load("DirentCacheLimiter", &x.DirentCacheLimiter)
m.Load("SpecialOpts", &x.SpecialOpts)
- m.Load("VFS", &x.VFS)
+ m.Load("vfs", &x.vfs)
m.LoadValue("danglingEndpoints", new([]tcpip.Endpoint), func(y interface{}) { x.loadDanglingEndpoints(y.([]tcpip.Endpoint)) })
m.LoadValue("deviceRegistry", new(*device.Registry), func(y interface{}) { x.loadDeviceRegistry(y.(*device.Registry)) })
}
diff --git a/pkg/sentry/vfs/dentry.go b/pkg/sentry/vfs/dentry.go
index 486a76475..35b208721 100755
--- a/pkg/sentry/vfs/dentry.go
+++ b/pkg/sentry/vfs/dentry.go
@@ -71,6 +71,8 @@ import (
// lifetime. Dentry reference counts only indicate the extent to which VFS
// requires Dentries to exist; Filesystems may elect to cache or discard
// Dentries with zero references.
+//
+// +stateify savable
type Dentry struct {
// parent is this Dentry's parent in this Filesystem. If this Dentry is
// independent, parent is nil.
@@ -89,7 +91,7 @@ type Dentry struct {
children map[string]*Dentry
// mu synchronizes disowning and mounting over this Dentry.
- mu sync.Mutex
+ mu sync.Mutex `state:"nosave"`
// impl is the DentryImpl associated with this Dentry. impl is immutable.
// This should be the last field in Dentry.
diff --git a/pkg/sentry/vfs/device.go b/pkg/sentry/vfs/device.go
index 3af2aa58d..bda5576fa 100755
--- a/pkg/sentry/vfs/device.go
+++ b/pkg/sentry/vfs/device.go
@@ -56,6 +56,7 @@ type Device interface {
Open(ctx context.Context, mnt *Mount, d *Dentry, opts OpenOptions) (*FileDescription, error)
}
+// +stateify savable
type registeredDevice struct {
dev Device
opts RegisterDeviceOptions
@@ -63,6 +64,8 @@ type registeredDevice struct {
// RegisterDeviceOptions contains options to
// VirtualFilesystem.RegisterDevice().
+//
+// +stateify savable
type RegisterDeviceOptions struct {
// GroupName is the name shown for this device registration in
// /proc/devices. If GroupName is empty, this registration will not be
diff --git a/pkg/sentry/vfs/filesystem.go b/pkg/sentry/vfs/filesystem.go
index a06a6caf3..556976d0b 100755
--- a/pkg/sentry/vfs/filesystem.go
+++ b/pkg/sentry/vfs/filesystem.go
@@ -29,6 +29,8 @@ import (
// Filesystem methods require that a reference is held.
//
// Filesystem is analogous to Linux's struct super_block.
+//
+// +stateify savable
type Filesystem struct {
// refs is the reference count. refs is accessed using atomic memory
// operations.
diff --git a/pkg/sentry/vfs/filesystem_type.go b/pkg/sentry/vfs/filesystem_type.go
index c58b70728..bb9cada81 100755
--- a/pkg/sentry/vfs/filesystem_type.go
+++ b/pkg/sentry/vfs/filesystem_type.go
@@ -44,6 +44,7 @@ type GetFilesystemOptions struct {
InternalData interface{}
}
+// +stateify savable
type registeredFilesystemType struct {
fsType FilesystemType
opts RegisterFilesystemTypeOptions
diff --git a/pkg/sentry/vfs/mount.go b/pkg/sentry/vfs/mount.go
index ad2c9fcf4..9912df799 100755
--- a/pkg/sentry/vfs/mount.go
+++ b/pkg/sentry/vfs/mount.go
@@ -38,6 +38,8 @@ import (
//
// Mount is analogous to Linux's struct mount. (gVisor does not distinguish
// between struct mount and struct vfsmount.)
+//
+// +stateify savable
type Mount struct {
// vfs, fs, and root are immutable. References are held on fs and root.
//
@@ -85,6 +87,8 @@ type Mount struct {
// MountNamespace methods require that a reference is held.
//
// MountNamespace is analogous to Linux's struct mnt_namespace.
+//
+// +stateify savable
type MountNamespace struct {
// root is the MountNamespace's root mount. root is immutable.
root *Mount
diff --git a/pkg/sentry/vfs/mount_unsafe.go b/pkg/sentry/vfs/mount_unsafe.go
index bd90d36c4..1fe766a44 100755
--- a/pkg/sentry/vfs/mount_unsafe.go
+++ b/pkg/sentry/vfs/mount_unsafe.go
@@ -64,6 +64,8 @@ func (mnt *Mount) storeKey(vd VirtualDentry) {
// (provided mutation is sufficiently uncommon).
//
// mountTable.Init() must be called on new mountTables before use.
+//
+// +stateify savable
type mountTable struct {
// mountTable is implemented as a seqcount-protected hash table that
// resolves collisions with linear probing, featuring Robin Hood insertion
@@ -75,8 +77,8 @@ type mountTable struct {
// intrinsics and inline assembly, limiting the performance of this
// approach.)
- seq sync.SeqCount
- seed uint32 // for hashing keys
+ seq sync.SeqCount `state:"nosave"`
+ seed uint32 // for hashing keys
// size holds both length (number of elements) and capacity (number of
// slots): capacity is stored as its base-2 log (referred to as order) in
@@ -89,7 +91,7 @@ type mountTable struct {
// length and cap in separate uint32s) for ~free.
size uint64
- slots unsafe.Pointer // []mountSlot; never nil after Init
+ slots unsafe.Pointer `state:"nosave"` // []mountSlot; never nil after Init
}
type mountSlot struct {
diff --git a/pkg/sentry/vfs/vfs.go b/pkg/sentry/vfs/vfs.go
index 51deae313..8f29031b2 100755
--- a/pkg/sentry/vfs/vfs.go
+++ b/pkg/sentry/vfs/vfs.go
@@ -46,11 +46,13 @@ import (
//
// There is no analogue to the VirtualFilesystem type in Linux, as the
// equivalent state in Linux is global.
+//
+// +stateify savable
type VirtualFilesystem struct {
// mountMu serializes mount mutations.
//
// mountMu is analogous to Linux's namespace_sem.
- mountMu sync.Mutex
+ mountMu sync.Mutex `state:"nosave"`
// mounts maps (mount parent, mount point) pairs to mounts. (Since mounts
// are uniquely namespaced, including mount parent in the key correctly
@@ -89,44 +91,42 @@ type VirtualFilesystem struct {
// devices contains all registered Devices. devices is protected by
// devicesMu.
- devicesMu sync.RWMutex
+ devicesMu sync.RWMutex `state:"nosave"`
devices map[devTuple]*registeredDevice
// anonBlockDevMinor contains all allocated anonymous block device minor
// numbers. anonBlockDevMinorNext is a lower bound for the smallest
// unallocated anonymous block device number. anonBlockDevMinorNext and
// anonBlockDevMinor are protected by anonBlockDevMinorMu.
- anonBlockDevMinorMu sync.Mutex
+ anonBlockDevMinorMu sync.Mutex `state:"nosave"`
anonBlockDevMinorNext uint32
anonBlockDevMinor map[uint32]struct{}
// fsTypes contains all registered FilesystemTypes. fsTypes is protected by
// fsTypesMu.
- fsTypesMu sync.RWMutex
+ fsTypesMu sync.RWMutex `state:"nosave"`
fsTypes map[string]*registeredFilesystemType
// filesystems contains all Filesystems. filesystems is protected by
// filesystemsMu.
- filesystemsMu sync.Mutex
+ filesystemsMu sync.Mutex `state:"nosave"`
filesystems map[*Filesystem]struct{}
}
-// New returns a new VirtualFilesystem with no mounts or FilesystemTypes.
-func New() *VirtualFilesystem {
- vfs := &VirtualFilesystem{
- mountpoints: make(map[*Dentry]map[*Mount]struct{}),
- devices: make(map[devTuple]*registeredDevice),
- anonBlockDevMinorNext: 1,
- anonBlockDevMinor: make(map[uint32]struct{}),
- fsTypes: make(map[string]*registeredFilesystemType),
- filesystems: make(map[*Filesystem]struct{}),
- }
+// Init initializes a new VirtualFilesystem with no mounts or FilesystemTypes.
+func (vfs *VirtualFilesystem) Init() error {
+ vfs.mountpoints = make(map[*Dentry]map[*Mount]struct{})
+ vfs.devices = make(map[devTuple]*registeredDevice)
+ vfs.anonBlockDevMinorNext = 1
+ vfs.anonBlockDevMinor = make(map[uint32]struct{})
+ vfs.fsTypes = make(map[string]*registeredFilesystemType)
+ vfs.filesystems = make(map[*Filesystem]struct{})
vfs.mounts.Init()
// Construct vfs.anonMount.
anonfsDevMinor, err := vfs.GetAnonBlockDevMinor()
if err != nil {
- panic(fmt.Sprintf("VirtualFilesystem.GetAnonBlockDevMinor() failed during VirtualFilesystem construction: %v", err))
+ return err
}
anonfs := anonFilesystem{
devMinor: anonfsDevMinor,
@@ -137,8 +137,7 @@ func New() *VirtualFilesystem {
fs: &anonfs.vfsfs,
refs: 1,
}
-
- return vfs
+ return nil
}
// PathOperation specifies the path operated on by a VFS method.
diff --git a/pkg/sentry/vfs/vfs_state_autogen.go b/pkg/sentry/vfs/vfs_state_autogen.go
index 3f14d460c..243646328 100755
--- a/pkg/sentry/vfs/vfs_state_autogen.go
+++ b/pkg/sentry/vfs/vfs_state_autogen.go
@@ -9,6 +9,51 @@ import (
"gvisor.dev/gvisor/pkg/state"
)
+func (x *Dentry) beforeSave() {}
+func (x *Dentry) save(m state.Map) {
+ x.beforeSave()
+ m.Save("parent", &x.parent)
+ m.Save("name", &x.name)
+ m.Save("flags", &x.flags)
+ m.Save("mounts", &x.mounts)
+ m.Save("children", &x.children)
+ m.Save("impl", &x.impl)
+}
+
+func (x *Dentry) afterLoad() {}
+func (x *Dentry) load(m state.Map) {
+ m.Load("parent", &x.parent)
+ m.Load("name", &x.name)
+ m.Load("flags", &x.flags)
+ m.Load("mounts", &x.mounts)
+ m.Load("children", &x.children)
+ m.Load("impl", &x.impl)
+}
+
+func (x *registeredDevice) beforeSave() {}
+func (x *registeredDevice) save(m state.Map) {
+ x.beforeSave()
+ m.Save("dev", &x.dev)
+ m.Save("opts", &x.opts)
+}
+
+func (x *registeredDevice) afterLoad() {}
+func (x *registeredDevice) load(m state.Map) {
+ m.Load("dev", &x.dev)
+ m.Load("opts", &x.opts)
+}
+
+func (x *RegisterDeviceOptions) beforeSave() {}
+func (x *RegisterDeviceOptions) save(m state.Map) {
+ x.beforeSave()
+ m.Save("GroupName", &x.GroupName)
+}
+
+func (x *RegisterDeviceOptions) afterLoad() {}
+func (x *RegisterDeviceOptions) load(m state.Map) {
+ m.Load("GroupName", &x.GroupName)
+}
+
func (x *epollInterestList) beforeSave() {}
func (x *epollInterestList) save(m state.Map) {
x.beforeSave()
@@ -35,6 +80,114 @@ func (x *epollInterestEntry) load(m state.Map) {
m.Load("prev", &x.prev)
}
+func (x *Filesystem) beforeSave() {}
+func (x *Filesystem) save(m state.Map) {
+ x.beforeSave()
+ m.Save("refs", &x.refs)
+ m.Save("vfs", &x.vfs)
+ m.Save("impl", &x.impl)
+}
+
+func (x *Filesystem) afterLoad() {}
+func (x *Filesystem) load(m state.Map) {
+ m.Load("refs", &x.refs)
+ m.Load("vfs", &x.vfs)
+ m.Load("impl", &x.impl)
+}
+
+func (x *registeredFilesystemType) beforeSave() {}
+func (x *registeredFilesystemType) save(m state.Map) {
+ x.beforeSave()
+ m.Save("fsType", &x.fsType)
+ m.Save("opts", &x.opts)
+}
+
+func (x *registeredFilesystemType) afterLoad() {}
+func (x *registeredFilesystemType) load(m state.Map) {
+ m.Load("fsType", &x.fsType)
+ m.Load("opts", &x.opts)
+}
+
+func (x *Mount) beforeSave() {}
+func (x *Mount) save(m state.Map) {
+ x.beforeSave()
+ m.Save("vfs", &x.vfs)
+ m.Save("fs", &x.fs)
+ m.Save("root", &x.root)
+ m.Save("key", &x.key)
+ m.Save("ns", &x.ns)
+ m.Save("refs", &x.refs)
+ m.Save("children", &x.children)
+ m.Save("umounted", &x.umounted)
+ m.Save("writers", &x.writers)
+}
+
+func (x *Mount) afterLoad() {}
+func (x *Mount) load(m state.Map) {
+ m.Load("vfs", &x.vfs)
+ m.Load("fs", &x.fs)
+ m.Load("root", &x.root)
+ m.Load("key", &x.key)
+ m.Load("ns", &x.ns)
+ m.Load("refs", &x.refs)
+ m.Load("children", &x.children)
+ m.Load("umounted", &x.umounted)
+ m.Load("writers", &x.writers)
+}
+
+func (x *MountNamespace) beforeSave() {}
+func (x *MountNamespace) save(m state.Map) {
+ x.beforeSave()
+ m.Save("root", &x.root)
+ m.Save("refs", &x.refs)
+ m.Save("mountpoints", &x.mountpoints)
+}
+
+func (x *MountNamespace) afterLoad() {}
+func (x *MountNamespace) load(m state.Map) {
+ m.Load("root", &x.root)
+ m.Load("refs", &x.refs)
+ m.Load("mountpoints", &x.mountpoints)
+}
+
+func (x *mountTable) beforeSave() {}
+func (x *mountTable) save(m state.Map) {
+ x.beforeSave()
+ m.Save("seed", &x.seed)
+ m.Save("size", &x.size)
+}
+
+func (x *mountTable) afterLoad() {}
+func (x *mountTable) load(m state.Map) {
+ m.Load("seed", &x.seed)
+ m.Load("size", &x.size)
+}
+
+func (x *VirtualFilesystem) beforeSave() {}
+func (x *VirtualFilesystem) save(m state.Map) {
+ x.beforeSave()
+ m.Save("mounts", &x.mounts)
+ m.Save("mountpoints", &x.mountpoints)
+ m.Save("anonMount", &x.anonMount)
+ m.Save("devices", &x.devices)
+ m.Save("anonBlockDevMinorNext", &x.anonBlockDevMinorNext)
+ m.Save("anonBlockDevMinor", &x.anonBlockDevMinor)
+ m.Save("fsTypes", &x.fsTypes)
+ m.Save("filesystems", &x.filesystems)
+}
+
+func (x *VirtualFilesystem) afterLoad() {}
+func (x *VirtualFilesystem) load(m state.Map) {
+ m.Load("mounts", &x.mounts)
+ m.Load("mountpoints", &x.mountpoints)
+ m.Load("anonMount", &x.anonMount)
+ m.Load("devices", &x.devices)
+ m.Load("anonBlockDevMinorNext", &x.anonBlockDevMinorNext)
+ m.Load("anonBlockDevMinor", &x.anonBlockDevMinor)
+ m.Load("fsTypes", &x.fsTypes)
+ m.Load("filesystems", &x.filesystems)
+}
+
func (x *VirtualDentry) beforeSave() {}
func (x *VirtualDentry) save(m state.Map) {
x.beforeSave()
@@ -49,7 +202,16 @@ func (x *VirtualDentry) load(m state.Map) {
}
func init() {
+ state.Register("pkg/sentry/vfs.Dentry", (*Dentry)(nil), state.Fns{Save: (*Dentry).save, Load: (*Dentry).load})
+ state.Register("pkg/sentry/vfs.registeredDevice", (*registeredDevice)(nil), state.Fns{Save: (*registeredDevice).save, Load: (*registeredDevice).load})
+ state.Register("pkg/sentry/vfs.RegisterDeviceOptions", (*RegisterDeviceOptions)(nil), state.Fns{Save: (*RegisterDeviceOptions).save, Load: (*RegisterDeviceOptions).load})
state.Register("pkg/sentry/vfs.epollInterestList", (*epollInterestList)(nil), state.Fns{Save: (*epollInterestList).save, Load: (*epollInterestList).load})
state.Register("pkg/sentry/vfs.epollInterestEntry", (*epollInterestEntry)(nil), state.Fns{Save: (*epollInterestEntry).save, Load: (*epollInterestEntry).load})
+ state.Register("pkg/sentry/vfs.Filesystem", (*Filesystem)(nil), state.Fns{Save: (*Filesystem).save, Load: (*Filesystem).load})
+ state.Register("pkg/sentry/vfs.registeredFilesystemType", (*registeredFilesystemType)(nil), state.Fns{Save: (*registeredFilesystemType).save, Load: (*registeredFilesystemType).load})
+ state.Register("pkg/sentry/vfs.Mount", (*Mount)(nil), state.Fns{Save: (*Mount).save, Load: (*Mount).load})
+ state.Register("pkg/sentry/vfs.MountNamespace", (*MountNamespace)(nil), state.Fns{Save: (*MountNamespace).save, Load: (*MountNamespace).load})
+ state.Register("pkg/sentry/vfs.mountTable", (*mountTable)(nil), state.Fns{Save: (*mountTable).save, Load: (*mountTable).load})
+ state.Register("pkg/sentry/vfs.VirtualFilesystem", (*VirtualFilesystem)(nil), state.Fns{Save: (*VirtualFilesystem).save, Load: (*VirtualFilesystem).load})
state.Register("pkg/sentry/vfs.VirtualDentry", (*VirtualDentry)(nil), state.Fns{Save: (*VirtualDentry).save, Load: (*VirtualDentry).load})
}