diff options
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/abi/linux/fuse.go | 175 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/fuse/BUILD | 1 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/fuse/init.go | 4 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/fuse/request_response.go | 78 |
4 files changed, 81 insertions, 177 deletions
diff --git a/pkg/abi/linux/fuse.go b/pkg/abi/linux/fuse.go index ca4ee5e80..5616290a5 100644 --- a/pkg/abi/linux/fuse.go +++ b/pkg/abi/linux/fuse.go @@ -15,7 +15,6 @@ package linux import ( - "gvisor.dev/gvisor/pkg/usermem" "gvisor.dev/gvisor/tools/go_marshal/marshal" "gvisor.dev/gvisor/tools/go_marshal/primitive" ) @@ -263,63 +262,6 @@ type FUSEInitOut struct { _ [8]uint32 } -// FUSEInitRes is a variable-length wrapper of FUSEInitOut. The FUSE server may -// implement older version of FUSE protocol, which contains a FUSEInitOut with -// less attributes. -// -// Dynamically-sized objects cannot be marshalled. -type FUSEInitRes struct { - marshal.StubMarshallable - - // InitOut contains the response from the FUSE server. - InitOut FUSEInitOut - - // Len is the total length of bytes of the response. - Len uint32 -} - -// UnMarshalBytes deserializes src to the InitOut attribute in a FUSEInitRes. -func (r *FUSEInitRes) UnmarshalBytes(src []byte) { - out := &r.InitOut - - // Introduced before FUSE kernel version 7.13. - out.Major = uint32(usermem.ByteOrder.Uint32(src[:4])) - src = src[4:] - out.Minor = uint32(usermem.ByteOrder.Uint32(src[:4])) - src = src[4:] - out.MaxReadahead = uint32(usermem.ByteOrder.Uint32(src[:4])) - src = src[4:] - out.Flags = uint32(usermem.ByteOrder.Uint32(src[:4])) - src = src[4:] - out.MaxBackground = uint16(usermem.ByteOrder.Uint16(src[:2])) - src = src[2:] - out.CongestionThreshold = uint16(usermem.ByteOrder.Uint16(src[:2])) - src = src[2:] - out.MaxWrite = uint32(usermem.ByteOrder.Uint32(src[:4])) - src = src[4:] - - // Introduced in FUSE kernel version 7.23. - if len(src) >= 4 { - out.TimeGran = uint32(usermem.ByteOrder.Uint32(src[:4])) - src = src[4:] - } - // Introduced in FUSE kernel version 7.28. - if len(src) >= 2 { - out.MaxPages = uint16(usermem.ByteOrder.Uint16(src[:2])) - src = src[2:] - } - // Introduced in FUSE kernel version 7.31. - if len(src) >= 2 { - out.MapAlignment = uint16(usermem.ByteOrder.Uint16(src[:2])) - src = src[2:] - } -} - -// SizeBytes is the size of the payload of the FUSE_INIT response. -func (r *FUSEInitRes) SizeBytes() int { - return int(r.Len) -} - // FUSEGetAttrIn is the request sent by the kernel to the daemon, // to get the attribute of a inode. // @@ -415,11 +357,6 @@ type FUSELookupIn struct { Name string } -// MarshalUnsafe serializes r.name to the dst buffer. -func (r *FUSELookupIn) MarshalUnsafe(buf []byte) { - copy(buf, r.Name) -} - // MarshalBytes serializes r.name to the dst buffer. func (r *FUSELookupIn) MarshalBytes(buf []byte) { copy(buf, r.Name) @@ -548,12 +485,6 @@ type FUSEMknodIn struct { Name string } -// MarshalUnsafe serializes r.MknodMeta and r.Name to the dst buffer. -func (r *FUSEMknodIn) MarshalUnsafe(buf []byte) { - r.MknodMeta.MarshalUnsafe(buf[:r.MknodMeta.SizeBytes()]) - 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()]) @@ -580,13 +511,6 @@ type FUSESymLinkIn struct { Target string } -// MarshalUnsafe serializes r.Name and r.Target to the dst buffer. -// Left null-termination at end of r.Name and r.Target. -func (r *FUSESymLinkIn) MarshalUnsafe(buf []byte) { - copy(buf, r.Name) - 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) { @@ -603,9 +527,6 @@ func (r *FUSESymLinkIn) SizeBytes() int { // FUSEEmptyIn is used by operations without request body. 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) {} @@ -640,12 +561,6 @@ type FUSEMkdirIn struct { Name string } -// MarshalUnsafe serializes r.MkdirMeta and r.Name to the dst buffer. -func (r *FUSEMkdirIn) MarshalUnsafe(buf []byte) { - r.MkdirMeta.MarshalUnsafe(buf[:r.MkdirMeta.SizeBytes()]) - 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()]) @@ -669,11 +584,6 @@ type FUSERmDirIn struct { Name string } -// MarshalUnsafe serializes r.name to the dst buffer. -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) @@ -684,16 +594,6 @@ func (r *FUSERmDirIn) SizeBytes() int { return len(r.Name) + 1 } -// UnmarshalUnsafe deserializes r.name from the src buffer. -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. // @@ -736,22 +636,6 @@ type FUSEDirentMeta struct { Type uint32 } -// MarshalUnsafe serializes FUSEDirents to the dst buffer. -func (r *FUSEDirents) MarshalUnsafe(dst []byte) { - for _, dirent := range r.Dirents { - dirent.MarshalUnsafe(dst) - dst = dst[dirent.SizeBytes():] - } -} - -// 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 @@ -762,30 +646,6 @@ func (r *FUSEDirents) SizeBytes() int { return sizeBytes } -// UnmarshalUnsafe deserializes FUSEDirents from the src buffer. -func (r *FUSEDirents) UnmarshalUnsafe(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.UnmarshalUnsafe(src) - r.Dirents = append(r.Dirents, &dirent) - - src = src[dirent.SizeBytes():] - } -} - // UnmarshalBytes deserializes FUSEDirents from the src buffer. func (r *FUSEDirents) UnmarshalBytes(src []byte) { for { @@ -810,24 +670,6 @@ func (r *FUSEDirents) UnmarshalBytes(src []byte) { } } -// MarshalUnsafe serializes FUSEDirent to the dst buffer. -func (r *FUSEDirent) MarshalUnsafe(dst []byte) { - r.Meta.MarshalUnsafe(dst) - dst = dst[r.Meta.SizeBytes():] - - name := primitive.ByteSlice(r.Name) - 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) @@ -838,23 +680,6 @@ func (r *FUSEDirent) SizeBytes() int { return (dataSize + (FUSE_DIRENT_ALIGN - 1)) & ^(FUSE_DIRENT_ALIGN - 1) } -// UnmarshalUnsafe deserializes FUSEDirent from the src buffer. -func (r *FUSEDirent) UnmarshalUnsafe(src []byte) { - r.Meta.UnmarshalUnsafe(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.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) diff --git a/pkg/sentry/fsimpl/fuse/BUILD b/pkg/sentry/fsimpl/fuse/BUILD index 241d50c3d..5085d0521 100644 --- a/pkg/sentry/fsimpl/fuse/BUILD +++ b/pkg/sentry/fsimpl/fuse/BUILD @@ -40,6 +40,7 @@ go_library( "register.go", "regular_file.go", "request_list.go", + "request_response.go", ], visibility = ["//pkg/sentry:internal"], deps = [ diff --git a/pkg/sentry/fsimpl/fuse/init.go b/pkg/sentry/fsimpl/fuse/init.go index 6384cbbdb..256b6fb65 100644 --- a/pkg/sentry/fsimpl/fuse/init.go +++ b/pkg/sentry/fsimpl/fuse/init.go @@ -76,12 +76,12 @@ func (conn *connection) InitRecv(res *Response, hasSysAdminCap bool) error { return err } - initRes := linux.FUSEInitRes{Len: res.DataLen()} + initRes := fuseInitRes{initLen: res.DataLen()} if err := res.UnmarshalPayload(&initRes); err != nil { return err } - return conn.initProcessReply(&initRes.InitOut, hasSysAdminCap) + return conn.initProcessReply(&initRes.initOut, hasSysAdminCap) } // Process the FUSE_INIT reply from the FUSE server. diff --git a/pkg/sentry/fsimpl/fuse/request_response.go b/pkg/sentry/fsimpl/fuse/request_response.go new file mode 100644 index 000000000..ae71b5e28 --- /dev/null +++ b/pkg/sentry/fsimpl/fuse/request_response.go @@ -0,0 +1,78 @@ +// Copyright 2020 The gVisor Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package fuse + +import ( + "gvisor.dev/gvisor/pkg/abi/linux" + "gvisor.dev/gvisor/pkg/usermem" + "gvisor.dev/gvisor/tools/go_marshal/marshal" +) + +// fuseInitRes is a variable-length wrapper of linux.FUSEInitOut. The FUSE +// server may implement an older version of FUSE protocol, which contains a +// linux.FUSEInitOut with less attributes. +// +// Dynamically-sized objects cannot be marshalled. +type fuseInitRes struct { + marshal.StubMarshallable + + // initOut contains the response from the FUSE server. + initOut linux.FUSEInitOut + + // initLen is the total length of bytes of the response. + initLen uint32 +} + +// UnmarshalBytes deserializes src to the initOut attribute in a fuseInitRes. +func (r *fuseInitRes) UnmarshalBytes(src []byte) { + out := &r.initOut + + // Introduced before FUSE kernel version 7.13. + out.Major = uint32(usermem.ByteOrder.Uint32(src[:4])) + src = src[4:] + out.Minor = uint32(usermem.ByteOrder.Uint32(src[:4])) + src = src[4:] + out.MaxReadahead = uint32(usermem.ByteOrder.Uint32(src[:4])) + src = src[4:] + out.Flags = uint32(usermem.ByteOrder.Uint32(src[:4])) + src = src[4:] + out.MaxBackground = uint16(usermem.ByteOrder.Uint16(src[:2])) + src = src[2:] + out.CongestionThreshold = uint16(usermem.ByteOrder.Uint16(src[:2])) + src = src[2:] + out.MaxWrite = uint32(usermem.ByteOrder.Uint32(src[:4])) + src = src[4:] + + // Introduced in FUSE kernel version 7.23. + if len(src) >= 4 { + out.TimeGran = uint32(usermem.ByteOrder.Uint32(src[:4])) + src = src[4:] + } + // Introduced in FUSE kernel version 7.28. + if len(src) >= 2 { + out.MaxPages = uint16(usermem.ByteOrder.Uint16(src[:2])) + src = src[2:] + } + // Introduced in FUSE kernel version 7.31. + if len(src) >= 2 { + out.MapAlignment = uint16(usermem.ByteOrder.Uint16(src[:2])) + src = src[2:] + } +} + +// SizeBytes is the size of the payload of the FUSE_INIT response. +func (r *fuseInitRes) SizeBytes() int { + return int(r.initLen) +} |