diff --git a/pkg/lisafs/fd.go b/pkg/lisafs/fd.go index 0d743ae4a..2b7107e56 100644 --- a/pkg/lisafs/fd.go +++ b/pkg/lisafs/fd.go @@ -344,11 +344,11 @@ type ControlFDImpl interface { Symlink(c *Connection, name string, target string, uid UID, gid GID) (Inode, error) Link(c *Connection, dir ControlFDImpl, name string) (Inode, error) StatFS(c *Connection) (StatFS, error) - Readlink(c *Connection, getLinkBuf func(uint32) []byte) (uint32, error) + Readlink(c *Connection, getLinkBuf func(uint32) []byte) (uint16, error) Connect(c *Connection, sockType uint32) (int, error) Unlink(c *Connection, name string, flags uint32) error RenameLocked(c *Connection, newDir ControlFDImpl, newName string) (func(ControlFDImpl), func(), error) - GetXattr(c *Connection, name string, dataBuf []byte) (uint32, error) + GetXattr(c *Connection, name string, dataBuf []byte) (uint16, error) SetXattr(c *Connection, name string, value string, flags uint32) error ListXattr(c *Connection, size uint64) (StringArray, error) RemoveXattr(c *Connection, name string) error diff --git a/pkg/lisafs/handlers.go b/pkg/lisafs/handlers.go index 502e13564..952c5ba41 100644 --- a/pkg/lisafs/handlers.go +++ b/pkg/lisafs/handlers.go @@ -251,7 +251,7 @@ func WalkHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32, e // the slice allocation. The memory format should be WalkResp's. var ( status WalkStatus - numInodes primitive.Uint32 + numInodes primitive.Uint16 ) maxPayloadSize := status.SizeBytes() + numInodes.SizeBytes() + (len(req.Path) * (*Inode)(nil).SizeBytes()) if maxPayloadSize > math.MaxUint32 { @@ -308,7 +308,7 @@ func WalkStatHandler(c *Connection, comm Communicator, payloadLen uint32) (uint3 // We will manually marshal the statx results into the payload buffer as they // are generated to avoid the slice allocation. The memory format should be // the same as WalkStatResp's. - var numStats primitive.Uint32 + var numStats primitive.Uint16 maxPayloadSize := numStats.SizeBytes() + (len(req.Path) * linux.SizeOfStatx) if maxPayloadSize > math.MaxUint32 { // Too much to walk, can't do. @@ -730,7 +730,7 @@ func ReadLinkAtHandler(c *Connection, comm Communicator, payloadLen uint32) (uin // We will manually marshal ReadLinkAtResp, which just contains a // SizedString. Let Readlinkat directly write into the payload buffer and // manually write the string size before it. - var linkLen primitive.Uint32 + var linkLen primitive.Uint16 respMetaSize := uint32(linkLen.SizeBytes()) n, err := fd.impl.Readlink(c, func(dataLen uint32) []byte { return comm.PayloadBuf(dataLen + respMetaSize)[respMetaSize:] @@ -738,9 +738,9 @@ func ReadLinkAtHandler(c *Connection, comm Communicator, payloadLen uint32) (uin if err != nil { return 0, err } - linkLen = primitive.Uint32(n) + linkLen = primitive.Uint16(n) linkLen.MarshalUnsafe(comm.PayloadBuf(respMetaSize)) - return respMetaSize + n, nil + return respMetaSize + uint32(n), nil } // FlushHandler handles the Flush RPC. @@ -923,7 +923,7 @@ func Getdents64Handler(c *Connection, comm Communicator, payloadLen uint32) (uin // We will manually marshal the response Getdents64Resp. // numDirents is the number of dirents marshalled into the payload. - var numDirents primitive.Uint32 + var numDirents primitive.Uint16 // The payload starts with numDirents, dirents go right after that. // payloadBufPos represents the position at which to write the next dirent. payloadBufPos := uint32(numDirents.SizeBytes()) @@ -964,16 +964,16 @@ func FGetXattrHandler(c *Connection, comm Communicator, payloadLen uint32) (uint // Manually marshal FGetXattrResp to avoid allocations and copying. // FGetXattrResp simply is a wrapper around SizedString. - var valueLen primitive.Uint32 + var valueLen primitive.Uint16 respMetaSize := uint32(valueLen.SizeBytes()) payloadBuf := comm.PayloadBuf(respMetaSize + uint32(req.BufSize)) n, err := fd.impl.GetXattr(c, string(req.Name), payloadBuf[respMetaSize:]) if err != nil { return 0, err } - valueLen = primitive.Uint32(n) + valueLen = primitive.Uint16(n) valueLen.MarshalBytes(payloadBuf) - return respMetaSize + n, nil + return respMetaSize + uint32(n), nil } // FSetXattrHandler handles the FSetXattr RPC. diff --git a/pkg/lisafs/message.go b/pkg/lisafs/message.go index ea5acae05..4fa9453da 100644 --- a/pkg/lisafs/message.go +++ b/pkg/lisafs/message.go @@ -181,17 +181,17 @@ func NoopMarshal(b []byte) []byte { return b } func NoopUnmarshal(b []byte) ([]byte, bool) { return b, true } // SizedString represents a string in memory. The marshalled string bytes are -// preceded by a uint32 signifying the string length. +// preceded by a uint16 signifying the string length. type SizedString string // SizeBytes implements marshal.Marshallable.SizeBytes. func (s *SizedString) SizeBytes() int { - return (*primitive.Uint32)(nil).SizeBytes() + len(*s) + return (*primitive.Uint16)(nil).SizeBytes() + len(*s) } // MarshalBytes implements marshal.Marshallable.MarshalBytes. func (s *SizedString) MarshalBytes(dst []byte) []byte { - strLen := primitive.Uint32(len(*s)) + strLen := primitive.Uint16(len(*s)) dst = strLen.MarshalUnsafe(dst) // Copy without any allocation. return dst[copy(dst[:strLen], *s):] @@ -199,7 +199,7 @@ func (s *SizedString) MarshalBytes(dst []byte) []byte { // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. func (s *SizedString) CheckedUnmarshal(src []byte) ([]byte, bool) { - var strLen primitive.Uint32 + var strLen primitive.Uint16 srcRemain, ok := strLen.CheckedUnmarshal(src) if !ok || len(srcRemain) < int(strLen) { return src, false @@ -210,12 +210,12 @@ func (s *SizedString) CheckedUnmarshal(src []byte) ([]byte, bool) { } // StringArray represents an array of SizedStrings in memory. The marshalled -// array data is preceded by a uint32 signifying the array length. +// array data is preceded by a uint16 signifying the array length. type StringArray []string // SizeBytes implements marshal.Marshallable.SizeBytes. func (s *StringArray) SizeBytes() int { - size := (*primitive.Uint32)(nil).SizeBytes() + size := (*primitive.Uint16)(nil).SizeBytes() for _, str := range *s { sstr := SizedString(str) size += sstr.SizeBytes() @@ -225,7 +225,7 @@ func (s *StringArray) SizeBytes() int { // MarshalBytes implements marshal.Marshallable.MarshalBytes. func (s *StringArray) MarshalBytes(dst []byte) []byte { - arrLen := primitive.Uint32(len(*s)) + arrLen := primitive.Uint16(len(*s)) dst = arrLen.MarshalUnsafe(dst) for _, str := range *s { sstr := SizedString(str) @@ -236,7 +236,7 @@ func (s *StringArray) MarshalBytes(dst []byte) []byte { // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. func (s *StringArray) CheckedUnmarshal(src []byte) ([]byte, bool) { - var arrLen primitive.Uint32 + var arrLen primitive.Uint16 srcRemain, ok := arrLen.CheckedUnmarshal(src) if !ok { return src, false @@ -248,7 +248,7 @@ func (s *StringArray) CheckedUnmarshal(src []byte) ([]byte, bool) { *s = (*s)[:arrLen] } - for i := primitive.Uint32(0); i < arrLen; i++ { + for i := primitive.Uint16(0); i < arrLen; i++ { var sstr SizedString srcRemain, ok = sstr.CheckedUnmarshal(srcRemain) if !ok { @@ -436,7 +436,8 @@ const ( WalkComponentSymlink ) -// WalkResp is used to communicate the inodes walked by the server. +// WalkResp is used to communicate the inodes walked by the server. In memory, +// the inode array is preceded by a uint16 integer denoting array length. type WalkResp struct { Status WalkStatus Inodes []Inode @@ -445,14 +446,14 @@ type WalkResp struct { // SizeBytes implements marshal.Marshallable.SizeBytes. func (w *WalkResp) SizeBytes() int { return w.Status.SizeBytes() + - (*primitive.Uint32)(nil).SizeBytes() + (len(w.Inodes) * (*Inode)(nil).SizeBytes()) + (*primitive.Uint16)(nil).SizeBytes() + (len(w.Inodes) * (*Inode)(nil).SizeBytes()) } // MarshalBytes implements marshal.Marshallable.MarshalBytes. func (w *WalkResp) MarshalBytes(dst []byte) []byte { dst = w.Status.MarshalUnsafe(dst) - numInodes := primitive.Uint32(len(w.Inodes)) + numInodes := primitive.Uint16(len(w.Inodes)) dst = numInodes.MarshalUnsafe(dst) return MarshalUnsafeInodeSlice(w.Inodes, dst) @@ -466,7 +467,7 @@ func (w *WalkResp) CheckedUnmarshal(src []byte) ([]byte, bool) { } srcRemain := w.Status.UnmarshalUnsafe(src) - var numInodes primitive.Uint32 + var numInodes primitive.Uint16 srcRemain = numInodes.UnmarshalUnsafe(srcRemain) if int(numInodes)*(*Inode)(nil).SizeBytes() > len(srcRemain) { return src, false @@ -479,19 +480,20 @@ func (w *WalkResp) CheckedUnmarshal(src []byte) ([]byte, bool) { return UnmarshalUnsafeInodeSlice(w.Inodes, srcRemain), true } -// WalkStatResp is used to communicate stat results for WalkStat. +// WalkStatResp is used to communicate stat results for WalkStat. In memory, +// the array data is preceded by a uint16 denoting the array length. type WalkStatResp struct { Stats []linux.Statx } // SizeBytes implements marshal.Marshallable.SizeBytes. func (w *WalkStatResp) SizeBytes() int { - return (*primitive.Uint32)(nil).SizeBytes() + (len(w.Stats) * linux.SizeOfStatx) + return (*primitive.Uint16)(nil).SizeBytes() + (len(w.Stats) * linux.SizeOfStatx) } // MarshalBytes implements marshal.Marshallable.MarshalBytes. func (w *WalkStatResp) MarshalBytes(dst []byte) []byte { - numStats := primitive.Uint32(len(w.Stats)) + numStats := primitive.Uint16(len(w.Stats)) dst = numStats.MarshalUnsafe(dst) return linux.MarshalUnsafeStatxSlice(w.Stats, dst) @@ -503,7 +505,7 @@ func (w *WalkStatResp) CheckedUnmarshal(src []byte) ([]byte, bool) { if w.SizeBytes() > len(src) { return src, false } - var numStats primitive.Uint32 + var numStats primitive.Uint16 srcRemain := numStats.UnmarshalUnsafe(src) if int(numStats)*linux.SizeOfStatx > len(srcRemain) { @@ -585,17 +587,17 @@ type OpenCreateAtResp struct { // FdArray is a utility struct which implements a marshallable type for // communicating an array of FDIDs. In memory, the array data is preceded by a -// uint32 denoting the array length. +// uint16 denoting the array length. type FdArray []FDID // SizeBytes implements marshal.Marshallable.SizeBytes. func (f *FdArray) SizeBytes() int { - return (*primitive.Uint32)(nil).SizeBytes() + (len(*f) * (*FDID)(nil).SizeBytes()) + return (*primitive.Uint16)(nil).SizeBytes() + (len(*f) * (*FDID)(nil).SizeBytes()) } // MarshalBytes implements marshal.Marshallable.MarshalBytes. func (f *FdArray) MarshalBytes(dst []byte) []byte { - arrLen := primitive.Uint32(len(*f)) + arrLen := primitive.Uint16(len(*f)) dst = arrLen.MarshalUnsafe(dst) return MarshalUnsafeFDIDSlice(*f, dst) } @@ -606,7 +608,7 @@ func (f *FdArray) CheckedUnmarshal(src []byte) ([]byte, bool) { if f.SizeBytes() > len(src) { return src, false } - var arrLen primitive.Uint32 + var arrLen primitive.Uint16 srcRemain := arrLen.UnmarshalUnsafe(src) if int(arrLen)*(*FDID)(nil).SizeBytes() > len(srcRemain) { return src, false @@ -688,7 +690,7 @@ func (r *PReadResp) MarshalBytes(dst []byte) []byte { // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. func (r *PReadResp) CheckedUnmarshal(src []byte) ([]byte, bool) { srcRemain, ok := r.NumBytes.CheckedUnmarshal(src) - if !ok || int(r.NumBytes) > len(srcRemain) || int(r.NumBytes) > len(r.Buf) { + if !ok || uint32(r.NumBytes) > uint32(len(srcRemain)) || uint32(r.NumBytes) > uint32(len(r.Buf)) { return src, false } @@ -730,7 +732,7 @@ func (w *PWriteReq) CheckedUnmarshal(src []byte) ([]byte, bool) { // This is an optimization. Assuming that the server is making this call, it // is safe to just point to src rather than allocating and copying. - if int(w.NumBytes) > len(srcRemain) { + if uint32(w.NumBytes) > uint32(len(srcRemain)) { return src, false } w.Buf = srcRemain[:w.NumBytes] @@ -1112,14 +1114,15 @@ func (d *Dirent64) CheckedUnmarshal(src []byte) ([]byte, bool) { return src, false } -// Getdents64Resp is used to communicate getdents64 results. +// Getdents64Resp is used to communicate getdents64 results. In memory, the +// dirents array is preceded by a uint16 integer denoting array length. type Getdents64Resp struct { Dirents []Dirent64 } // SizeBytes implements marshal.Marshallable.SizeBytes. func (g *Getdents64Resp) SizeBytes() int { - ret := (*primitive.Uint32)(nil).SizeBytes() + ret := (*primitive.Uint16)(nil).SizeBytes() for i := range g.Dirents { ret += g.Dirents[i].SizeBytes() } @@ -1128,7 +1131,7 @@ func (g *Getdents64Resp) SizeBytes() int { // MarshalBytes implements marshal.Marshallable.MarshalBytes. func (g *Getdents64Resp) MarshalBytes(dst []byte) []byte { - numDirents := primitive.Uint32(len(g.Dirents)) + numDirents := primitive.Uint16(len(g.Dirents)) dst = numDirents.MarshalUnsafe(dst) for i := range g.Dirents { dst = g.Dirents[i].MarshalBytes(dst) @@ -1142,7 +1145,7 @@ func (g *Getdents64Resp) CheckedUnmarshal(src []byte) ([]byte, bool) { if g.SizeBytes() > len(src) { return src, false } - var numDirents primitive.Uint32 + var numDirents primitive.Uint16 srcRemain := numDirents.UnmarshalUnsafe(src) if cap(g.Dirents) < int(numDirents) { g.Dirents = make([]Dirent64, numDirents) diff --git a/runsc/fsgofer/lisafs.go b/runsc/fsgofer/lisafs.go index 6b73fa4c4..612fbab57 100644 --- a/runsc/fsgofer/lisafs.go +++ b/runsc/fsgofer/lisafs.go @@ -16,6 +16,7 @@ package fsgofer import ( "io" + "math" "path" "strconv" "sync/atomic" @@ -622,17 +623,16 @@ func (fd *controlFDLisa) StatFS(c *lisafs.Connection) (lisafs.StatFS, error) { } // Readlink implements lisafs.ControlFDImpl.Readlink. -func (fd *controlFDLisa) Readlink(c *lisafs.Connection, getLinkBuf func(uint32) []byte) (uint32, error) { +func (fd *controlFDLisa) Readlink(c *lisafs.Connection, getLinkBuf func(uint32) []byte) (uint16, error) { // This is similar to what os.Readlink does. - const limit = uint32(1024 * 1024) - for linkLen := uint32(128); linkLen < limit; linkLen *= 2 { - b := getLinkBuf(linkLen) + for linkLen := 128; linkLen < math.MaxUint16; linkLen *= 2 { + b := getLinkBuf(uint32(linkLen)) n, err := unix.Readlinkat(fd.hostFD, "", b) if err != nil { return 0, err } if n < int(linkLen) { - return uint32(n), nil + return uint16(n), nil } } return 0, unix.ENOMEM @@ -693,7 +693,7 @@ func (fd *controlFDLisa) RenameLocked(c *lisafs.Connection, newDir lisafs.Contro } // GetXattr implements lisafs.ControlFDImpl.GetXattr. -func (fd *controlFDLisa) GetXattr(c *lisafs.Connection, name string, dataBuf []byte) (uint32, error) { +func (fd *controlFDLisa) GetXattr(c *lisafs.Connection, name string, dataBuf []byte) (uint16, error) { if !c.ServerImpl().(*LisafsServer).config.EnableVerityXattr { return 0, unix.EOPNOTSUPP } @@ -701,7 +701,7 @@ func (fd *controlFDLisa) GetXattr(c *lisafs.Connection, name string, dataBuf []b return 0, unix.EOPNOTSUPP } n, err := unix.Fgetxattr(fd.hostFD, name, dataBuf) - return uint32(n), err + return uint16(n), err } // SetXattr implements lisafs.ControlFDImpl.SetXattr.