diff --git a/pkg/abi/linux/fuse.go b/pkg/abi/linux/fuse.go index 0147077a3..71a6f95e6 100644 --- a/pkg/abi/linux/fuse.go +++ b/pkg/abi/linux/fuse.go @@ -15,7 +15,6 @@ package linux import ( - "gvisor.dev/gvisor/pkg/marshal" "gvisor.dev/gvisor/pkg/marshal/primitive" ) @@ -353,6 +352,8 @@ type FUSEEntryOut struct { } // CString represents a null terminated string which can be marshalled. +// +// +marshal dynamic type CString string // MarshalBytes implements marshal.Marshallable.MarshalBytes. @@ -362,6 +363,11 @@ func (s *CString) MarshalBytes(buf []byte) []byte { return buf[s.SizeBytes():] } +// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes. +func (s *CString) UnmarshalBytes(buf []byte) []byte { + panic("Unimplemented, CString is never unmarshalled") +} + // SizeBytes implements marshal.Marshallable.SizeBytes. func (s *CString) SizeBytes() int { // 1 extra byte for null-terminated string. @@ -371,20 +377,23 @@ func (s *CString) SizeBytes() int { // FUSELookupIn is the request sent by the kernel to the daemon // to look up a file name. // -// Dynamically-sized objects cannot be marshalled. +// +marshal dynamic type FUSELookupIn struct { - marshal.StubMarshallable - // Name is a file name to be looked up. Name CString } -// MarshalBytes serializes r.name to the dst buffer. +// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes. +func (r *FUSELookupIn) UnmarshalBytes(buf []byte) []byte { + panic("Unimplemented, FUSELookupIn is never unmarshalled") +} + +// MarshalBytes implements marshal.Marshallable.MarshalBytes. func (r *FUSELookupIn) MarshalBytes(buf []byte) []byte { return r.Name.MarshalBytes(buf) } -// SizeBytes is the size of the memory representation of FUSELookupIn. +// SizeBytes implements marshal.Marshallable.SizeBytes. func (r *FUSELookupIn) SizeBytes() int { return r.Name.SizeBytes() } @@ -537,10 +546,8 @@ type FUSECreateMeta struct { // FUSECreateIn contains all the arguments sent by the kernel to the daemon, to // atomically create and open a new regular file. // -// Dynamically-sized objects cannot be marshalled. +// +marshal dynamic type FUSECreateIn struct { - marshal.StubMarshallable - // CreateMeta contains mode, rdev and umash field for FUSE_MKNODS. CreateMeta FUSECreateMeta @@ -548,13 +555,18 @@ type FUSECreateIn struct { Name CString } -// MarshalBytes serializes r.CreateMeta and r.Name to the dst buffer. +// MarshalBytes implements marshal.Marshallable.MarshalBytes. 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. +// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes. +func (r *FUSECreateIn) UnmarshalBytes(buf []byte) []byte { + panic("Unimplemented, FUSECreateIn is never unmarshalled") +} + +// SizeBytes implements marshal.Marshallable.SizeBytes. func (r *FUSECreateIn) SizeBytes() int { return r.CreateMeta.SizeBytes() + r.Name.SizeBytes() } @@ -579,35 +591,35 @@ type FUSEMknodMeta struct { // FUSEMknodIn contains all the arguments sent by the kernel // to the daemon, to create a new file node. // -// Dynamically-sized objects cannot be marshalled. +// +marshal dynamic type FUSEMknodIn struct { - marshal.StubMarshallable - // MknodMeta contains mode, rdev and umash field for FUSE_MKNODS. MknodMeta FUSEMknodMeta - // Name is the name of the node to create. Name CString } -// MarshalBytes serializes r.MknodMeta and r.Name to the dst buffer. +// MarshalBytes implements marshal.Marshallable.MarshalBytes. 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. +// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes. +func (r *FUSEMknodIn) UnmarshalBytes(buf []byte) []byte { + panic("Unimplemented, FUSEMknodIn is never unmarshalled") +} + +// SizeBytes implements marshal.Marshallable.SizeBytes. func (r *FUSEMknodIn) SizeBytes() int { return r.MknodMeta.SizeBytes() + r.Name.SizeBytes() } -// FUSESymLinkIn is the request sent by the kernel to the daemon, +// FUSESymlinkIn is the request sent by the kernel to the daemon, // to create a symbolic link. // -// Dynamically-sized objects cannot be marshalled. -type FUSESymLinkIn struct { - marshal.StubMarshallable - +// +marshal dynamic +type FUSESymlinkIn struct { // Name of symlink to create. Name CString @@ -615,26 +627,38 @@ type FUSESymLinkIn struct { Target CString } -// MarshalBytes serializes r.Name and r.Target to the dst buffer. -func (r *FUSESymLinkIn) MarshalBytes(buf []byte) []byte { +// MarshalBytes implements marshal.Marshallable.MarshalBytes. +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. -func (r *FUSESymLinkIn) SizeBytes() int { +// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes. +func (r *FUSESymlinkIn) UnmarshalBytes(buf []byte) []byte { + panic("Unimplemented, FUSEMknodIn is never unmarshalled") +} + +// SizeBytes implements marshal.Marshallable.SizeBytes. +func (r *FUSESymlinkIn) SizeBytes() int { return r.Name.SizeBytes() + r.Target.SizeBytes() } // FUSEEmptyIn is used by operations without request body. -type FUSEEmptyIn struct{ marshal.StubMarshallable } +// +// +marshal dynamic +type FUSEEmptyIn struct{} -// MarshalBytes do nothing for marshal. +// MarshalBytes implements marshal.Marshallable.MarshalBytes. func (r *FUSEEmptyIn) MarshalBytes(buf []byte) []byte { return buf } -// SizeBytes is 0 for empty request. +// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes. +func (r *FUSEEmptyIn) UnmarshalBytes(buf []byte) []byte { + panic("Unimplemented, FUSEEmptyIn is never unmarshalled") +} + +// SizeBytes implements marshal.Marshallable.SizeBytes. func (r *FUSEEmptyIn) SizeBytes() int { return 0 } @@ -646,7 +670,6 @@ func (r *FUSEEmptyIn) SizeBytes() int { type FUSEMkdirMeta struct { // Mode of the directory of create. Mode uint32 - // Umask is the user file creation mask. Umask uint32 } @@ -654,24 +677,26 @@ type FUSEMkdirMeta struct { // FUSEMkdirIn contains all the arguments sent by the kernel // to the daemon, to create a new directory. // -// Dynamically-sized objects cannot be marshalled. +// +marshal dynamic type FUSEMkdirIn struct { - marshal.StubMarshallable - // MkdirMeta contains Mode and Umask of the directory to create. MkdirMeta FUSEMkdirMeta - // Name of the directory to create. Name CString } -// MarshalBytes serializes r.MkdirMeta and r.Name to the dst buffer. +// MarshalBytes implements marshal.Marshallable.MarshalBytes. 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. +// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes. +func (r *FUSEMkdirIn) UnmarshalBytes(buf []byte) []byte { + panic("Unimplemented, FUSEMkdirIn is never unmarshalled") +} + +// SizeBytes implements marshal.Marshallable.SizeBytes. func (r *FUSEMkdirIn) SizeBytes() int { return r.MkdirMeta.SizeBytes() + r.Name.SizeBytes() } @@ -679,20 +704,23 @@ func (r *FUSEMkdirIn) SizeBytes() int { // FUSERmDirIn is the request sent by the kernel to the daemon // when trying to remove a directory. // -// Dynamically-sized objects cannot be marshalled. +// +marshal dynamic type FUSERmDirIn struct { - marshal.StubMarshallable - // Name is a directory name to be removed. Name CString } -// MarshalBytes serializes r.name to the dst buffer. +// MarshalBytes implements marshal.Marshallable.MarshalBytes. func (r *FUSERmDirIn) MarshalBytes(buf []byte) []byte { return r.Name.MarshalBytes(buf) } -// SizeBytes is the size of the memory representation of FUSERmDirIn. +// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes. +func (r *FUSERmDirIn) UnmarshalBytes(buf []byte) []byte { + panic("Unimplemented, FUSERmDirIn is never unmarshalled") +} + +// SizeBytes implements marshal.Marshallable.SizeBytes. func (r *FUSERmDirIn) SizeBytes() int { return r.Name.SizeBytes() } @@ -700,23 +728,18 @@ func (r *FUSERmDirIn) SizeBytes() int { // FUSEDirents is a list of Dirents received from the FUSE daemon server. // It is used for FUSE_READDIR. // -// Dynamically-sized objects cannot be marshalled. +// +marshal dynamic type FUSEDirents struct { - marshal.StubMarshallable - Dirents []*FUSEDirent } // FUSEDirent is a Dirent received from the FUSE daemon server. // It is used for FUSE_READDIR. // -// Dynamically-sized objects cannot be marshalled. +// +marshal dynamic type FUSEDirent struct { - marshal.StubMarshallable - // Meta contains all the static fields of FUSEDirent. Meta FUSEDirentMeta - // Name is the filename of the dirent. Name string } @@ -728,18 +751,15 @@ type FUSEDirent struct { type FUSEDirentMeta struct { // Inode of the dirent. Ino uint64 - // Offset of the dirent. Off uint64 - // NameLen is the length of the dirent name. NameLen uint32 - // Type of the dirent. Type uint32 } -// SizeBytes is the size of the memory representation of FUSEDirents. +// SizeBytes implements marshal.Marshallable.SizeBytes. func (r *FUSEDirents) SizeBytes() int { var sizeBytes int for _, dirent := range r.Dirents { @@ -749,6 +769,11 @@ func (r *FUSEDirents) SizeBytes() int { return sizeBytes } +// MarshalBytes implements marshal.Marshallable.MarshalBytes. +func (r *FUSEDirents) MarshalBytes(buf []byte) []byte { + panic("Unimplemented, FUSEDirents is never marshalled") +} + // UnmarshalBytes deserializes FUSEDirents from the src buffer. func (r *FUSEDirents) UnmarshalBytes(src []byte) []byte { for { @@ -772,7 +797,7 @@ func (r *FUSEDirents) UnmarshalBytes(src []byte) []byte { return src } -// SizeBytes is the size of the memory representation of FUSEDirent. +// SizeBytes implements marshal.Marshallable.SizeBytes. func (r *FUSEDirent) SizeBytes() int { dataSize := r.Meta.SizeBytes() + len(r.Name) @@ -782,6 +807,11 @@ func (r *FUSEDirent) SizeBytes() int { return (dataSize + (FUSE_DIRENT_ALIGN - 1)) & ^(FUSE_DIRENT_ALIGN - 1) } +// MarshalBytes implements marshal.Marshallable.MarshalBytes. +func (r *FUSEDirent) MarshalBytes(buf []byte) []byte { + panic("Unimplemented, FUSEDirent is never marshalled") +} + // shiftNextDirent advances buf to the start of the next dirent, per // FUSE ABI. buf should begin at the start of a dirent. func (r *FUSEDirent) shiftNextDirent(buf []byte) []byte { @@ -792,7 +822,7 @@ func (r *FUSEDirent) shiftNextDirent(buf []byte) []byte { return buf[nextOff:] } -// UnmarshalBytes deserializes FUSEDirent from the src buffer. +// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes. func (r *FUSEDirent) UnmarshalBytes(src []byte) []byte { srcP := r.Meta.UnmarshalBytes(src) @@ -879,20 +909,23 @@ type FUSESetAttrIn struct { // FUSEUnlinkIn is the request sent by the kernel to the daemon // when trying to unlink a node. // -// Dynamically-sized objects cannot be marshalled. +// +marshal dynamic type FUSEUnlinkIn struct { - marshal.StubMarshallable - // Name of the node to unlink. Name CString } -// MarshalBytes serializes r.name to the dst buffer. +// MarshalBytes implements marshal.Marshallable.MarshalBytes. func (r *FUSEUnlinkIn) MarshalBytes(buf []byte) []byte { return r.Name.MarshalBytes(buf) } -// SizeBytes is the size of the memory representation of FUSEUnlinkIn. +// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes. +func (r *FUSEUnlinkIn) UnmarshalBytes(buf []byte) []byte { + panic("Unimplemented, FUSEUnlinkIn is never unmarshalled") +} + +// SizeBytes implements marshal.Marshallable.SizeBytes. func (r *FUSEUnlinkIn) SizeBytes() int { return r.Name.SizeBytes() } diff --git a/pkg/marshal/BUILD b/pkg/marshal/BUILD index 7a5002176..9ef453283 100644 --- a/pkg/marshal/BUILD +++ b/pkg/marshal/BUILD @@ -6,7 +6,6 @@ go_library( name = "marshal", srcs = [ "marshal.go", - "marshal_impl_util.go", "util.go", ], visibility = [ diff --git a/pkg/marshal/marshal_impl_util.go b/pkg/marshal/marshal_impl_util.go deleted file mode 100644 index 6c1cf7a4c..000000000 --- a/pkg/marshal/marshal_impl_util.go +++ /dev/null @@ -1,78 +0,0 @@ -// 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 marshal - -import ( - "io" - - "gvisor.dev/gvisor/pkg/hostarch" -) - -// StubMarshallable implements the Marshallable interface. -// StubMarshallable is a convenient embeddable type for satisfying the -// marshallable interface, but provides no actual implementation. It is -// useful when the marshallable interface needs to be implemented manually, -// but the caller doesn't require the full marshallable interface. -type StubMarshallable struct{} - -// WriteTo implements Marshallable.WriteTo. -func (StubMarshallable) WriteTo(w io.Writer) (n int64, err error) { - panic("Please implement your own WriteTo function") -} - -// SizeBytes implements Marshallable.SizeBytes. -func (StubMarshallable) SizeBytes() int { - panic("Please implement your own SizeBytes function") -} - -// MarshalBytes implements Marshallable.MarshalBytes. -func (StubMarshallable) MarshalBytes(dst []byte) []byte { - panic("Please implement your own MarshalBytes function") -} - -// UnmarshalBytes implements Marshallable.UnmarshalBytes. -func (StubMarshallable) UnmarshalBytes(src []byte) []byte { - panic("Please implement your own UnmarshalBytes function") -} - -// Packed implements Marshallable.Packed. -func (StubMarshallable) Packed() bool { - panic("Please implement your own Packed function") -} - -// MarshalUnsafe implements Marshallable.MarshalUnsafe. -func (StubMarshallable) MarshalUnsafe(dst []byte) []byte { - panic("Please implement your own MarshalUnsafe function") -} - -// UnmarshalUnsafe implements Marshallable.UnmarshalUnsafe. -func (StubMarshallable) UnmarshalUnsafe(src []byte) []byte { - panic("Please implement your own UnmarshalUnsafe function") -} - -// CopyIn implements Marshallable.CopyIn. -func (StubMarshallable) CopyIn(cc CopyContext, addr hostarch.Addr) (int, error) { - panic("Please implement your own CopyIn function") -} - -// CopyOut implements Marshallable.CopyOut. -func (StubMarshallable) CopyOut(cc CopyContext, addr hostarch.Addr) (int, error) { - panic("Please implement your own CopyOut function") -} - -// CopyOutN implements Marshallable.CopyOutN. -func (StubMarshallable) CopyOutN(cc CopyContext, addr hostarch.Addr, limit int) (int, error) { - panic("Please implement your own CopyOutN function") -} diff --git a/pkg/sentry/fsimpl/fuse/BUILD b/pkg/sentry/fsimpl/fuse/BUILD index 18497a880..07400d273 100644 --- a/pkg/sentry/fsimpl/fuse/BUILD +++ b/pkg/sentry/fsimpl/fuse/BUILD @@ -42,6 +42,7 @@ go_library( "request_list.go", "request_response.go", ], + marshal = True, visibility = ["//pkg/sentry:internal"], deps = [ "//pkg/abi/linux", diff --git a/pkg/sentry/fsimpl/fuse/fusefs.go b/pkg/sentry/fsimpl/fuse/fusefs.go index 00b520c31..039dc6996 100644 --- a/pkg/sentry/fsimpl/fuse/fusefs.go +++ b/pkg/sentry/fsimpl/fuse/fusefs.go @@ -540,7 +540,7 @@ 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{ + in := linux.FUSESymlinkIn{ Name: linux.CString(name), Target: linux.CString(target), } diff --git a/pkg/sentry/fsimpl/fuse/request_response.go b/pkg/sentry/fsimpl/fuse/request_response.go index ec76ec2a4..fa774f67a 100644 --- a/pkg/sentry/fsimpl/fuse/request_response.go +++ b/pkg/sentry/fsimpl/fuse/request_response.go @@ -29,10 +29,8 @@ import ( // server may implement an older version of FUSE protocol, which contains a // linux.FUSEInitOut with less attributes. // -// Dynamically-sized objects cannot be marshalled. +// +marshal dynamic type fuseInitRes struct { - marshal.StubMarshallable - // initOut contains the response from the FUSE server. initOut linux.FUSEInitOut @@ -40,6 +38,10 @@ type fuseInitRes struct { initLen uint32 } +func (r *fuseInitRes) MarshalBytes(src []byte) []byte { + panic("Unimplemented, fuseInitRes should never be marshalled") +} + // UnmarshalBytes deserializes src to the initOut attribute in a fuseInitRes. func (r *fuseInitRes) UnmarshalBytes(src []byte) []byte { out := &r.initOut @@ -123,9 +125,8 @@ func (conn *connection) NewRequest(creds *auth.Credentials, pid uint32, ino uint buf := make([]byte, hdr.Len) - // TODO(gVisor.dev/issue/3698): Use the unsafe version once go_marshal is safe to use again. - hdr.MarshalBytes(buf[:hdrLen]) - payload.MarshalBytes(buf[hdrLen:]) + hdr.MarshalUnsafe(buf[:hdrLen]) + payload.MarshalUnsafe(buf[hdrLen:]) return &Request{ id: hdr.Unique, @@ -224,7 +225,6 @@ func (r *Response) UnmarshalPayload(m marshal.Marshallable) error { return nil } - // TODO(gVisor.dev/issue/3698): Use the unsafe version once go_marshal is safe to use again. - m.UnmarshalBytes(r.data[hdrLen:]) + m.UnmarshalUnsafe(r.data[hdrLen:]) return nil }