mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
fuse: use safe go_marshal API for FUSE
Until #3698 is resolved, this change is needed to ensure we're not corrupting memory anywhere.
This commit is contained in:
committed by
Andrei Vagin
parent
4a5857d644
commit
d51ddcefdc
+96
-1
@@ -359,7 +359,12 @@ type FUSELookupIn struct {
|
||||
|
||||
// MarshalUnsafe serializes r.name to the dst buffer.
|
||||
func (r *FUSELookupIn) MarshalUnsafe(buf []byte) {
|
||||
copy(buf, []byte(r.Name))
|
||||
copy(buf, r.Name)
|
||||
}
|
||||
|
||||
// MarshalBytes serializes r.name to the dst buffer.
|
||||
func (r *FUSELookupIn) MarshalBytes(buf []byte) {
|
||||
copy(buf, r.Name)
|
||||
}
|
||||
|
||||
// SizeBytes is the size of the memory representation of FUSELookupIn.
|
||||
@@ -491,6 +496,12 @@ func (r *FUSEMknodIn) MarshalUnsafe(buf []byte) {
|
||||
copy(buf[r.MknodMeta.SizeBytes():], r.Name)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// SizeBytes is the size of the memory representation of FUSEMknodIn.
|
||||
// 1 extra byte for null-terminated string.
|
||||
func (r *FUSEMknodIn) SizeBytes() int {
|
||||
@@ -518,6 +529,13 @@ func (r *FUSESymLinkIn) MarshalUnsafe(buf []byte) {
|
||||
copy(buf[len(r.Name)+1:], r.Target)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// SizeBytes is the size of the memory representation of FUSESymLinkIn.
|
||||
// 2 extra bytes for null-terminated string.
|
||||
func (r *FUSESymLinkIn) SizeBytes() int {
|
||||
@@ -530,6 +548,9 @@ type FUSEEmptyIn struct{ marshal.StubMarshallable }
|
||||
// MarshalUnsafe do nothing for marshal.
|
||||
func (r *FUSEEmptyIn) MarshalUnsafe(buf []byte) {}
|
||||
|
||||
// MarshalBytes do nothing for marshal.
|
||||
func (r *FUSEEmptyIn) MarshalBytes(buf []byte) {}
|
||||
|
||||
// SizeBytes is 0 for empty request.
|
||||
func (r *FUSEEmptyIn) SizeBytes() int {
|
||||
return 0
|
||||
@@ -567,6 +588,12 @@ func (r *FUSEMkdirIn) MarshalUnsafe(buf []byte) {
|
||||
copy(buf[r.MkdirMeta.SizeBytes():], r.Name)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// SizeBytes is the size of the memory representation of FUSEMkdirIn.
|
||||
// 1 extra byte for null-terminated Name string.
|
||||
func (r *FUSEMkdirIn) SizeBytes() int {
|
||||
@@ -589,6 +616,11 @@ func (r *FUSERmDirIn) MarshalUnsafe(buf []byte) {
|
||||
copy(buf, r.Name)
|
||||
}
|
||||
|
||||
// MarshalBytes serializes r.name to the dst buffer.
|
||||
func (r *FUSERmDirIn) MarshalBytes(buf []byte) {
|
||||
copy(buf, r.Name)
|
||||
}
|
||||
|
||||
// SizeBytes is the size of the memory representation of FUSERmDirIn.
|
||||
func (r *FUSERmDirIn) SizeBytes() int {
|
||||
return len(r.Name) + 1
|
||||
@@ -599,6 +631,11 @@ func (r *FUSERmDirIn) UnmarshalUnsafe(src []byte) {
|
||||
r.Name = string(src)
|
||||
}
|
||||
|
||||
// UnmarshalBytes deserializes r.name from the src buffer.
|
||||
func (r *FUSERmDirIn) UnmarshalBytes(src []byte) {
|
||||
r.Name = string(src)
|
||||
}
|
||||
|
||||
// FUSEDirents is a list of Dirents received from the FUSE daemon server.
|
||||
// It is used for FUSE_READDIR.
|
||||
//
|
||||
@@ -649,6 +686,14 @@ func (r *FUSEDirents) MarshalUnsafe(dst []byte) {
|
||||
}
|
||||
}
|
||||
|
||||
// MarshalBytes serializes FUSEDirents to the dst buffer.
|
||||
func (r *FUSEDirents) MarshalBytes(dst []byte) {
|
||||
for _, dirent := range r.Dirents {
|
||||
dirent.MarshalBytes(dst)
|
||||
dst = dst[dirent.SizeBytes():]
|
||||
}
|
||||
}
|
||||
|
||||
// SizeBytes is the size of the memory representation of FUSEDirents.
|
||||
func (r *FUSEDirents) SizeBytes() int {
|
||||
var sizeBytes int
|
||||
@@ -683,6 +728,30 @@ func (r *FUSEDirents) UnmarshalUnsafe(src []byte) {
|
||||
}
|
||||
}
|
||||
|
||||
// UnmarshalBytes deserializes FUSEDirents from the src buffer.
|
||||
func (r *FUSEDirents) UnmarshalBytes(src []byte) {
|
||||
for {
|
||||
if len(src) <= (*FUSEDirentMeta)(nil).SizeBytes() {
|
||||
break
|
||||
}
|
||||
|
||||
// Its unclear how many dirents there are in src. Each dirent is dynamically
|
||||
// sized and so we can't make assumptions about how many dirents we can allocate.
|
||||
if r.Dirents == nil {
|
||||
r.Dirents = make([]*FUSEDirent, 0)
|
||||
}
|
||||
|
||||
// We have to allocate a struct for each dirent - there must be a better way
|
||||
// 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)
|
||||
r.Dirents = append(r.Dirents, &dirent)
|
||||
|
||||
src = src[dirent.SizeBytes():]
|
||||
}
|
||||
}
|
||||
|
||||
// MarshalUnsafe serializes FUSEDirent to the dst buffer.
|
||||
func (r *FUSEDirent) MarshalUnsafe(dst []byte) {
|
||||
r.Meta.MarshalUnsafe(dst)
|
||||
@@ -692,6 +761,15 @@ func (r *FUSEDirent) MarshalUnsafe(dst []byte) {
|
||||
name.MarshalUnsafe(dst)
|
||||
}
|
||||
|
||||
// MarshalBytes serializes FUSEDirent to the dst buffer.
|
||||
func (r *FUSEDirent) MarshalBytes(dst []byte) {
|
||||
r.Meta.MarshalBytes(dst)
|
||||
dst = dst[r.Meta.SizeBytes():]
|
||||
|
||||
name := primitive.ByteSlice(r.Name)
|
||||
name.MarshalBytes(dst)
|
||||
}
|
||||
|
||||
// SizeBytes is the size of the memory representation of FUSEDirent.
|
||||
func (r *FUSEDirent) SizeBytes() int {
|
||||
dataSize := r.Meta.SizeBytes() + len(r.Name)
|
||||
@@ -718,3 +796,20 @@ func (r *FUSEDirent) UnmarshalUnsafe(src []byte) {
|
||||
name.UnmarshalUnsafe(src[:r.Meta.NameLen])
|
||||
r.Name = string(name)
|
||||
}
|
||||
|
||||
// UnmarshalBytes deserializes FUSEDirent from the src buffer.
|
||||
func (r *FUSEDirent) UnmarshalBytes(src []byte) {
|
||||
r.Meta.UnmarshalBytes(src)
|
||||
src = src[r.Meta.SizeBytes():]
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
buf := make([]byte, r.Meta.NameLen)
|
||||
name := primitive.ByteSlice(buf)
|
||||
name.UnmarshalBytes(src[:r.Meta.NameLen])
|
||||
r.Name = string(name)
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ func (StubMarshallable) MarshalBytes(dst []byte) {
|
||||
|
||||
// UnmarshalBytes implements Marshallable.UnmarshalBytes.
|
||||
func (StubMarshallable) UnmarshalBytes(src []byte) {
|
||||
panic("Please implement your own UnMarshalBytes function")
|
||||
panic("Please implement your own UnmarshalBytes function")
|
||||
}
|
||||
|
||||
// Packed implements Marshallable.Packed.
|
||||
|
||||
@@ -271,8 +271,10 @@ func (conn *connection) NewRequest(creds *auth.Credentials, pid uint32, ino uint
|
||||
}
|
||||
|
||||
buf := make([]byte, hdr.Len)
|
||||
hdr.MarshalUnsafe(buf[:hdrLen])
|
||||
payload.MarshalUnsafe(buf[hdrLen:])
|
||||
|
||||
// TODO(gVisor.dev/3698): Use the unsafe version once go_marshal is safe to use again.
|
||||
hdr.MarshalBytes(buf[:hdrLen])
|
||||
payload.MarshalBytes(buf[hdrLen:])
|
||||
|
||||
return &Request{
|
||||
id: hdr.Unique,
|
||||
@@ -360,7 +362,8 @@ func (r *Response) UnmarshalPayload(m marshal.Marshallable) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
m.UnmarshalUnsafe(r.data[hdrLen:])
|
||||
// TODO(gVisor.dev/3698): Use the unsafe version once go_marshal is safe to use again.
|
||||
m.UnmarshalBytes(r.data[hdrLen:])
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user