Make {Un}Marshal{Bytes/Unsafe} return remaining buffer.

Change marshal.Marshallable method signatures to return the remaining buffer.
This makes it easier to implement these method manually. Without this, we would
have to manually do buffer shifting which is error prone.

tools/go_marshal/test:benchmark test does not show change in performance.
Additionally fixed some marshalling bugs in fsimpl/fuse.

Updated multiple callpoints to get rid of redundant slice indexing work and
simplified code using this new signature.

Updates #6450

PiperOrigin-RevId: 407857019
This commit is contained in:
Ayush Ranjan
2021-11-05 10:43:49 -07:00
committed by gVisor bot
parent 822a647018
commit ce4f4283ba
41 changed files with 631 additions and 754 deletions
+60 -51
View File
@@ -352,6 +352,22 @@ type FUSEEntryOut struct {
Attr FUSEAttr
}
// CString represents a null terminated string which can be marshalled.
type CString string
// MarshalBytes implements marshal.Marshallable.MarshalBytes.
func (s *CString) MarshalBytes(buf []byte) []byte {
copy(buf, *s)
buf[len(*s)] = 0 // null char
return buf[s.SizeBytes():]
}
// SizeBytes implements marshal.Marshallable.SizeBytes.
func (s *CString) SizeBytes() int {
// 1 extra byte for null-terminated string.
return len(*s) + 1
}
// FUSELookupIn is the request sent by the kernel to the daemon
// to look up a file name.
//
@@ -360,18 +376,17 @@ type FUSELookupIn struct {
marshal.StubMarshallable
// Name is a file name to be looked up.
Name string
Name CString
}
// MarshalBytes serializes r.name to the dst buffer.
func (r *FUSELookupIn) MarshalBytes(buf []byte) {
copy(buf, r.Name)
func (r *FUSELookupIn) MarshalBytes(buf []byte) []byte {
return r.Name.MarshalBytes(buf)
}
// SizeBytes is the size of the memory representation of FUSELookupIn.
// 1 extra byte for null-terminated string.
func (r *FUSELookupIn) SizeBytes() int {
return len(r.Name) + 1
return r.Name.SizeBytes()
}
// MAX_NON_LFS indicates the maximum offset without large file support.
@@ -530,19 +545,18 @@ type FUSECreateIn struct {
CreateMeta FUSECreateMeta
// Name is the name of the node to create.
Name string
Name CString
}
// MarshalBytes serializes r.CreateMeta and r.Name to the dst buffer.
func (r *FUSECreateIn) MarshalBytes(buf []byte) {
r.CreateMeta.MarshalBytes(buf[:r.CreateMeta.SizeBytes()])
copy(buf[r.CreateMeta.SizeBytes():], r.Name)
func (r *FUSECreateIn) MarshalBytes(buf []byte) []byte {
buf = r.CreateMeta.MarshalBytes(buf)
return r.Name.MarshalBytes(buf)
}
// SizeBytes is the size of the memory representation of FUSECreateIn.
// 1 extra byte for null-terminated string.
func (r *FUSECreateIn) SizeBytes() int {
return r.CreateMeta.SizeBytes() + len(r.Name) + 1
return r.CreateMeta.SizeBytes() + r.Name.SizeBytes()
}
// FUSEMknodMeta contains all the static fields of FUSEMknodIn,
@@ -573,19 +587,18 @@ type FUSEMknodIn struct {
MknodMeta FUSEMknodMeta
// Name is the name of the node to create.
Name string
Name CString
}
// MarshalBytes serializes r.MknodMeta and r.Name to the dst buffer.
func (r *FUSEMknodIn) MarshalBytes(buf []byte) {
r.MknodMeta.MarshalBytes(buf[:r.MknodMeta.SizeBytes()])
copy(buf[r.MknodMeta.SizeBytes():], r.Name)
func (r *FUSEMknodIn) MarshalBytes(buf []byte) []byte {
buf = r.MknodMeta.MarshalBytes(buf)
return r.Name.MarshalBytes(buf)
}
// SizeBytes is the size of the memory representation of FUSEMknodIn.
// 1 extra byte for null-terminated string.
func (r *FUSEMknodIn) SizeBytes() int {
return r.MknodMeta.SizeBytes() + len(r.Name) + 1
return r.MknodMeta.SizeBytes() + r.Name.SizeBytes()
}
// FUSESymLinkIn is the request sent by the kernel to the daemon,
@@ -596,30 +609,30 @@ type FUSESymLinkIn struct {
marshal.StubMarshallable
// Name of symlink to create.
Name string
Name CString
// Target of the symlink.
Target string
Target CString
}
// MarshalBytes serializes r.Name and r.Target to the dst buffer.
// Left null-termination at end of r.Name and r.Target.
func (r *FUSESymLinkIn) MarshalBytes(buf []byte) {
copy(buf, r.Name)
copy(buf[len(r.Name)+1:], r.Target)
func (r *FUSESymLinkIn) MarshalBytes(buf []byte) []byte {
buf = r.Name.MarshalBytes(buf)
return r.Target.MarshalBytes(buf)
}
// SizeBytes is the size of the memory representation of FUSESymLinkIn.
// 2 extra bytes for null-terminated string.
func (r *FUSESymLinkIn) SizeBytes() int {
return len(r.Name) + len(r.Target) + 2
return r.Name.SizeBytes() + r.Target.SizeBytes()
}
// FUSEEmptyIn is used by operations without request body.
type FUSEEmptyIn struct{ marshal.StubMarshallable }
// MarshalBytes do nothing for marshal.
func (r *FUSEEmptyIn) MarshalBytes(buf []byte) {}
func (r *FUSEEmptyIn) MarshalBytes(buf []byte) []byte {
return buf
}
// SizeBytes is 0 for empty request.
func (r *FUSEEmptyIn) SizeBytes() int {
@@ -649,19 +662,18 @@ type FUSEMkdirIn struct {
MkdirMeta FUSEMkdirMeta
// Name of the directory to create.
Name string
Name CString
}
// MarshalBytes serializes r.MkdirMeta and r.Name to the dst buffer.
func (r *FUSEMkdirIn) MarshalBytes(buf []byte) {
r.MkdirMeta.MarshalBytes(buf[:r.MkdirMeta.SizeBytes()])
copy(buf[r.MkdirMeta.SizeBytes():], r.Name)
func (r *FUSEMkdirIn) MarshalBytes(buf []byte) []byte {
buf = r.MkdirMeta.MarshalBytes(buf)
return r.Name.MarshalBytes(buf)
}
// SizeBytes is the size of the memory representation of FUSEMkdirIn.
// 1 extra byte for null-terminated Name string.
func (r *FUSEMkdirIn) SizeBytes() int {
return r.MkdirMeta.SizeBytes() + len(r.Name) + 1
return r.MkdirMeta.SizeBytes() + r.Name.SizeBytes()
}
// FUSERmDirIn is the request sent by the kernel to the daemon
@@ -672,17 +684,17 @@ type FUSERmDirIn struct {
marshal.StubMarshallable
// Name is a directory name to be removed.
Name string
Name CString
}
// MarshalBytes serializes r.name to the dst buffer.
func (r *FUSERmDirIn) MarshalBytes(buf []byte) {
copy(buf, r.Name)
func (r *FUSERmDirIn) MarshalBytes(buf []byte) []byte {
return r.Name.MarshalBytes(buf)
}
// SizeBytes is the size of the memory representation of FUSERmDirIn.
func (r *FUSERmDirIn) SizeBytes() int {
return len(r.Name) + 1
return r.Name.SizeBytes()
}
// FUSEDirents is a list of Dirents received from the FUSE daemon server.
@@ -738,7 +750,7 @@ func (r *FUSEDirents) SizeBytes() int {
}
// UnmarshalBytes deserializes FUSEDirents from the src buffer.
func (r *FUSEDirents) UnmarshalBytes(src []byte) {
func (r *FUSEDirents) UnmarshalBytes(src []byte) []byte {
for {
if len(src) <= (*FUSEDirentMeta)(nil).SizeBytes() {
break
@@ -754,11 +766,10 @@ func (r *FUSEDirents) UnmarshalBytes(src []byte) {
// to do this. Linux allocates 1 page to store all the dirents and then
// simply reads them from the page.
var dirent FUSEDirent
dirent.UnmarshalBytes(src)
src = dirent.UnmarshalBytes(src)
r.Dirents = append(r.Dirents, &dirent)
src = src[dirent.SizeBytes():]
}
return src
}
// SizeBytes is the size of the memory representation of FUSEDirent.
@@ -772,20 +783,20 @@ func (r *FUSEDirent) SizeBytes() int {
}
// UnmarshalBytes deserializes FUSEDirent from the src buffer.
func (r *FUSEDirent) UnmarshalBytes(src []byte) {
r.Meta.UnmarshalBytes(src)
src = src[r.Meta.SizeBytes():]
func (r *FUSEDirent) UnmarshalBytes(src []byte) []byte {
src = r.Meta.UnmarshalBytes(src)
if r.Meta.NameLen > FUSE_NAME_MAX {
// The name is too long and therefore invalid. We don't
// need to unmarshal the name since it'll be thrown away.
return
return src
}
buf := make([]byte, r.Meta.NameLen)
name := primitive.ByteSlice(buf)
name.UnmarshalBytes(src[:r.Meta.NameLen])
r.Name = string(name)
return src[r.Meta.NameLen:]
}
// FATTR_* consts are the attribute flags defined in include/uapi/linux/fuse.h.
@@ -863,17 +874,15 @@ type FUSEUnlinkIn struct {
marshal.StubMarshallable
// Name of the node to unlink.
Name string
Name CString
}
// MarshalBytes serializes r.name to the dst buffer, which should
// have size len(r.Name) + 1 and last byte set to 0.
func (r *FUSEUnlinkIn) MarshalBytes(buf []byte) {
copy(buf, r.Name)
// MarshalBytes serializes r.name to the dst buffer.
func (r *FUSEUnlinkIn) MarshalBytes(buf []byte) []byte {
return r.Name.MarshalBytes(buf)
}
// SizeBytes is the size of the memory representation of FUSEUnlinkIn.
// 1 extra byte for null-terminated Name string.
func (r *FUSEUnlinkIn) SizeBytes() int {
return len(r.Name) + 1
return r.Name.SizeBytes()
}
+6 -6
View File
@@ -82,15 +82,15 @@ func (b *MsgBuf) SizeBytes() int {
}
// MarshalBytes implements marshal.Marshallable.MarshalBytes.
func (b *MsgBuf) MarshalBytes(dst []byte) {
b.Type.MarshalUnsafe(dst)
b.Text.MarshalBytes(dst[b.Type.SizeBytes():])
func (b *MsgBuf) MarshalBytes(dst []byte) []byte {
dst = b.Type.MarshalUnsafe(dst)
return b.Text.MarshalBytes(dst)
}
// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
func (b *MsgBuf) UnmarshalBytes(src []byte) {
b.Type.UnmarshalUnsafe(src)
b.Text.UnmarshalBytes(src[b.Type.SizeBytes():])
func (b *MsgBuf) UnmarshalBytes(src []byte) []byte {
src = b.Type.UnmarshalUnsafe(src)
return b.Text.UnmarshalBytes(src)
}
// MsgInfo is equivelant to struct msginfo. Source: include/uapi/linux/msg.h
+14 -16
View File
@@ -144,15 +144,15 @@ func (ke *KernelIPTEntry) SizeBytes() int {
}
// MarshalBytes implements marshal.Marshallable.MarshalBytes.
func (ke *KernelIPTEntry) MarshalBytes(dst []byte) {
ke.Entry.MarshalUnsafe(dst)
ke.Elems.MarshalBytes(dst[ke.Entry.SizeBytes():])
func (ke *KernelIPTEntry) MarshalBytes(dst []byte) []byte {
dst = ke.Entry.MarshalUnsafe(dst)
return ke.Elems.MarshalBytes(dst)
}
// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
func (ke *KernelIPTEntry) UnmarshalBytes(src []byte) {
ke.Entry.UnmarshalUnsafe(src)
ke.Elems.UnmarshalBytes(src[ke.Entry.SizeBytes():])
func (ke *KernelIPTEntry) UnmarshalBytes(src []byte) []byte {
src = ke.Entry.UnmarshalUnsafe(src)
return ke.Elems.UnmarshalBytes(src)
}
var _ marshal.Marshallable = (*KernelIPTEntry)(nil)
@@ -455,23 +455,21 @@ func (ke *KernelIPTGetEntries) SizeBytes() int {
}
// MarshalBytes implements marshal.Marshallable.MarshalBytes.
func (ke *KernelIPTGetEntries) MarshalBytes(dst []byte) {
ke.IPTGetEntries.MarshalUnsafe(dst)
marshalledUntil := ke.IPTGetEntries.SizeBytes()
func (ke *KernelIPTGetEntries) MarshalBytes(dst []byte) []byte {
dst = ke.IPTGetEntries.MarshalUnsafe(dst)
for i := range ke.Entrytable {
ke.Entrytable[i].MarshalBytes(dst[marshalledUntil:])
marshalledUntil += ke.Entrytable[i].SizeBytes()
dst = ke.Entrytable[i].MarshalBytes(dst)
}
return dst
}
// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
func (ke *KernelIPTGetEntries) UnmarshalBytes(src []byte) {
ke.IPTGetEntries.UnmarshalUnsafe(src)
unmarshalledUntil := ke.IPTGetEntries.SizeBytes()
func (ke *KernelIPTGetEntries) UnmarshalBytes(src []byte) []byte {
src = ke.IPTGetEntries.UnmarshalUnsafe(src)
for i := range ke.Entrytable {
ke.Entrytable[i].UnmarshalBytes(src[unmarshalledUntil:])
unmarshalledUntil += ke.Entrytable[i].SizeBytes()
src = ke.Entrytable[i].UnmarshalBytes(src)
}
return src
}
var _ marshal.Marshallable = (*KernelIPTGetEntries)(nil)
+16 -16
View File
@@ -84,23 +84,21 @@ func (ke *KernelIP6TGetEntries) SizeBytes() int {
}
// MarshalBytes implements marshal.Marshallable.MarshalBytes.
func (ke *KernelIP6TGetEntries) MarshalBytes(dst []byte) {
ke.IPTGetEntries.MarshalUnsafe(dst)
marshalledUntil := ke.IPTGetEntries.SizeBytes()
func (ke *KernelIP6TGetEntries) MarshalBytes(dst []byte) []byte {
dst = ke.IPTGetEntries.MarshalUnsafe(dst)
for i := range ke.Entrytable {
ke.Entrytable[i].MarshalBytes(dst[marshalledUntil:])
marshalledUntil += ke.Entrytable[i].SizeBytes()
dst = ke.Entrytable[i].MarshalBytes(dst)
}
return dst
}
// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
func (ke *KernelIP6TGetEntries) UnmarshalBytes(src []byte) {
ke.IPTGetEntries.UnmarshalUnsafe(src)
unmarshalledUntil := ke.IPTGetEntries.SizeBytes()
func (ke *KernelIP6TGetEntries) UnmarshalBytes(src []byte) []byte {
src = ke.IPTGetEntries.UnmarshalUnsafe(src)
for i := range ke.Entrytable {
ke.Entrytable[i].UnmarshalBytes(src[unmarshalledUntil:])
unmarshalledUntil += ke.Entrytable[i].SizeBytes()
src = ke.Entrytable[i].UnmarshalBytes(src)
}
return src
}
var _ marshal.Marshallable = (*KernelIP6TGetEntries)(nil)
@@ -166,17 +164,19 @@ func (ke *KernelIP6TEntry) SizeBytes() int {
}
// MarshalBytes implements marshal.Marshallable.MarshalBytes.
func (ke *KernelIP6TEntry) MarshalBytes(dst []byte) {
ke.Entry.MarshalUnsafe(dst)
ke.Elems.MarshalBytes(dst[ke.Entry.SizeBytes():])
func (ke *KernelIP6TEntry) MarshalBytes(dst []byte) []byte {
dst = ke.Entry.MarshalUnsafe(dst)
return ke.Elems.MarshalBytes(dst)
}
// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
func (ke *KernelIP6TEntry) UnmarshalBytes(src []byte) {
ke.Entry.UnmarshalUnsafe(src)
ke.Elems.UnmarshalBytes(src[ke.Entry.SizeBytes():])
func (ke *KernelIP6TEntry) UnmarshalBytes(src []byte) []byte {
src = ke.Entry.UnmarshalUnsafe(src)
return ke.Elems.UnmarshalBytes(src)
}
var _ marshal.Marshallable = (*KernelIP6TEntry)(nil)
// IP6TIP contains information for matching a packet's IP header.
// It corresponds to struct ip6t_ip6 in
// include/uapi/linux/netfilter_ipv6/ip6_tables.h.
-3
View File
@@ -555,9 +555,6 @@ type ControlMessageIPv6PacketInfo struct {
// ControlMessageCredentials struct.
var SizeOfControlMessageCredentials = (*ControlMessageCredentials)(nil).SizeBytes()
// A ControlMessageRights is an SCM_RIGHTS socket control message.
type ControlMessageRights []int32
// SizeOfControlMessageRight is the size of a single element in
// ControlMessageRights.
const SizeOfControlMessageRight = 4
+1 -1
View File
@@ -313,7 +313,7 @@ func (c *Client) SyncFDs(ctx context.Context, fds []FDID) error {
// implicit conversion to an interface leads to an allocation.
//
// Precondition: reqMarshal and respUnmarshal must be non-nil.
func (c *Client) SndRcvMessage(m MID, payloadLen uint32, reqMarshal func(dst []byte), respUnmarshal func(src []byte), respFDs []int) error {
func (c *Client) SndRcvMessage(m MID, payloadLen uint32, reqMarshal func(dst []byte) []byte, respUnmarshal func(src []byte) []byte, respFDs []int) error {
if !c.IsSupported(m) {
return unix.EOPNOTSUPP
}
+230 -281
View File
File diff suppressed because it is too large Load Diff
+22 -19
View File
@@ -53,18 +53,24 @@ func (m *MsgDynamic) SizeBytes() int {
}
// MarshalBytes implements marshal.Marshallable.MarshalBytes.
func (m *MsgDynamic) MarshalBytes(dst []byte) {
m.N.MarshalUnsafe(dst)
dst = dst[m.N.SizeBytes():]
MarshalUnsafeMsg1Slice(m.Arr, dst)
func (m *MsgDynamic) MarshalBytes(dst []byte) []byte {
dst = m.N.MarshalUnsafe(dst)
n, err := MarshalUnsafeMsg1Slice(m.Arr, dst)
if err != nil {
panic(err)
}
return dst[n:]
}
// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
func (m *MsgDynamic) UnmarshalBytes(src []byte) {
m.N.UnmarshalUnsafe(src)
src = src[m.N.SizeBytes():]
func (m *MsgDynamic) UnmarshalBytes(src []byte) []byte {
src = m.N.UnmarshalUnsafe(src)
m.Arr = make([]MsgSimple, m.N)
UnmarshalUnsafeMsg1Slice(m.Arr, src)
n, err := UnmarshalUnsafeMsg1Slice(m.Arr, src)
if err != nil {
panic(err)
}
return src[n:]
}
// Randomize randomizes the contents of m.
@@ -90,21 +96,18 @@ func (v *P9Version) SizeBytes() int {
}
// MarshalBytes implements marshal.Marshallable.MarshalBytes.
func (v *P9Version) MarshalBytes(dst []byte) {
v.MSize.MarshalUnsafe(dst)
dst = dst[v.MSize.SizeBytes():]
func (v *P9Version) MarshalBytes(dst []byte) []byte {
dst = v.MSize.MarshalUnsafe(dst)
versionLen := primitive.Uint16(len(v.Version))
versionLen.MarshalUnsafe(dst)
dst = dst[versionLen.SizeBytes():]
copy(dst, v.Version)
dst = versionLen.MarshalUnsafe(dst)
return dst[copy(dst, v.Version):]
}
// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
func (v *P9Version) UnmarshalBytes(src []byte) {
v.MSize.UnmarshalUnsafe(src)
src = src[v.MSize.SizeBytes():]
func (v *P9Version) UnmarshalBytes(src []byte) []byte {
src = v.MSize.UnmarshalUnsafe(src)
var versionLen primitive.Uint16
versionLen.UnmarshalUnsafe(src)
src = src[versionLen.SizeBytes():]
src = versionLen.UnmarshalUnsafe(src)
v.Version = string(src[:versionLen])
return src[versionLen:]
}
+8 -6
View File
@@ -59,13 +59,15 @@ type Marshallable interface {
// likely make use of the type of these fields).
SizeBytes() int
// MarshalBytes serializes a copy of a type to dst.
// MarshalBytes serializes a copy of a type to dst and returns the remaining
// buffer.
// Precondition: dst must be at least SizeBytes() in length.
MarshalBytes(dst []byte)
MarshalBytes(dst []byte) []byte
// UnmarshalBytes deserializes a type from src.
// UnmarshalBytes deserializes a type from src and returns the remaining
// buffer.
// Precondition: src must be at least SizeBytes() in length.
UnmarshalBytes(src []byte)
UnmarshalBytes(src []byte) []byte
// Packed returns true if the marshalled size of the type is the same as the
// size it occupies in memory. This happens when the type has no fields
@@ -86,7 +88,7 @@ type Marshallable interface {
// return false, MarshalUnsafe should fall back to the safer but slower
// MarshalBytes.
// Precondition: dst must be at least SizeBytes() in length.
MarshalUnsafe(dst []byte)
MarshalUnsafe(dst []byte) []byte
// UnmarshalUnsafe deserializes a type by directly copying to the underlying
// memory allocated for the object by the runtime.
@@ -96,7 +98,7 @@ type Marshallable interface {
// UnmarshalUnsafe should fall back to the safer but slower unmarshal
// mechanism implemented in UnmarshalBytes.
// Precondition: src must be at least SizeBytes() in length.
UnmarshalUnsafe(src []byte)
UnmarshalUnsafe(src []byte) []byte
// CopyIn deserializes a Marshallable type from a task's memory. This may
// only be called from a task goroutine. This is more efficient than calling
+4 -4
View File
@@ -38,12 +38,12 @@ func (StubMarshallable) SizeBytes() int {
}
// MarshalBytes implements Marshallable.MarshalBytes.
func (StubMarshallable) MarshalBytes(dst []byte) {
func (StubMarshallable) MarshalBytes(dst []byte) []byte {
panic("Please implement your own MarshalBytes function")
}
// UnmarshalBytes implements Marshallable.UnmarshalBytes.
func (StubMarshallable) UnmarshalBytes(src []byte) {
func (StubMarshallable) UnmarshalBytes(src []byte) []byte {
panic("Please implement your own UnmarshalBytes function")
}
@@ -53,12 +53,12 @@ func (StubMarshallable) Packed() bool {
}
// MarshalUnsafe implements Marshallable.MarshalUnsafe.
func (StubMarshallable) MarshalUnsafe(dst []byte) {
func (StubMarshallable) MarshalUnsafe(dst []byte) []byte {
panic("Please implement your own MarshalUnsafe function")
}
// UnmarshalUnsafe implements Marshallable.UnmarshalUnsafe.
func (StubMarshallable) UnmarshalUnsafe(src []byte) {
func (StubMarshallable) UnmarshalUnsafe(src []byte) []byte {
panic("Please implement your own UnmarshalUnsafe function")
}
+8 -8
View File
@@ -76,13 +76,13 @@ func (b *ByteSlice) SizeBytes() int {
}
// MarshalBytes implements marshal.Marshallable.MarshalBytes.
func (b *ByteSlice) MarshalBytes(dst []byte) {
copy(dst, *b)
func (b *ByteSlice) MarshalBytes(dst []byte) []byte {
return dst[copy(dst, *b):]
}
// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
func (b *ByteSlice) UnmarshalBytes(src []byte) {
copy(*b, src)
func (b *ByteSlice) UnmarshalBytes(src []byte) []byte {
return src[copy(*b, src):]
}
// Packed implements marshal.Marshallable.Packed.
@@ -91,13 +91,13 @@ func (b *ByteSlice) Packed() bool {
}
// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
func (b *ByteSlice) MarshalUnsafe(dst []byte) {
b.MarshalBytes(dst)
func (b *ByteSlice) MarshalUnsafe(dst []byte) []byte {
return b.MarshalBytes(dst)
}
// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
func (b *ByteSlice) UnmarshalUnsafe(src []byte) {
b.UnmarshalBytes(src)
func (b *ByteSlice) UnmarshalUnsafe(src []byte) []byte {
return b.UnmarshalBytes(src)
}
// CopyIn implements marshal.Marshallable.CopyIn.
+1 -2
View File
@@ -77,8 +77,7 @@ go_test(
deps = [
"//pkg/abi/linux",
"//pkg/errors/linuxerr",
"//pkg/hostarch",
"//pkg/marshal",
"//pkg/marshal/primitive",
"//pkg/sentry/fsimpl/testutil",
"//pkg/sentry/kernel",
"//pkg/sentry/kernel/auth",
+4 -7
View File
@@ -20,6 +20,7 @@ import (
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/marshal/primitive"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
)
@@ -69,14 +70,10 @@ func TestConnectionAbort(t *testing.T) {
t.Fatalf("newTestConnection: %v", err)
}
testObj := &testPayload{
data: rand.Uint32(),
}
var futNormal []*futureResponse
testObj := primitive.Uint32(rand.Uint32())
for i := 0; i < int(numRequests); i++ {
req := conn.NewRequest(creds, uint32(i), uint64(i), 0, testObj)
req := conn.NewRequest(creds, uint32(i), uint64(i), 0, &testObj)
fut, err := conn.callFutureLocked(task, req)
if err != nil {
t.Fatalf("callFutureLocked failed: %v", err)
@@ -102,7 +99,7 @@ func TestConnectionAbort(t *testing.T) {
}
// After abort, Call() should return directly with ENOTCONN.
req := conn.NewRequest(creds, 0, 0, 0, testObj)
req := conn.NewRequest(creds, 0, 0, 0, &testObj)
_, err = conn.Call(task, req)
if !linuxerr.Equals(linuxerr.ENOTCONN, err) {
t.Fatalf("Incorrect error code received for Call() after connection aborted")
+9 -10
View File
@@ -21,6 +21,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/marshal/primitive"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/testutil"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
@@ -215,11 +216,9 @@ func fuseClientRun(t *testing.T, s *testutil.System, k *kernel.Kernel, conn *con
if err != nil {
t.Fatal(err)
}
testObj := &testPayload{
data: rand.Uint32(),
}
req := conn.NewRequest(creds, pid, inode, echoTestOpcode, testObj)
testObj := primitive.Uint32(rand.Uint32())
req := conn.NewRequest(creds, pid, inode, echoTestOpcode, &testObj)
// Queue up a request.
// Analogous to Call except it doesn't block on the task.
@@ -232,7 +231,7 @@ func fuseClientRun(t *testing.T, s *testutil.System, k *kernel.Kernel, conn *con
t.Fatalf("Server responded with an error: %v", err)
}
var respTestPayload testPayload
var respTestPayload primitive.Uint32
if err := resp.UnmarshalPayload(&respTestPayload); err != nil {
t.Fatalf("Unmarshalling payload error: %v", err)
}
@@ -242,8 +241,8 @@ func fuseClientRun(t *testing.T, s *testutil.System, k *kernel.Kernel, conn *con
req.hdr.Unique, resp.hdr.Unique)
}
if respTestPayload.data != testObj.data {
t.Fatalf("read incorrect data. Data expected: %v, but got %v", testObj.data, respTestPayload.data)
if respTestPayload != testObj {
t.Fatalf("read incorrect data. Data expected: %d, but got %d", testObj, respTestPayload)
}
}
@@ -256,8 +255,8 @@ func fuseServerRun(t *testing.T, s *testutil.System, k *kernel.Kernel, fd *vfs.F
// Create the tasks that the server will be using.
tc := k.NewThreadGroup(nil, k.RootPIDNamespace(), kernel.NewSignalHandlers(), linux.SIGCHLD, k.GlobalInit().Limits())
var readPayload testPayload
var readPayload primitive.Uint32
serverTask, err := testutil.CreateTask(s.Ctx, "fuse-server", tc, s.MntNs, s.Root, s.Root)
if err != nil {
t.Fatal(err)
@@ -291,8 +290,8 @@ func fuseServerRun(t *testing.T, s *testutil.System, k *kernel.Kernel, fd *vfs.F
}
var readFUSEHeaderIn linux.FUSEHeaderIn
readFUSEHeaderIn.UnmarshalUnsafe(inBuf[:inHdrLen])
readPayload.UnmarshalUnsafe(inBuf[inHdrLen : inHdrLen+payloadLen])
inBuf = readFUSEHeaderIn.UnmarshalUnsafe(inBuf)
readPayload.UnmarshalUnsafe(inBuf)
if readFUSEHeaderIn.Opcode != echoTestOpcode {
t.Fatalf("read incorrect data. Header: %v, Payload: %v", readFUSEHeaderIn, readPayload)
+8 -8
View File
@@ -489,7 +489,7 @@ func (i *inode) Open(ctx context.Context, rp *vfs.ResolvingPath, d *kernfs.Dentr
// Lookup implements kernfs.Inode.Lookup.
func (i *inode) Lookup(ctx context.Context, name string) (kernfs.Inode, error) {
in := linux.FUSELookupIn{Name: name}
in := linux.FUSELookupIn{Name: linux.CString(name)}
return i.newEntry(ctx, name, 0, linux.FUSE_LOOKUP, &in)
}
@@ -520,7 +520,7 @@ func (i *inode) NewFile(ctx context.Context, name string, opts vfs.OpenOptions)
Mode: uint32(opts.Mode) | linux.S_IFREG,
Umask: uint32(kernelTask.FSContext().Umask()),
},
Name: name,
Name: linux.CString(name),
}
return i.newEntry(ctx, name, linux.S_IFREG, linux.FUSE_CREATE, &in)
}
@@ -533,7 +533,7 @@ func (i *inode) NewNode(ctx context.Context, name string, opts vfs.MknodOptions)
Rdev: linux.MakeDeviceID(uint16(opts.DevMajor), opts.DevMinor),
Umask: uint32(kernel.TaskFromContext(ctx).FSContext().Umask()),
},
Name: name,
Name: linux.CString(name),
}
return i.newEntry(ctx, name, opts.Mode.FileType(), linux.FUSE_MKNOD, &in)
}
@@ -541,8 +541,8 @@ func (i *inode) NewNode(ctx context.Context, name string, opts vfs.MknodOptions)
// NewSymlink implements kernfs.Inode.NewSymlink.
func (i *inode) NewSymlink(ctx context.Context, name, target string) (kernfs.Inode, error) {
in := linux.FUSESymLinkIn{
Name: name,
Target: target,
Name: linux.CString(name),
Target: linux.CString(target),
}
return i.newEntry(ctx, name, linux.S_IFLNK, linux.FUSE_SYMLINK, &in)
}
@@ -554,7 +554,7 @@ func (i *inode) Unlink(ctx context.Context, name string, child kernfs.Inode) err
log.Warningf("fusefs.Inode.newEntry: couldn't get kernel task from context", i.nodeID)
return linuxerr.EINVAL
}
in := linux.FUSEUnlinkIn{Name: name}
in := linux.FUSEUnlinkIn{Name: linux.CString(name)}
req := i.fs.conn.NewRequest(auth.CredentialsFromContext(ctx), uint32(kernelTask.ThreadID()), i.nodeID, linux.FUSE_UNLINK, &in)
res, err := i.fs.conn.Call(kernelTask, req)
if err != nil {
@@ -571,7 +571,7 @@ func (i *inode) NewDir(ctx context.Context, name string, opts vfs.MkdirOptions)
Mode: uint32(opts.Mode),
Umask: uint32(kernel.TaskFromContext(ctx).FSContext().Umask()),
},
Name: name,
Name: linux.CString(name),
}
return i.newEntry(ctx, name, linux.S_IFDIR, linux.FUSE_MKDIR, &in)
}
@@ -581,7 +581,7 @@ func (i *inode) RmDir(ctx context.Context, name string, child kernfs.Inode) erro
fusefs := i.fs
task, creds := kernel.TaskFromContext(ctx), auth.CredentialsFromContext(ctx)
in := linux.FUSERmDirIn{Name: name}
in := linux.FUSERmDirIn{Name: linux.CString(name)}
req := fusefs.conn.NewRequest(creds, uint32(task.ThreadID()), i.nodeID, linux.FUSE_RMDIR, &in)
res, err := i.fs.conn.Call(task, req)
if err != nil {
+2 -2
View File
@@ -41,7 +41,7 @@ type fuseInitRes struct {
}
// UnmarshalBytes deserializes src to the initOut attribute in a fuseInitRes.
func (r *fuseInitRes) UnmarshalBytes(src []byte) {
func (r *fuseInitRes) UnmarshalBytes(src []byte) []byte {
out := &r.initOut
// Introduced before FUSE kernel version 7.13.
@@ -70,7 +70,7 @@ func (r *fuseInitRes) UnmarshalBytes(src []byte) {
out.MaxPages = uint16(hostarch.ByteOrder.Uint16(src[:2]))
src = src[2:]
}
_ = src // Remove unused warning.
return src
}
// SizeBytes is the size of the payload of the FUSE_INIT response.
-59
View File
@@ -15,17 +15,13 @@
package fuse
import (
"io"
"testing"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/marshal"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/testutil"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/hostarch"
)
func setup(t *testing.T) *testutil.System {
@@ -70,58 +66,3 @@ func newTestConnection(system *testutil.System, k *kernel.Kernel, maxActiveReque
}
return fs.conn, &fuseDev.vfsfd, nil
}
type testPayload struct {
marshal.StubMarshallable
data uint32
}
// SizeBytes implements marshal.Marshallable.SizeBytes.
func (t *testPayload) SizeBytes() int {
return 4
}
// MarshalBytes implements marshal.Marshallable.MarshalBytes.
func (t *testPayload) MarshalBytes(dst []byte) {
hostarch.ByteOrder.PutUint32(dst[:4], t.data)
}
// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
func (t *testPayload) UnmarshalBytes(src []byte) {
*t = testPayload{data: hostarch.ByteOrder.Uint32(src[:4])}
}
// Packed implements marshal.Marshallable.Packed.
func (t *testPayload) Packed() bool {
return true
}
// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
func (t *testPayload) MarshalUnsafe(dst []byte) {
t.MarshalBytes(dst)
}
// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
func (t *testPayload) UnmarshalUnsafe(src []byte) {
t.UnmarshalBytes(src)
}
// CopyOutN implements marshal.Marshallable.CopyOutN.
func (t *testPayload) CopyOutN(task marshal.CopyContext, addr hostarch.Addr, limit int) (int, error) {
panic("not implemented")
}
// CopyOut implements marshal.Marshallable.CopyOut.
func (t *testPayload) CopyOut(task marshal.CopyContext, addr hostarch.Addr) (int, error) {
panic("not implemented")
}
// CopyIn implements marshal.Marshallable.CopyIn.
func (t *testPayload) CopyIn(task marshal.CopyContext, addr hostarch.Addr) (int, error) {
panic("not implemented")
}
// WriteTo implements io.WriterTo.WriteTo.
func (t *testPayload) WriteTo(w io.Writer) (int64, error) {
panic("not implemented")
}
+1 -2
View File
@@ -212,8 +212,7 @@ func parseHeader(ctx context.Context, f fullReader) (elfInfo, error) {
phdrs := make([]elf.ProgHeader, hdr.Phnum)
for i := range phdrs {
var prog64 linux.ElfProg64
prog64.UnmarshalUnsafe(phdrBuf[:prog64Size])
phdrBuf = phdrBuf[prog64Size:]
phdrBuf = prog64.UnmarshalUnsafe(phdrBuf)
phdrs[i] = elf.ProgHeader{
Type: elf.ProgType(prog64.Type),
Flags: elf.ProgFlag(prog64.Flags),
+28 -35
View File
@@ -17,6 +17,8 @@
package control
import (
"time"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/bits"
"gvisor.dev/gvisor/pkg/context"
@@ -29,7 +31,6 @@ import (
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/socket"
"gvisor.dev/gvisor/pkg/sentry/socket/unix/transport"
"time"
)
// SCMCredentials represents a SCM_CREDENTIALS socket control message.
@@ -63,10 +64,10 @@ type RightsFiles []*fs.File
// NewSCMRights creates a new SCM_RIGHTS socket control message representation
// using local sentry FDs.
func NewSCMRights(t *kernel.Task, fds []int32) (SCMRights, error) {
func NewSCMRights(t *kernel.Task, fds []primitive.Int32) (SCMRights, error) {
files := make(RightsFiles, 0, len(fds))
for _, fd := range fds {
file := t.GetFile(fd)
file := t.GetFile(int32(fd))
if file == nil {
files.Release(t)
return nil, linuxerr.EBADF
@@ -486,27 +487,26 @@ func CmsgsSpace(t *kernel.Task, cmsgs socket.ControlMessages) int {
func Parse(t *kernel.Task, socketOrEndpoint interface{}, buf []byte, width uint) (socket.ControlMessages, error) {
var (
cmsgs socket.ControlMessages
fds linux.ControlMessageRights
fds []primitive.Int32
)
for i := 0; i < len(buf); {
if i+linux.SizeOfControlMessageHeader > len(buf) {
for len(buf) > 0 {
if linux.SizeOfControlMessageHeader > len(buf) {
return cmsgs, linuxerr.EINVAL
}
var h linux.ControlMessageHeader
h.UnmarshalUnsafe(buf[i : i+linux.SizeOfControlMessageHeader])
buf = h.UnmarshalUnsafe(buf)
if h.Length < uint64(linux.SizeOfControlMessageHeader) {
return socket.ControlMessages{}, linuxerr.EINVAL
}
if h.Length > uint64(len(buf)-i) {
length := int(h.Length) - linux.SizeOfControlMessageHeader
if length > len(buf) {
return socket.ControlMessages{}, linuxerr.EINVAL
}
i += linux.SizeOfControlMessageHeader
length := int(h.Length) - linux.SizeOfControlMessageHeader
switch h.Level {
case linux.SOL_SOCKET:
switch h.Type {
@@ -518,11 +518,9 @@ func Parse(t *kernel.Task, socketOrEndpoint interface{}, buf []byte, width uint)
return socket.ControlMessages{}, linuxerr.EINVAL
}
for j := i; j < i+rightsSize; j += linux.SizeOfControlMessageRight {
fds = append(fds, int32(hostarch.ByteOrder.Uint32(buf[j:j+linux.SizeOfControlMessageRight])))
}
i += bits.AlignUp(length, width)
curFDs := make([]primitive.Int32, numRights)
primitive.UnmarshalUnsafeInt32Slice(curFDs, buf[:rightsSize])
fds = append(fds, curFDs...)
case linux.SCM_CREDENTIALS:
if length < linux.SizeOfControlMessageCredentials {
@@ -530,23 +528,21 @@ func Parse(t *kernel.Task, socketOrEndpoint interface{}, buf []byte, width uint)
}
var creds linux.ControlMessageCredentials
creds.UnmarshalUnsafe(buf[i : i+linux.SizeOfControlMessageCredentials])
creds.UnmarshalUnsafe(buf)
scmCreds, err := NewSCMCredentials(t, creds)
if err != nil {
return socket.ControlMessages{}, err
}
cmsgs.Unix.Credentials = scmCreds
i += bits.AlignUp(length, width)
case linux.SO_TIMESTAMP:
if length < linux.SizeOfTimeval {
return socket.ControlMessages{}, linuxerr.EINVAL
}
var ts linux.Timeval
ts.UnmarshalUnsafe(buf[i : i+linux.SizeOfTimeval])
ts.UnmarshalUnsafe(buf)
cmsgs.IP.Timestamp = ts.ToTime()
cmsgs.IP.HasTimestamp = true
i += bits.AlignUp(length, width)
default:
// Unknown message type.
@@ -560,9 +556,8 @@ func Parse(t *kernel.Task, socketOrEndpoint interface{}, buf []byte, width uint)
}
cmsgs.IP.HasTOS = true
var tos primitive.Uint8
tos.UnmarshalUnsafe(buf[i : i+linux.SizeOfControlMessageTOS])
tos.UnmarshalUnsafe(buf)
cmsgs.IP.TOS = uint8(tos)
i += bits.AlignUp(length, width)
case linux.IP_PKTINFO:
if length < linux.SizeOfControlMessageIPPacketInfo {
@@ -571,19 +566,16 @@ func Parse(t *kernel.Task, socketOrEndpoint interface{}, buf []byte, width uint)
cmsgs.IP.HasIPPacketInfo = true
var packetInfo linux.ControlMessageIPPacketInfo
packetInfo.UnmarshalUnsafe(buf[i : i+linux.SizeOfControlMessageIPPacketInfo])
packetInfo.UnmarshalUnsafe(buf)
cmsgs.IP.PacketInfo = packetInfo
i += bits.AlignUp(length, width)
case linux.IP_RECVORIGDSTADDR:
var addr linux.SockAddrInet
if length < addr.SizeBytes() {
return socket.ControlMessages{}, linuxerr.EINVAL
}
addr.UnmarshalUnsafe(buf[i : i+addr.SizeBytes()])
addr.UnmarshalUnsafe(buf)
cmsgs.IP.OriginalDstAddress = &addr
i += bits.AlignUp(length, width)
case linux.IP_RECVERR:
var errCmsg linux.SockErrCMsgIPv4
@@ -591,9 +583,8 @@ func Parse(t *kernel.Task, socketOrEndpoint interface{}, buf []byte, width uint)
return socket.ControlMessages{}, linuxerr.EINVAL
}
errCmsg.UnmarshalBytes(buf[i : i+errCmsg.SizeBytes()])
errCmsg.UnmarshalBytes(buf)
cmsgs.IP.SockErr = &errCmsg
i += bits.AlignUp(length, width)
default:
return socket.ControlMessages{}, linuxerr.EINVAL
@@ -606,18 +597,16 @@ func Parse(t *kernel.Task, socketOrEndpoint interface{}, buf []byte, width uint)
}
cmsgs.IP.HasTClass = true
var tclass primitive.Uint32
tclass.UnmarshalUnsafe(buf[i : i+linux.SizeOfControlMessageTClass])
tclass.UnmarshalUnsafe(buf)
cmsgs.IP.TClass = uint32(tclass)
i += bits.AlignUp(length, width)
case linux.IPV6_RECVORIGDSTADDR:
var addr linux.SockAddrInet6
if length < addr.SizeBytes() {
return socket.ControlMessages{}, linuxerr.EINVAL
}
addr.UnmarshalUnsafe(buf[i : i+addr.SizeBytes()])
addr.UnmarshalUnsafe(buf)
cmsgs.IP.OriginalDstAddress = &addr
i += bits.AlignUp(length, width)
case linux.IPV6_RECVERR:
var errCmsg linux.SockErrCMsgIPv6
@@ -625,9 +614,8 @@ func Parse(t *kernel.Task, socketOrEndpoint interface{}, buf []byte, width uint)
return socket.ControlMessages{}, linuxerr.EINVAL
}
errCmsg.UnmarshalBytes(buf[i : i+errCmsg.SizeBytes()])
errCmsg.UnmarshalBytes(buf)
cmsgs.IP.SockErr = &errCmsg
i += bits.AlignUp(length, width)
default:
return socket.ControlMessages{}, linuxerr.EINVAL
@@ -635,6 +623,11 @@ func Parse(t *kernel.Task, socketOrEndpoint interface{}, buf []byte, width uint)
default:
return socket.ControlMessages{}, linuxerr.EINVAL
}
if shift := bits.AlignUp(length, width); shift > len(buf) {
buf = buf[:0]
} else {
buf = buf[shift:]
}
}
if cmsgs.Unix.Credentials == nil {
+3 -2
View File
@@ -18,6 +18,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/marshal/primitive"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/socket/unix/transport"
"gvisor.dev/gvisor/pkg/sentry/vfs"
@@ -45,10 +46,10 @@ type RightsFilesVFS2 []*vfs.FileDescription
// NewSCMRightsVFS2 creates a new SCM_RIGHTS socket control message
// representation using local sentry FDs.
func NewSCMRightsVFS2(t *kernel.Task, fds []int32) (SCMRightsVFS2, error) {
func NewSCMRightsVFS2(t *kernel.Task, fds []primitive.Int32) (SCMRightsVFS2, error) {
files := make(RightsFilesVFS2, 0, len(fds))
for _, fd := range fds {
file := t.GetFileVFS2(fd)
file := t.GetFileVFS2(int32(fd))
if file == nil {
files.Release(t)
return nil, linuxerr.EBADF

Some files were not shown because too many files have changed in this diff Show More