summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/fsimpl/fuse
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/sentry/fsimpl/fuse')
-rw-r--r--pkg/sentry/fsimpl/fuse/connection.go25
-rw-r--r--pkg/sentry/fsimpl/fuse/dev.go16
-rw-r--r--pkg/sentry/fsimpl/fuse/fuse_state_autogen.go333
-rw-r--r--pkg/sentry/fsimpl/fuse/fusefs.go7
4 files changed, 376 insertions, 5 deletions
diff --git a/pkg/sentry/fsimpl/fuse/connection.go b/pkg/sentry/fsimpl/fuse/connection.go
index dbc5e1954..8ccda1264 100644
--- a/pkg/sentry/fsimpl/fuse/connection.go
+++ b/pkg/sentry/fsimpl/fuse/connection.go
@@ -39,15 +39,18 @@ const (
)
// connection is the struct by which the sentry communicates with the FUSE server daemon.
+//
// Lock order:
// - conn.fd.mu
// - conn.mu
// - conn.asyncMu
+//
+// +stateify savable
type connection struct {
fd *DeviceFD
// mu protects access to struct memebers.
- mu sync.Mutex
+ mu sync.Mutex `state:"nosave"`
// attributeVersion is the version of connection's attributes.
attributeVersion uint64
@@ -75,7 +78,7 @@ type connection struct {
initialized int32
// initializedChan is used to block requests before initialization.
- initializedChan chan struct{}
+ initializedChan chan struct{} `state:".(bool)"`
// connected (connection established) when a new FUSE file system is created.
// Set to false when:
@@ -113,7 +116,7 @@ type connection struct {
// i.e. `!request.noReply`
// asyncMu protects the async request fields.
- asyncMu sync.Mutex
+ asyncMu sync.Mutex `state:"nosave"`
// asyncNum is the number of async requests.
// Protected by asyncMu.
@@ -174,6 +177,22 @@ type connection struct {
noOpen bool
}
+func (conn *connection) saveInitializedChan() bool {
+ select {
+ case <-conn.initializedChan:
+ return true // Closed.
+ default:
+ return false // Not closed.
+ }
+}
+
+func (conn *connection) loadInitializedChan(closed bool) {
+ conn.initializedChan = make(chan struct{}, 1)
+ if closed {
+ close(conn.initializedChan)
+ }
+}
+
// newFUSEConnection creates a FUSE connection to fd.
func newFUSEConnection(_ context.Context, fd *vfs.FileDescription, opts *filesystemOptions) (*connection, error) {
// Mark the device as ready so it can be used. /dev/fuse can only be used if the FD was used to
diff --git a/pkg/sentry/fsimpl/fuse/dev.go b/pkg/sentry/fsimpl/fuse/dev.go
index f690ef5ad..1b86a4b4c 100644
--- a/pkg/sentry/fsimpl/fuse/dev.go
+++ b/pkg/sentry/fsimpl/fuse/dev.go
@@ -31,6 +31,8 @@ import (
const fuseDevMinor = 229
// fuseDevice implements vfs.Device for /dev/fuse.
+//
+// +stateify savable
type fuseDevice struct{}
// Open implements vfs.Device.Open.
@@ -49,6 +51,8 @@ func (fuseDevice) Open(ctx context.Context, mnt *vfs.Mount, vfsd *vfs.Dentry, op
}
// DeviceFD implements vfs.FileDescriptionImpl for /dev/fuse.
+//
+// +stateify savable
type DeviceFD struct {
vfsfd vfs.FileDescription
vfs.FileDescriptionDefaultImpl
@@ -79,7 +83,7 @@ type DeviceFD struct {
writeCursorFR *futureResponse
// mu protects all the queues, maps, buffers and cursors and nextOpID.
- mu sync.Mutex
+ mu sync.Mutex `state:"nosave"`
// waitQueue is used to notify interested parties when the device becomes
// readable or writable.
@@ -88,12 +92,20 @@ type DeviceFD struct {
// fullQueueCh is a channel used to synchronize the readers with the writers.
// Writers (inbound requests to the filesystem) block if there are too many
// unprocessed in-flight requests.
- fullQueueCh chan struct{}
+ fullQueueCh chan struct{} `state:".(int)"`
// fs is the FUSE filesystem that this FD is being used for.
fs *filesystem
}
+func (fd *DeviceFD) saveFullQueueCh() int {
+ return cap(fd.fullQueueCh)
+}
+
+func (fd *DeviceFD) loadFullQueueCh(capacity int) {
+ fd.fullQueueCh = make(chan struct{}, capacity)
+}
+
// Release implements vfs.FileDescriptionImpl.Release.
func (fd *DeviceFD) Release(ctx context.Context) {
if fd.fs != nil {
diff --git a/pkg/sentry/fsimpl/fuse/fuse_state_autogen.go b/pkg/sentry/fsimpl/fuse/fuse_state_autogen.go
index 6c82dce30..b127b2015 100644
--- a/pkg/sentry/fsimpl/fuse/fuse_state_autogen.go
+++ b/pkg/sentry/fsimpl/fuse/fuse_state_autogen.go
@@ -6,6 +6,332 @@ import (
"gvisor.dev/gvisor/pkg/state"
)
+func (x *connection) StateTypeName() string {
+ return "pkg/sentry/fsimpl/fuse.connection"
+}
+
+func (x *connection) StateFields() []string {
+ return []string{
+ "fd",
+ "attributeVersion",
+ "initialized",
+ "initializedChan",
+ "connected",
+ "connInitError",
+ "connInitSuccess",
+ "aborted",
+ "numWaiting",
+ "asyncNum",
+ "asyncCongestionThreshold",
+ "asyncNumMax",
+ "maxRead",
+ "maxWrite",
+ "maxPages",
+ "minor",
+ "atomicOTrunc",
+ "asyncRead",
+ "writebackCache",
+ "bigWrites",
+ "dontMask",
+ "noOpen",
+ }
+}
+
+func (x *connection) beforeSave() {}
+
+func (x *connection) StateSave(m state.Sink) {
+ x.beforeSave()
+ var initializedChan bool = x.saveInitializedChan()
+ m.SaveValue(3, initializedChan)
+ m.Save(0, &x.fd)
+ m.Save(1, &x.attributeVersion)
+ m.Save(2, &x.initialized)
+ m.Save(4, &x.connected)
+ m.Save(5, &x.connInitError)
+ m.Save(6, &x.connInitSuccess)
+ m.Save(7, &x.aborted)
+ m.Save(8, &x.numWaiting)
+ m.Save(9, &x.asyncNum)
+ m.Save(10, &x.asyncCongestionThreshold)
+ m.Save(11, &x.asyncNumMax)
+ m.Save(12, &x.maxRead)
+ m.Save(13, &x.maxWrite)
+ m.Save(14, &x.maxPages)
+ m.Save(15, &x.minor)
+ m.Save(16, &x.atomicOTrunc)
+ m.Save(17, &x.asyncRead)
+ m.Save(18, &x.writebackCache)
+ m.Save(19, &x.bigWrites)
+ m.Save(20, &x.dontMask)
+ m.Save(21, &x.noOpen)
+}
+
+func (x *connection) afterLoad() {}
+
+func (x *connection) StateLoad(m state.Source) {
+ m.Load(0, &x.fd)
+ m.Load(1, &x.attributeVersion)
+ m.Load(2, &x.initialized)
+ m.Load(4, &x.connected)
+ m.Load(5, &x.connInitError)
+ m.Load(6, &x.connInitSuccess)
+ m.Load(7, &x.aborted)
+ m.Load(8, &x.numWaiting)
+ m.Load(9, &x.asyncNum)
+ m.Load(10, &x.asyncCongestionThreshold)
+ m.Load(11, &x.asyncNumMax)
+ m.Load(12, &x.maxRead)
+ m.Load(13, &x.maxWrite)
+ m.Load(14, &x.maxPages)
+ m.Load(15, &x.minor)
+ m.Load(16, &x.atomicOTrunc)
+ m.Load(17, &x.asyncRead)
+ m.Load(18, &x.writebackCache)
+ m.Load(19, &x.bigWrites)
+ m.Load(20, &x.dontMask)
+ m.Load(21, &x.noOpen)
+ m.LoadValue(3, new(bool), func(y interface{}) { x.loadInitializedChan(y.(bool)) })
+}
+
+func (x *fuseDevice) StateTypeName() string {
+ return "pkg/sentry/fsimpl/fuse.fuseDevice"
+}
+
+func (x *fuseDevice) StateFields() []string {
+ return []string{}
+}
+
+func (x *fuseDevice) beforeSave() {}
+
+func (x *fuseDevice) StateSave(m state.Sink) {
+ x.beforeSave()
+}
+
+func (x *fuseDevice) afterLoad() {}
+
+func (x *fuseDevice) StateLoad(m state.Source) {
+}
+
+func (x *DeviceFD) StateTypeName() string {
+ return "pkg/sentry/fsimpl/fuse.DeviceFD"
+}
+
+func (x *DeviceFD) StateFields() []string {
+ return []string{
+ "vfsfd",
+ "FileDescriptionDefaultImpl",
+ "DentryMetadataFileDescriptionImpl",
+ "NoLockFD",
+ "nextOpID",
+ "queue",
+ "numActiveRequests",
+ "completions",
+ "writeCursor",
+ "writeBuf",
+ "writeCursorFR",
+ "waitQueue",
+ "fullQueueCh",
+ "fs",
+ }
+}
+
+func (x *DeviceFD) beforeSave() {}
+
+func (x *DeviceFD) StateSave(m state.Sink) {
+ x.beforeSave()
+ var fullQueueCh int = x.saveFullQueueCh()
+ m.SaveValue(12, fullQueueCh)
+ m.Save(0, &x.vfsfd)
+ m.Save(1, &x.FileDescriptionDefaultImpl)
+ m.Save(2, &x.DentryMetadataFileDescriptionImpl)
+ m.Save(3, &x.NoLockFD)
+ m.Save(4, &x.nextOpID)
+ m.Save(5, &x.queue)
+ m.Save(6, &x.numActiveRequests)
+ m.Save(7, &x.completions)
+ m.Save(8, &x.writeCursor)
+ m.Save(9, &x.writeBuf)
+ m.Save(10, &x.writeCursorFR)
+ m.Save(11, &x.waitQueue)
+ m.Save(13, &x.fs)
+}
+
+func (x *DeviceFD) afterLoad() {}
+
+func (x *DeviceFD) StateLoad(m state.Source) {
+ m.Load(0, &x.vfsfd)
+ m.Load(1, &x.FileDescriptionDefaultImpl)
+ m.Load(2, &x.DentryMetadataFileDescriptionImpl)
+ m.Load(3, &x.NoLockFD)
+ m.Load(4, &x.nextOpID)
+ m.Load(5, &x.queue)
+ m.Load(6, &x.numActiveRequests)
+ m.Load(7, &x.completions)
+ m.Load(8, &x.writeCursor)
+ m.Load(9, &x.writeBuf)
+ m.Load(10, &x.writeCursorFR)
+ m.Load(11, &x.waitQueue)
+ m.Load(13, &x.fs)
+ m.LoadValue(12, new(int), func(y interface{}) { x.loadFullQueueCh(y.(int)) })
+}
+
+func (x *FilesystemType) StateTypeName() string {
+ return "pkg/sentry/fsimpl/fuse.FilesystemType"
+}
+
+func (x *FilesystemType) StateFields() []string {
+ return []string{}
+}
+
+func (x *FilesystemType) beforeSave() {}
+
+func (x *FilesystemType) StateSave(m state.Sink) {
+ x.beforeSave()
+}
+
+func (x *FilesystemType) afterLoad() {}
+
+func (x *FilesystemType) StateLoad(m state.Source) {
+}
+
+func (x *filesystemOptions) StateTypeName() string {
+ return "pkg/sentry/fsimpl/fuse.filesystemOptions"
+}
+
+func (x *filesystemOptions) StateFields() []string {
+ return []string{
+ "userID",
+ "groupID",
+ "rootMode",
+ "maxActiveRequests",
+ "maxRead",
+ }
+}
+
+func (x *filesystemOptions) beforeSave() {}
+
+func (x *filesystemOptions) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.userID)
+ m.Save(1, &x.groupID)
+ m.Save(2, &x.rootMode)
+ m.Save(3, &x.maxActiveRequests)
+ m.Save(4, &x.maxRead)
+}
+
+func (x *filesystemOptions) afterLoad() {}
+
+func (x *filesystemOptions) StateLoad(m state.Source) {
+ m.Load(0, &x.userID)
+ m.Load(1, &x.groupID)
+ m.Load(2, &x.rootMode)
+ m.Load(3, &x.maxActiveRequests)
+ m.Load(4, &x.maxRead)
+}
+
+func (x *filesystem) StateTypeName() string {
+ return "pkg/sentry/fsimpl/fuse.filesystem"
+}
+
+func (x *filesystem) StateFields() []string {
+ return []string{
+ "Filesystem",
+ "devMinor",
+ "conn",
+ "opts",
+ "umounted",
+ }
+}
+
+func (x *filesystem) beforeSave() {}
+
+func (x *filesystem) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.Filesystem)
+ m.Save(1, &x.devMinor)
+ m.Save(2, &x.conn)
+ m.Save(3, &x.opts)
+ m.Save(4, &x.umounted)
+}
+
+func (x *filesystem) afterLoad() {}
+
+func (x *filesystem) StateLoad(m state.Source) {
+ m.Load(0, &x.Filesystem)
+ m.Load(1, &x.devMinor)
+ m.Load(2, &x.conn)
+ m.Load(3, &x.opts)
+ m.Load(4, &x.umounted)
+}
+
+func (x *inode) StateTypeName() string {
+ return "pkg/sentry/fsimpl/fuse.inode"
+}
+
+func (x *inode) StateFields() []string {
+ return []string{
+ "inodeRefs",
+ "InodeAttrs",
+ "InodeDirectoryNoNewChildren",
+ "InodeNoDynamicLookup",
+ "InodeNotSymlink",
+ "OrderedChildren",
+ "dentry",
+ "fs",
+ "metadataMu",
+ "nodeID",
+ "locks",
+ "size",
+ "attributeVersion",
+ "attributeTime",
+ "version",
+ "link",
+ }
+}
+
+func (x *inode) beforeSave() {}
+
+func (x *inode) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.inodeRefs)
+ m.Save(1, &x.InodeAttrs)
+ m.Save(2, &x.InodeDirectoryNoNewChildren)
+ m.Save(3, &x.InodeNoDynamicLookup)
+ m.Save(4, &x.InodeNotSymlink)
+ m.Save(5, &x.OrderedChildren)
+ m.Save(6, &x.dentry)
+ m.Save(7, &x.fs)
+ m.Save(8, &x.metadataMu)
+ m.Save(9, &x.nodeID)
+ m.Save(10, &x.locks)
+ m.Save(11, &x.size)
+ m.Save(12, &x.attributeVersion)
+ m.Save(13, &x.attributeTime)
+ m.Save(14, &x.version)
+ m.Save(15, &x.link)
+}
+
+func (x *inode) afterLoad() {}
+
+func (x *inode) StateLoad(m state.Source) {
+ m.Load(0, &x.inodeRefs)
+ m.Load(1, &x.InodeAttrs)
+ m.Load(2, &x.InodeDirectoryNoNewChildren)
+ m.Load(3, &x.InodeNoDynamicLookup)
+ m.Load(4, &x.InodeNotSymlink)
+ m.Load(5, &x.OrderedChildren)
+ m.Load(6, &x.dentry)
+ m.Load(7, &x.fs)
+ m.Load(8, &x.metadataMu)
+ m.Load(9, &x.nodeID)
+ m.Load(10, &x.locks)
+ m.Load(11, &x.size)
+ m.Load(12, &x.attributeVersion)
+ m.Load(13, &x.attributeTime)
+ m.Load(14, &x.version)
+ m.Load(15, &x.link)
+}
+
func (x *inodeRefs) StateTypeName() string {
return "pkg/sentry/fsimpl/fuse.inodeRefs"
}
@@ -187,6 +513,13 @@ func (x *Response) StateLoad(m state.Source) {
}
func init() {
+ state.Register((*connection)(nil))
+ state.Register((*fuseDevice)(nil))
+ state.Register((*DeviceFD)(nil))
+ state.Register((*FilesystemType)(nil))
+ state.Register((*filesystemOptions)(nil))
+ state.Register((*filesystem)(nil))
+ state.Register((*inode)(nil))
state.Register((*inodeRefs)(nil))
state.Register((*requestList)(nil))
state.Register((*requestEntry)(nil))
diff --git a/pkg/sentry/fsimpl/fuse/fusefs.go b/pkg/sentry/fsimpl/fuse/fusefs.go
index 5ccfc43e7..2f7cd8b8a 100644
--- a/pkg/sentry/fsimpl/fuse/fusefs.go
+++ b/pkg/sentry/fsimpl/fuse/fusefs.go
@@ -41,8 +41,11 @@ const Name = "fuse"
const maxActiveRequestsDefault = 10000
// FilesystemType implements vfs.FilesystemType.
+//
+// +stateify savable
type FilesystemType struct{}
+// +stateify savable
type filesystemOptions struct {
// userID specifies the numeric uid of the mount owner.
// This option should not be specified by the filesystem owner.
@@ -73,6 +76,8 @@ type filesystemOptions struct {
}
// filesystem implements vfs.FilesystemImpl.
+//
+// +stateify savable
type filesystem struct {
kernfs.Filesystem
devMinor uint32
@@ -240,6 +245,8 @@ func (fs *filesystem) Release(ctx context.Context) {
}
// inode implements kernfs.Inode.
+//
+// +stateify savable
type inode struct {
inodeRefs
kernfs.InodeAttrs