diff options
Diffstat (limited to 'pkg/sentry/socket/unix')
-rw-r--r-- | pkg/sentry/socket/unix/BUILD | 66 | ||||
-rw-r--r-- | pkg/sentry/socket/unix/socket_refs.go | 118 | ||||
-rw-r--r-- | pkg/sentry/socket/unix/socket_vfs2_refs.go | 118 | ||||
-rw-r--r-- | pkg/sentry/socket/unix/transport/BUILD | 53 | ||||
-rw-r--r-- | pkg/sentry/socket/unix/transport/queue_refs.go | 118 | ||||
-rw-r--r-- | pkg/sentry/socket/unix/transport/transport_message_list.go | 193 | ||||
-rw-r--r-- | pkg/sentry/socket/unix/transport/transport_state_autogen.go | 377 | ||||
-rw-r--r-- | pkg/sentry/socket/unix/unix_state_autogen.go | 160 |
8 files changed, 1084 insertions, 119 deletions
diff --git a/pkg/sentry/socket/unix/BUILD b/pkg/sentry/socket/unix/BUILD deleted file mode 100644 index cc7408698..000000000 --- a/pkg/sentry/socket/unix/BUILD +++ /dev/null @@ -1,66 +0,0 @@ -load("//tools:defs.bzl", "go_library") -load("//tools/go_generics:defs.bzl", "go_template_instance") - -package(licenses = ["notice"]) - -go_template_instance( - name = "socket_refs", - out = "socket_refs.go", - package = "unix", - prefix = "socketOperations", - template = "//pkg/refs_vfs2:refs_template", - types = { - "T": "SocketOperations", - }, -) - -go_template_instance( - name = "socket_vfs2_refs", - out = "socket_vfs2_refs.go", - package = "unix", - prefix = "socketVFS2", - template = "//pkg/refs_vfs2:refs_template", - types = { - "T": "SocketVFS2", - }, -) - -go_library( - name = "unix", - srcs = [ - "device.go", - "io.go", - "socket_refs.go", - "socket_vfs2_refs.go", - "unix.go", - "unix_vfs2.go", - ], - visibility = ["//pkg/sentry:internal"], - deps = [ - "//pkg/abi/linux", - "//pkg/context", - "//pkg/fspath", - "//pkg/log", - "//pkg/marshal", - "//pkg/refs", - "//pkg/safemem", - "//pkg/sentry/arch", - "//pkg/sentry/device", - "//pkg/sentry/fs", - "//pkg/sentry/fs/fsutil", - "//pkg/sentry/fs/lock", - "//pkg/sentry/fsimpl/sockfs", - "//pkg/sentry/kernel", - "//pkg/sentry/kernel/time", - "//pkg/sentry/socket", - "//pkg/sentry/socket/control", - "//pkg/sentry/socket/netstack", - "//pkg/sentry/socket/unix/transport", - "//pkg/sentry/vfs", - "//pkg/syserr", - "//pkg/syserror", - "//pkg/tcpip", - "//pkg/usermem", - "//pkg/waiter", - ], -) diff --git a/pkg/sentry/socket/unix/socket_refs.go b/pkg/sentry/socket/unix/socket_refs.go new file mode 100644 index 000000000..ea63dc659 --- /dev/null +++ b/pkg/sentry/socket/unix/socket_refs.go @@ -0,0 +1,118 @@ +package unix + +import ( + "fmt" + "runtime" + "sync/atomic" + + "gvisor.dev/gvisor/pkg/log" + refs_vfs1 "gvisor.dev/gvisor/pkg/refs" +) + +// ownerType is used to customize logging. Note that we use a pointer to T so +// that we do not copy the entire object when passed as a format parameter. +var socketOperationsownerType *SocketOperations + +// Refs implements refs.RefCounter. It keeps a reference count using atomic +// operations and calls the destructor when the count reaches zero. +// +// Note that the number of references is actually refCount + 1 so that a default +// zero-value Refs object contains one reference. +// +// TODO(gvisor.dev/issue/1486): Store stack traces when leak check is enabled in +// a map with 16-bit hashes, and store the hash in the top 16 bits of refCount. +// This will allow us to add stack trace information to the leak messages +// without growing the size of Refs. +// +// +stateify savable +type socketOperationsRefs struct { + // refCount is composed of two fields: + // + // [32-bit speculative references]:[32-bit real references] + // + // Speculative references are used for TryIncRef, to avoid a CompareAndSwap + // loop. See IncRef, DecRef and TryIncRef for details of how these fields are + // used. + refCount int64 +} + +func (r *socketOperationsRefs) finalize() { + var note string + switch refs_vfs1.GetLeakMode() { + case refs_vfs1.NoLeakChecking: + return + case refs_vfs1.UninitializedLeakChecking: + note = "(Leak checker uninitialized): " + } + if n := r.ReadRefs(); n != 0 { + log.Warningf("%sRefs %p owned by %T garbage collected with ref count of %d (want 0)", note, r, socketOperationsownerType, n) + } +} + +// EnableLeakCheck checks for reference leaks when Refs gets garbage collected. +func (r *socketOperationsRefs) EnableLeakCheck() { + if refs_vfs1.GetLeakMode() != refs_vfs1.NoLeakChecking { + runtime.SetFinalizer(r, (*socketOperationsRefs).finalize) + } +} + +// ReadRefs returns the current number of references. The returned count is +// inherently racy and is unsafe to use without external synchronization. +func (r *socketOperationsRefs) ReadRefs() int64 { + + return atomic.LoadInt64(&r.refCount) + 1 +} + +// IncRef implements refs.RefCounter.IncRef. +// +//go:nosplit +func (r *socketOperationsRefs) IncRef() { + if v := atomic.AddInt64(&r.refCount, 1); v <= 0 { + panic(fmt.Sprintf("Incrementing non-positive ref count %p owned by %T", r, socketOperationsownerType)) + } +} + +// TryIncRef implements refs.RefCounter.TryIncRef. +// +// To do this safely without a loop, a speculative reference is first acquired +// on the object. This allows multiple concurrent TryIncRef calls to distinguish +// other TryIncRef calls from genuine references held. +// +//go:nosplit +func (r *socketOperationsRefs) TryIncRef() bool { + const speculativeRef = 1 << 32 + v := atomic.AddInt64(&r.refCount, speculativeRef) + if int32(v) < 0 { + + atomic.AddInt64(&r.refCount, -speculativeRef) + return false + } + + atomic.AddInt64(&r.refCount, -speculativeRef+1) + return true +} + +// DecRef implements refs.RefCounter.DecRef. +// +// Note that speculative references are counted here. Since they were added +// prior to real references reaching zero, they will successfully convert to +// real references. In other words, we see speculative references only in the +// following case: +// +// A: TryIncRef [speculative increase => sees non-negative references] +// B: DecRef [real decrease] +// A: TryIncRef [transform speculative to real] +// +//go:nosplit +func (r *socketOperationsRefs) DecRef(destroy func()) { + switch v := atomic.AddInt64(&r.refCount, -1); { + case v < -1: + panic(fmt.Sprintf("Decrementing non-positive ref count %p, owned by %T", r, socketOperationsownerType)) + + case v == -1: + + if destroy != nil { + destroy() + } + } +} diff --git a/pkg/sentry/socket/unix/socket_vfs2_refs.go b/pkg/sentry/socket/unix/socket_vfs2_refs.go new file mode 100644 index 000000000..dc55f2947 --- /dev/null +++ b/pkg/sentry/socket/unix/socket_vfs2_refs.go @@ -0,0 +1,118 @@ +package unix + +import ( + "fmt" + "runtime" + "sync/atomic" + + "gvisor.dev/gvisor/pkg/log" + refs_vfs1 "gvisor.dev/gvisor/pkg/refs" +) + +// ownerType is used to customize logging. Note that we use a pointer to T so +// that we do not copy the entire object when passed as a format parameter. +var socketVFS2ownerType *SocketVFS2 + +// Refs implements refs.RefCounter. It keeps a reference count using atomic +// operations and calls the destructor when the count reaches zero. +// +// Note that the number of references is actually refCount + 1 so that a default +// zero-value Refs object contains one reference. +// +// TODO(gvisor.dev/issue/1486): Store stack traces when leak check is enabled in +// a map with 16-bit hashes, and store the hash in the top 16 bits of refCount. +// This will allow us to add stack trace information to the leak messages +// without growing the size of Refs. +// +// +stateify savable +type socketVFS2Refs struct { + // refCount is composed of two fields: + // + // [32-bit speculative references]:[32-bit real references] + // + // Speculative references are used for TryIncRef, to avoid a CompareAndSwap + // loop. See IncRef, DecRef and TryIncRef for details of how these fields are + // used. + refCount int64 +} + +func (r *socketVFS2Refs) finalize() { + var note string + switch refs_vfs1.GetLeakMode() { + case refs_vfs1.NoLeakChecking: + return + case refs_vfs1.UninitializedLeakChecking: + note = "(Leak checker uninitialized): " + } + if n := r.ReadRefs(); n != 0 { + log.Warningf("%sRefs %p owned by %T garbage collected with ref count of %d (want 0)", note, r, socketVFS2ownerType, n) + } +} + +// EnableLeakCheck checks for reference leaks when Refs gets garbage collected. +func (r *socketVFS2Refs) EnableLeakCheck() { + if refs_vfs1.GetLeakMode() != refs_vfs1.NoLeakChecking { + runtime.SetFinalizer(r, (*socketVFS2Refs).finalize) + } +} + +// ReadRefs returns the current number of references. The returned count is +// inherently racy and is unsafe to use without external synchronization. +func (r *socketVFS2Refs) ReadRefs() int64 { + + return atomic.LoadInt64(&r.refCount) + 1 +} + +// IncRef implements refs.RefCounter.IncRef. +// +//go:nosplit +func (r *socketVFS2Refs) IncRef() { + if v := atomic.AddInt64(&r.refCount, 1); v <= 0 { + panic(fmt.Sprintf("Incrementing non-positive ref count %p owned by %T", r, socketVFS2ownerType)) + } +} + +// TryIncRef implements refs.RefCounter.TryIncRef. +// +// To do this safely without a loop, a speculative reference is first acquired +// on the object. This allows multiple concurrent TryIncRef calls to distinguish +// other TryIncRef calls from genuine references held. +// +//go:nosplit +func (r *socketVFS2Refs) TryIncRef() bool { + const speculativeRef = 1 << 32 + v := atomic.AddInt64(&r.refCount, speculativeRef) + if int32(v) < 0 { + + atomic.AddInt64(&r.refCount, -speculativeRef) + return false + } + + atomic.AddInt64(&r.refCount, -speculativeRef+1) + return true +} + +// DecRef implements refs.RefCounter.DecRef. +// +// Note that speculative references are counted here. Since they were added +// prior to real references reaching zero, they will successfully convert to +// real references. In other words, we see speculative references only in the +// following case: +// +// A: TryIncRef [speculative increase => sees non-negative references] +// B: DecRef [real decrease] +// A: TryIncRef [transform speculative to real] +// +//go:nosplit +func (r *socketVFS2Refs) DecRef(destroy func()) { + switch v := atomic.AddInt64(&r.refCount, -1); { + case v < -1: + panic(fmt.Sprintf("Decrementing non-positive ref count %p, owned by %T", r, socketVFS2ownerType)) + + case v == -1: + + if destroy != nil { + destroy() + } + } +} diff --git a/pkg/sentry/socket/unix/transport/BUILD b/pkg/sentry/socket/unix/transport/BUILD deleted file mode 100644 index 26c3a51b9..000000000 --- a/pkg/sentry/socket/unix/transport/BUILD +++ /dev/null @@ -1,53 +0,0 @@ -load("//tools:defs.bzl", "go_library") -load("//tools/go_generics:defs.bzl", "go_template_instance") - -package(licenses = ["notice"]) - -go_template_instance( - name = "transport_message_list", - out = "transport_message_list.go", - package = "transport", - prefix = "message", - template = "//pkg/ilist:generic_list", - types = { - "Element": "*message", - "Linker": "*message", - }, -) - -go_template_instance( - name = "queue_refs", - out = "queue_refs.go", - package = "transport", - prefix = "queue", - template = "//pkg/refs_vfs2:refs_template", - types = { - "T": "queue", - }, -) - -go_library( - name = "transport", - srcs = [ - "connectioned.go", - "connectioned_state.go", - "connectionless.go", - "queue.go", - "queue_refs.go", - "transport_message_list.go", - "unix.go", - ], - visibility = ["//:sandbox"], - deps = [ - "//pkg/abi/linux", - "//pkg/context", - "//pkg/ilist", - "//pkg/log", - "//pkg/refs", - "//pkg/sync", - "//pkg/syserr", - "//pkg/tcpip", - "//pkg/tcpip/buffer", - "//pkg/waiter", - ], -) diff --git a/pkg/sentry/socket/unix/transport/queue_refs.go b/pkg/sentry/socket/unix/transport/queue_refs.go new file mode 100644 index 000000000..0d4e34988 --- /dev/null +++ b/pkg/sentry/socket/unix/transport/queue_refs.go @@ -0,0 +1,118 @@ +package transport + +import ( + "fmt" + "runtime" + "sync/atomic" + + "gvisor.dev/gvisor/pkg/log" + refs_vfs1 "gvisor.dev/gvisor/pkg/refs" +) + +// ownerType is used to customize logging. Note that we use a pointer to T so +// that we do not copy the entire object when passed as a format parameter. +var queueownerType *queue + +// Refs implements refs.RefCounter. It keeps a reference count using atomic +// operations and calls the destructor when the count reaches zero. +// +// Note that the number of references is actually refCount + 1 so that a default +// zero-value Refs object contains one reference. +// +// TODO(gvisor.dev/issue/1486): Store stack traces when leak check is enabled in +// a map with 16-bit hashes, and store the hash in the top 16 bits of refCount. +// This will allow us to add stack trace information to the leak messages +// without growing the size of Refs. +// +// +stateify savable +type queueRefs struct { + // refCount is composed of two fields: + // + // [32-bit speculative references]:[32-bit real references] + // + // Speculative references are used for TryIncRef, to avoid a CompareAndSwap + // loop. See IncRef, DecRef and TryIncRef for details of how these fields are + // used. + refCount int64 +} + +func (r *queueRefs) finalize() { + var note string + switch refs_vfs1.GetLeakMode() { + case refs_vfs1.NoLeakChecking: + return + case refs_vfs1.UninitializedLeakChecking: + note = "(Leak checker uninitialized): " + } + if n := r.ReadRefs(); n != 0 { + log.Warningf("%sRefs %p owned by %T garbage collected with ref count of %d (want 0)", note, r, queueownerType, n) + } +} + +// EnableLeakCheck checks for reference leaks when Refs gets garbage collected. +func (r *queueRefs) EnableLeakCheck() { + if refs_vfs1.GetLeakMode() != refs_vfs1.NoLeakChecking { + runtime.SetFinalizer(r, (*queueRefs).finalize) + } +} + +// ReadRefs returns the current number of references. The returned count is +// inherently racy and is unsafe to use without external synchronization. +func (r *queueRefs) ReadRefs() int64 { + + return atomic.LoadInt64(&r.refCount) + 1 +} + +// IncRef implements refs.RefCounter.IncRef. +// +//go:nosplit +func (r *queueRefs) IncRef() { + if v := atomic.AddInt64(&r.refCount, 1); v <= 0 { + panic(fmt.Sprintf("Incrementing non-positive ref count %p owned by %T", r, queueownerType)) + } +} + +// TryIncRef implements refs.RefCounter.TryIncRef. +// +// To do this safely without a loop, a speculative reference is first acquired +// on the object. This allows multiple concurrent TryIncRef calls to distinguish +// other TryIncRef calls from genuine references held. +// +//go:nosplit +func (r *queueRefs) TryIncRef() bool { + const speculativeRef = 1 << 32 + v := atomic.AddInt64(&r.refCount, speculativeRef) + if int32(v) < 0 { + + atomic.AddInt64(&r.refCount, -speculativeRef) + return false + } + + atomic.AddInt64(&r.refCount, -speculativeRef+1) + return true +} + +// DecRef implements refs.RefCounter.DecRef. +// +// Note that speculative references are counted here. Since they were added +// prior to real references reaching zero, they will successfully convert to +// real references. In other words, we see speculative references only in the +// following case: +// +// A: TryIncRef [speculative increase => sees non-negative references] +// B: DecRef [real decrease] +// A: TryIncRef [transform speculative to real] +// +//go:nosplit +func (r *queueRefs) DecRef(destroy func()) { + switch v := atomic.AddInt64(&r.refCount, -1); { + case v < -1: + panic(fmt.Sprintf("Decrementing non-positive ref count %p, owned by %T", r, queueownerType)) + + case v == -1: + + if destroy != nil { + destroy() + } + } +} diff --git a/pkg/sentry/socket/unix/transport/transport_message_list.go b/pkg/sentry/socket/unix/transport/transport_message_list.go new file mode 100644 index 000000000..dda579c27 --- /dev/null +++ b/pkg/sentry/socket/unix/transport/transport_message_list.go @@ -0,0 +1,193 @@ +package transport + +// ElementMapper provides an identity mapping by default. +// +// This can be replaced to provide a struct that maps elements to linker +// objects, if they are not the same. An ElementMapper is not typically +// required if: Linker is left as is, Element is left as is, or Linker and +// Element are the same type. +type messageElementMapper struct{} + +// linkerFor maps an Element to a Linker. +// +// This default implementation should be inlined. +// +//go:nosplit +func (messageElementMapper) linkerFor(elem *message) *message { return elem } + +// List is an intrusive list. Entries can be added to or removed from the list +// in O(1) time and with no additional memory allocations. +// +// The zero value for List is an empty list ready to use. +// +// To iterate over a list (where l is a List): +// for e := l.Front(); e != nil; e = e.Next() { +// // do something with e. +// } +// +// +stateify savable +type messageList struct { + head *message + tail *message +} + +// Reset resets list l to the empty state. +func (l *messageList) Reset() { + l.head = nil + l.tail = nil +} + +// Empty returns true iff the list is empty. +func (l *messageList) Empty() bool { + return l.head == nil +} + +// Front returns the first element of list l or nil. +func (l *messageList) Front() *message { + return l.head +} + +// Back returns the last element of list l or nil. +func (l *messageList) Back() *message { + return l.tail +} + +// Len returns the number of elements in the list. +// +// NOTE: This is an O(n) operation. +func (l *messageList) Len() (count int) { + for e := l.Front(); e != nil; e = (messageElementMapper{}.linkerFor(e)).Next() { + count++ + } + return count +} + +// PushFront inserts the element e at the front of list l. +func (l *messageList) PushFront(e *message) { + linker := messageElementMapper{}.linkerFor(e) + linker.SetNext(l.head) + linker.SetPrev(nil) + if l.head != nil { + messageElementMapper{}.linkerFor(l.head).SetPrev(e) + } else { + l.tail = e + } + + l.head = e +} + +// PushBack inserts the element e at the back of list l. +func (l *messageList) PushBack(e *message) { + linker := messageElementMapper{}.linkerFor(e) + linker.SetNext(nil) + linker.SetPrev(l.tail) + if l.tail != nil { + messageElementMapper{}.linkerFor(l.tail).SetNext(e) + } else { + l.head = e + } + + l.tail = e +} + +// PushBackList inserts list m at the end of list l, emptying m. +func (l *messageList) PushBackList(m *messageList) { + if l.head == nil { + l.head = m.head + l.tail = m.tail + } else if m.head != nil { + messageElementMapper{}.linkerFor(l.tail).SetNext(m.head) + messageElementMapper{}.linkerFor(m.head).SetPrev(l.tail) + + l.tail = m.tail + } + m.head = nil + m.tail = nil +} + +// InsertAfter inserts e after b. +func (l *messageList) InsertAfter(b, e *message) { + bLinker := messageElementMapper{}.linkerFor(b) + eLinker := messageElementMapper{}.linkerFor(e) + + a := bLinker.Next() + + eLinker.SetNext(a) + eLinker.SetPrev(b) + bLinker.SetNext(e) + + if a != nil { + messageElementMapper{}.linkerFor(a).SetPrev(e) + } else { + l.tail = e + } +} + +// InsertBefore inserts e before a. +func (l *messageList) InsertBefore(a, e *message) { + aLinker := messageElementMapper{}.linkerFor(a) + eLinker := messageElementMapper{}.linkerFor(e) + + b := aLinker.Prev() + eLinker.SetNext(a) + eLinker.SetPrev(b) + aLinker.SetPrev(e) + + if b != nil { + messageElementMapper{}.linkerFor(b).SetNext(e) + } else { + l.head = e + } +} + +// Remove removes e from l. +func (l *messageList) Remove(e *message) { + linker := messageElementMapper{}.linkerFor(e) + prev := linker.Prev() + next := linker.Next() + + if prev != nil { + messageElementMapper{}.linkerFor(prev).SetNext(next) + } else if l.head == e { + l.head = next + } + + if next != nil { + messageElementMapper{}.linkerFor(next).SetPrev(prev) + } else if l.tail == e { + l.tail = prev + } + + linker.SetNext(nil) + linker.SetPrev(nil) +} + +// Entry is a default implementation of Linker. Users can add anonymous fields +// of this type to their structs to make them automatically implement the +// methods needed by List. +// +// +stateify savable +type messageEntry struct { + next *message + prev *message +} + +// Next returns the entry that follows e in the list. +func (e *messageEntry) Next() *message { + return e.next +} + +// Prev returns the entry that precedes e in the list. +func (e *messageEntry) Prev() *message { + return e.prev +} + +// SetNext assigns 'entry' as the entry that follows e in the list. +func (e *messageEntry) SetNext(elem *message) { + e.next = elem +} + +// SetPrev assigns 'entry' as the entry that precedes e in the list. +func (e *messageEntry) SetPrev(elem *message) { + e.prev = elem +} diff --git a/pkg/sentry/socket/unix/transport/transport_state_autogen.go b/pkg/sentry/socket/unix/transport/transport_state_autogen.go new file mode 100644 index 000000000..0264e8fb5 --- /dev/null +++ b/pkg/sentry/socket/unix/transport/transport_state_autogen.go @@ -0,0 +1,377 @@ +// automatically generated by stateify. + +package transport + +import ( + "gvisor.dev/gvisor/pkg/state" +) + +func (c *connectionedEndpoint) StateTypeName() string { + return "pkg/sentry/socket/unix/transport.connectionedEndpoint" +} + +func (c *connectionedEndpoint) StateFields() []string { + return []string{ + "baseEndpoint", + "id", + "idGenerator", + "stype", + "acceptedChan", + } +} + +func (c *connectionedEndpoint) beforeSave() {} + +func (c *connectionedEndpoint) StateSave(stateSinkObject state.Sink) { + c.beforeSave() + var acceptedChanValue []*connectionedEndpoint = c.saveAcceptedChan() + stateSinkObject.SaveValue(4, acceptedChanValue) + stateSinkObject.Save(0, &c.baseEndpoint) + stateSinkObject.Save(1, &c.id) + stateSinkObject.Save(2, &c.idGenerator) + stateSinkObject.Save(3, &c.stype) +} + +func (c *connectionedEndpoint) afterLoad() {} + +func (c *connectionedEndpoint) StateLoad(stateSourceObject state.Source) { + stateSourceObject.Load(0, &c.baseEndpoint) + stateSourceObject.Load(1, &c.id) + stateSourceObject.Load(2, &c.idGenerator) + stateSourceObject.Load(3, &c.stype) + stateSourceObject.LoadValue(4, new([]*connectionedEndpoint), func(y interface{}) { c.loadAcceptedChan(y.([]*connectionedEndpoint)) }) +} + +func (c *connectionlessEndpoint) StateTypeName() string { + return "pkg/sentry/socket/unix/transport.connectionlessEndpoint" +} + +func (c *connectionlessEndpoint) StateFields() []string { + return []string{ + "baseEndpoint", + } +} + +func (c *connectionlessEndpoint) beforeSave() {} + +func (c *connectionlessEndpoint) StateSave(stateSinkObject state.Sink) { + c.beforeSave() + stateSinkObject.Save(0, &c.baseEndpoint) +} + +func (c *connectionlessEndpoint) afterLoad() {} + +func (c *connectionlessEndpoint) StateLoad(stateSourceObject state.Source) { + stateSourceObject.Load(0, &c.baseEndpoint) +} + +func (q *queue) StateTypeName() string { + return "pkg/sentry/socket/unix/transport.queue" +} + +func (q *queue) StateFields() []string { + return []string{ + "queueRefs", + "ReaderQueue", + "WriterQueue", + "closed", + "unread", + "used", + "limit", + "dataList", + } +} + +func (q *queue) beforeSave() {} + +func (q *queue) StateSave(stateSinkObject state.Sink) { + q.beforeSave() + stateSinkObject.Save(0, &q.queueRefs) + stateSinkObject.Save(1, &q.ReaderQueue) + stateSinkObject.Save(2, &q.WriterQueue) + stateSinkObject.Save(3, &q.closed) + stateSinkObject.Save(4, &q.unread) + stateSinkObject.Save(5, &q.used) + stateSinkObject.Save(6, &q.limit) + stateSinkObject.Save(7, &q.dataList) +} + +func (q *queue) afterLoad() {} + +func (q *queue) StateLoad(stateSourceObject state.Source) { + stateSourceObject.Load(0, &q.queueRefs) + stateSourceObject.Load(1, &q.ReaderQueue) + stateSourceObject.Load(2, &q.WriterQueue) + stateSourceObject.Load(3, &q.closed) + stateSourceObject.Load(4, &q.unread) + stateSourceObject.Load(5, &q.used) + stateSourceObject.Load(6, &q.limit) + stateSourceObject.Load(7, &q.dataList) +} + +func (q *queueRefs) StateTypeName() string { + return "pkg/sentry/socket/unix/transport.queueRefs" +} + +func (q *queueRefs) StateFields() []string { + return []string{ + "refCount", + } +} + +func (q *queueRefs) beforeSave() {} + +func (q *queueRefs) StateSave(stateSinkObject state.Sink) { + q.beforeSave() + stateSinkObject.Save(0, &q.refCount) +} + +func (q *queueRefs) afterLoad() {} + +func (q *queueRefs) StateLoad(stateSourceObject state.Source) { + stateSourceObject.Load(0, &q.refCount) +} + +func (m *messageList) StateTypeName() string { + return "pkg/sentry/socket/unix/transport.messageList" +} + +func (m *messageList) StateFields() []string { + return []string{ + "head", + "tail", + } +} + +func (m *messageList) beforeSave() {} + +func (m *messageList) StateSave(stateSinkObject state.Sink) { + m.beforeSave() + stateSinkObject.Save(0, &m.head) + stateSinkObject.Save(1, &m.tail) +} + +func (m *messageList) afterLoad() {} + +func (m *messageList) StateLoad(stateSourceObject state.Source) { + stateSourceObject.Load(0, &m.head) + stateSourceObject.Load(1, &m.tail) +} + +func (m *messageEntry) StateTypeName() string { + return "pkg/sentry/socket/unix/transport.messageEntry" +} + +func (m *messageEntry) StateFields() []string { + return []string{ + "next", + "prev", + } +} + +func (m *messageEntry) beforeSave() {} + +func (m *messageEntry) StateSave(stateSinkObject state.Sink) { + m.beforeSave() + stateSinkObject.Save(0, &m.next) + stateSinkObject.Save(1, &m.prev) +} + +func (m *messageEntry) afterLoad() {} + +func (m *messageEntry) StateLoad(stateSourceObject state.Source) { + stateSourceObject.Load(0, &m.next) + stateSourceObject.Load(1, &m.prev) +} + +func (c *ControlMessages) StateTypeName() string { + return "pkg/sentry/socket/unix/transport.ControlMessages" +} + +func (c *ControlMessages) StateFields() []string { + return []string{ + "Rights", + "Credentials", + } +} + +func (c *ControlMessages) beforeSave() {} + +func (c *ControlMessages) StateSave(stateSinkObject state.Sink) { + c.beforeSave() + stateSinkObject.Save(0, &c.Rights) + stateSinkObject.Save(1, &c.Credentials) +} + +func (c *ControlMessages) afterLoad() {} + +func (c *ControlMessages) StateLoad(stateSourceObject state.Source) { + stateSourceObject.Load(0, &c.Rights) + stateSourceObject.Load(1, &c.Credentials) +} + +func (m *message) StateTypeName() string { + return "pkg/sentry/socket/unix/transport.message" +} + +func (m *message) StateFields() []string { + return []string{ + "messageEntry", + "Data", + "Control", + "Address", + } +} + +func (m *message) beforeSave() {} + +func (m *message) StateSave(stateSinkObject state.Sink) { + m.beforeSave() + stateSinkObject.Save(0, &m.messageEntry) + stateSinkObject.Save(1, &m.Data) + stateSinkObject.Save(2, &m.Control) + stateSinkObject.Save(3, &m.Address) +} + +func (m *message) afterLoad() {} + +func (m *message) StateLoad(stateSourceObject state.Source) { + stateSourceObject.Load(0, &m.messageEntry) + stateSourceObject.Load(1, &m.Data) + stateSourceObject.Load(2, &m.Control) + stateSourceObject.Load(3, &m.Address) +} + +func (q *queueReceiver) StateTypeName() string { + return "pkg/sentry/socket/unix/transport.queueReceiver" +} + +func (q *queueReceiver) StateFields() []string { + return []string{ + "readQueue", + } +} + +func (q *queueReceiver) beforeSave() {} + +func (q *queueReceiver) StateSave(stateSinkObject state.Sink) { + q.beforeSave() + stateSinkObject.Save(0, &q.readQueue) +} + +func (q *queueReceiver) afterLoad() {} + +func (q *queueReceiver) StateLoad(stateSourceObject state.Source) { + stateSourceObject.Load(0, &q.readQueue) +} + +func (s *streamQueueReceiver) StateTypeName() string { + return "pkg/sentry/socket/unix/transport.streamQueueReceiver" +} + +func (s *streamQueueReceiver) StateFields() []string { + return []string{ + "queueReceiver", + "buffer", + "control", + "addr", + } +} + +func (s *streamQueueReceiver) beforeSave() {} + +func (s *streamQueueReceiver) StateSave(stateSinkObject state.Sink) { + s.beforeSave() + stateSinkObject.Save(0, &s.queueReceiver) + stateSinkObject.Save(1, &s.buffer) + stateSinkObject.Save(2, &s.control) + stateSinkObject.Save(3, &s.addr) +} + +func (s *streamQueueReceiver) afterLoad() {} + +func (s *streamQueueReceiver) StateLoad(stateSourceObject state.Source) { + stateSourceObject.Load(0, &s.queueReceiver) + stateSourceObject.Load(1, &s.buffer) + stateSourceObject.Load(2, &s.control) + stateSourceObject.Load(3, &s.addr) +} + +func (c *connectedEndpoint) StateTypeName() string { + return "pkg/sentry/socket/unix/transport.connectedEndpoint" +} + +func (c *connectedEndpoint) StateFields() []string { + return []string{ + "endpoint", + "writeQueue", + } +} + +func (c *connectedEndpoint) beforeSave() {} + +func (c *connectedEndpoint) StateSave(stateSinkObject state.Sink) { + c.beforeSave() + stateSinkObject.Save(0, &c.endpoint) + stateSinkObject.Save(1, &c.writeQueue) +} + +func (c *connectedEndpoint) afterLoad() {} + +func (c *connectedEndpoint) StateLoad(stateSourceObject state.Source) { + stateSourceObject.Load(0, &c.endpoint) + stateSourceObject.Load(1, &c.writeQueue) +} + +func (b *baseEndpoint) StateTypeName() string { + return "pkg/sentry/socket/unix/transport.baseEndpoint" +} + +func (b *baseEndpoint) StateFields() []string { + return []string{ + "Queue", + "passcred", + "receiver", + "connected", + "path", + "linger", + } +} + +func (b *baseEndpoint) beforeSave() {} + +func (b *baseEndpoint) StateSave(stateSinkObject state.Sink) { + b.beforeSave() + stateSinkObject.Save(0, &b.Queue) + stateSinkObject.Save(1, &b.passcred) + stateSinkObject.Save(2, &b.receiver) + stateSinkObject.Save(3, &b.connected) + stateSinkObject.Save(4, &b.path) + stateSinkObject.Save(5, &b.linger) +} + +func (b *baseEndpoint) afterLoad() {} + +func (b *baseEndpoint) StateLoad(stateSourceObject state.Source) { + stateSourceObject.Load(0, &b.Queue) + stateSourceObject.Load(1, &b.passcred) + stateSourceObject.Load(2, &b.receiver) + stateSourceObject.Load(3, &b.connected) + stateSourceObject.Load(4, &b.path) + stateSourceObject.Load(5, &b.linger) +} + +func init() { + state.Register((*connectionedEndpoint)(nil)) + state.Register((*connectionlessEndpoint)(nil)) + state.Register((*queue)(nil)) + state.Register((*queueRefs)(nil)) + state.Register((*messageList)(nil)) + state.Register((*messageEntry)(nil)) + state.Register((*ControlMessages)(nil)) + state.Register((*message)(nil)) + state.Register((*queueReceiver)(nil)) + state.Register((*streamQueueReceiver)(nil)) + state.Register((*connectedEndpoint)(nil)) + state.Register((*baseEndpoint)(nil)) +} diff --git a/pkg/sentry/socket/unix/unix_state_autogen.go b/pkg/sentry/socket/unix/unix_state_autogen.go new file mode 100644 index 000000000..4afe51e7c --- /dev/null +++ b/pkg/sentry/socket/unix/unix_state_autogen.go @@ -0,0 +1,160 @@ +// automatically generated by stateify. + +package unix + +import ( + "gvisor.dev/gvisor/pkg/state" +) + +func (s *socketOperationsRefs) StateTypeName() string { + return "pkg/sentry/socket/unix.socketOperationsRefs" +} + +func (s *socketOperationsRefs) StateFields() []string { + return []string{ + "refCount", + } +} + +func (s *socketOperationsRefs) beforeSave() {} + +func (s *socketOperationsRefs) StateSave(stateSinkObject state.Sink) { + s.beforeSave() + stateSinkObject.Save(0, &s.refCount) +} + +func (s *socketOperationsRefs) afterLoad() {} + +func (s *socketOperationsRefs) StateLoad(stateSourceObject state.Source) { + stateSourceObject.Load(0, &s.refCount) +} + +func (s *socketVFS2Refs) StateTypeName() string { + return "pkg/sentry/socket/unix.socketVFS2Refs" +} + +func (s *socketVFS2Refs) StateFields() []string { + return []string{ + "refCount", + } +} + +func (s *socketVFS2Refs) beforeSave() {} + +func (s *socketVFS2Refs) StateSave(stateSinkObject state.Sink) { + s.beforeSave() + stateSinkObject.Save(0, &s.refCount) +} + +func (s *socketVFS2Refs) afterLoad() {} + +func (s *socketVFS2Refs) StateLoad(stateSourceObject state.Source) { + stateSourceObject.Load(0, &s.refCount) +} + +func (s *SocketOperations) StateTypeName() string { + return "pkg/sentry/socket/unix.SocketOperations" +} + +func (s *SocketOperations) StateFields() []string { + return []string{ + "socketOperationsRefs", + "socketOpsCommon", + } +} + +func (s *SocketOperations) beforeSave() {} + +func (s *SocketOperations) StateSave(stateSinkObject state.Sink) { + s.beforeSave() + stateSinkObject.Save(0, &s.socketOperationsRefs) + stateSinkObject.Save(1, &s.socketOpsCommon) +} + +func (s *SocketOperations) afterLoad() {} + +func (s *SocketOperations) StateLoad(stateSourceObject state.Source) { + stateSourceObject.Load(0, &s.socketOperationsRefs) + stateSourceObject.Load(1, &s.socketOpsCommon) +} + +func (s *socketOpsCommon) StateTypeName() string { + return "pkg/sentry/socket/unix.socketOpsCommon" +} + +func (s *socketOpsCommon) StateFields() []string { + return []string{ + "SendReceiveTimeout", + "ep", + "stype", + "abstractName", + "abstractNamespace", + } +} + +func (s *socketOpsCommon) beforeSave() {} + +func (s *socketOpsCommon) StateSave(stateSinkObject state.Sink) { + s.beforeSave() + stateSinkObject.Save(0, &s.SendReceiveTimeout) + stateSinkObject.Save(1, &s.ep) + stateSinkObject.Save(2, &s.stype) + stateSinkObject.Save(3, &s.abstractName) + stateSinkObject.Save(4, &s.abstractNamespace) +} + +func (s *socketOpsCommon) afterLoad() {} + +func (s *socketOpsCommon) StateLoad(stateSourceObject state.Source) { + stateSourceObject.Load(0, &s.SendReceiveTimeout) + stateSourceObject.Load(1, &s.ep) + stateSourceObject.Load(2, &s.stype) + stateSourceObject.Load(3, &s.abstractName) + stateSourceObject.Load(4, &s.abstractNamespace) +} + +func (s *SocketVFS2) StateTypeName() string { + return "pkg/sentry/socket/unix.SocketVFS2" +} + +func (s *SocketVFS2) StateFields() []string { + return []string{ + "vfsfd", + "FileDescriptionDefaultImpl", + "DentryMetadataFileDescriptionImpl", + "LockFD", + "socketVFS2Refs", + "socketOpsCommon", + } +} + +func (s *SocketVFS2) beforeSave() {} + +func (s *SocketVFS2) StateSave(stateSinkObject state.Sink) { + s.beforeSave() + stateSinkObject.Save(0, &s.vfsfd) + stateSinkObject.Save(1, &s.FileDescriptionDefaultImpl) + stateSinkObject.Save(2, &s.DentryMetadataFileDescriptionImpl) + stateSinkObject.Save(3, &s.LockFD) + stateSinkObject.Save(4, &s.socketVFS2Refs) + stateSinkObject.Save(5, &s.socketOpsCommon) +} + +func (s *SocketVFS2) afterLoad() {} + +func (s *SocketVFS2) StateLoad(stateSourceObject state.Source) { + stateSourceObject.Load(0, &s.vfsfd) + stateSourceObject.Load(1, &s.FileDescriptionDefaultImpl) + stateSourceObject.Load(2, &s.DentryMetadataFileDescriptionImpl) + stateSourceObject.Load(3, &s.LockFD) + stateSourceObject.Load(4, &s.socketVFS2Refs) + stateSourceObject.Load(5, &s.socketOpsCommon) +} + +func init() { + state.Register((*socketOperationsRefs)(nil)) + state.Register((*socketVFS2Refs)(nil)) + state.Register((*SocketOperations)(nil)) + state.Register((*socketOpsCommon)(nil)) + state.Register((*SocketVFS2)(nil)) +} |