github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/fsimpl/fuse/request_response.go (about) 1 // Copyright 2020 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package fuse 16 17 import ( 18 "fmt" 19 20 "golang.org/x/sys/unix" 21 "github.com/SagerNet/gvisor/pkg/abi/linux" 22 "github.com/SagerNet/gvisor/pkg/hostarch" 23 "github.com/SagerNet/gvisor/pkg/marshal" 24 "github.com/SagerNet/gvisor/pkg/sentry/kernel" 25 "github.com/SagerNet/gvisor/pkg/sentry/kernel/auth" 26 ) 27 28 // fuseInitRes is a variable-length wrapper of linux.FUSEInitOut. The FUSE 29 // server may implement an older version of FUSE protocol, which contains a 30 // linux.FUSEInitOut with less attributes. 31 // 32 // Dynamically-sized objects cannot be marshalled. 33 type fuseInitRes struct { 34 marshal.StubMarshallable 35 36 // initOut contains the response from the FUSE server. 37 initOut linux.FUSEInitOut 38 39 // initLen is the total length of bytes of the response. 40 initLen uint32 41 } 42 43 // UnmarshalBytes deserializes src to the initOut attribute in a fuseInitRes. 44 func (r *fuseInitRes) UnmarshalBytes(src []byte) { 45 out := &r.initOut 46 47 // Introduced before FUSE kernel version 7.13. 48 out.Major = uint32(hostarch.ByteOrder.Uint32(src[:4])) 49 src = src[4:] 50 out.Minor = uint32(hostarch.ByteOrder.Uint32(src[:4])) 51 src = src[4:] 52 out.MaxReadahead = uint32(hostarch.ByteOrder.Uint32(src[:4])) 53 src = src[4:] 54 out.Flags = uint32(hostarch.ByteOrder.Uint32(src[:4])) 55 src = src[4:] 56 out.MaxBackground = uint16(hostarch.ByteOrder.Uint16(src[:2])) 57 src = src[2:] 58 out.CongestionThreshold = uint16(hostarch.ByteOrder.Uint16(src[:2])) 59 src = src[2:] 60 out.MaxWrite = uint32(hostarch.ByteOrder.Uint32(src[:4])) 61 src = src[4:] 62 63 // Introduced in FUSE kernel version 7.23. 64 if len(src) >= 4 { 65 out.TimeGran = uint32(hostarch.ByteOrder.Uint32(src[:4])) 66 src = src[4:] 67 } 68 // Introduced in FUSE kernel version 7.28. 69 if len(src) >= 2 { 70 out.MaxPages = uint16(hostarch.ByteOrder.Uint16(src[:2])) 71 src = src[2:] 72 } 73 _ = src // Remove unused warning. 74 } 75 76 // SizeBytes is the size of the payload of the FUSE_INIT response. 77 func (r *fuseInitRes) SizeBytes() int { 78 return int(r.initLen) 79 } 80 81 // Ordinary requests have even IDs, while interrupts IDs are odd. 82 // Used to increment the unique ID for each FUSE request. 83 var reqIDStep uint64 = 2 84 85 // Request represents a FUSE operation request that hasn't been sent to the 86 // server yet. 87 // 88 // +stateify savable 89 type Request struct { 90 requestEntry 91 92 id linux.FUSEOpID 93 hdr *linux.FUSEHeaderIn 94 data []byte 95 96 // payload for this request: extra bytes to write after 97 // the data slice. Used by FUSE_WRITE. 98 payload []byte 99 100 // If this request is async. 101 async bool 102 // If we don't care its response. 103 // Manually set by the caller. 104 noReply bool 105 } 106 107 // NewRequest creates a new request that can be sent to the FUSE server. 108 func (conn *connection) NewRequest(creds *auth.Credentials, pid uint32, ino uint64, opcode linux.FUSEOpcode, payload marshal.Marshallable) *Request { 109 conn.fd.mu.Lock() 110 defer conn.fd.mu.Unlock() 111 conn.fd.nextOpID += linux.FUSEOpID(reqIDStep) 112 113 hdrLen := (*linux.FUSEHeaderIn)(nil).SizeBytes() 114 hdr := linux.FUSEHeaderIn{ 115 Len: uint32(hdrLen + payload.SizeBytes()), 116 Opcode: opcode, 117 Unique: conn.fd.nextOpID, 118 NodeID: ino, 119 UID: uint32(creds.EffectiveKUID), 120 GID: uint32(creds.EffectiveKGID), 121 PID: pid, 122 } 123 124 buf := make([]byte, hdr.Len) 125 126 // TODO(github.com/SagerNet/issue/3698): Use the unsafe version once go_marshal is safe to use again. 127 hdr.MarshalBytes(buf[:hdrLen]) 128 payload.MarshalBytes(buf[hdrLen:]) 129 130 return &Request{ 131 id: hdr.Unique, 132 hdr: &hdr, 133 data: buf, 134 } 135 } 136 137 // futureResponse represents an in-flight request, that may or may not have 138 // completed yet. Convert it to a resolved Response by calling Resolve, but note 139 // that this may block. 140 // 141 // +stateify savable 142 type futureResponse struct { 143 opcode linux.FUSEOpcode 144 ch chan struct{} 145 hdr *linux.FUSEHeaderOut 146 data []byte 147 148 // If this request is async. 149 async bool 150 } 151 152 // newFutureResponse creates a future response to a FUSE request. 153 func newFutureResponse(req *Request) *futureResponse { 154 return &futureResponse{ 155 opcode: req.hdr.Opcode, 156 ch: make(chan struct{}), 157 async: req.async, 158 } 159 } 160 161 // resolve blocks the task until the server responds to its corresponding request, 162 // then returns a resolved response. 163 func (f *futureResponse) resolve(t *kernel.Task) (*Response, error) { 164 // Return directly for async requests. 165 if f.async { 166 return nil, nil 167 } 168 169 if err := t.Block(f.ch); err != nil { 170 return nil, err 171 } 172 173 return f.getResponse(), nil 174 } 175 176 // getResponse creates a Response from the data the futureResponse has. 177 func (f *futureResponse) getResponse() *Response { 178 return &Response{ 179 opcode: f.opcode, 180 hdr: *f.hdr, 181 data: f.data, 182 } 183 } 184 185 // Response represents an actual response from the server, including the 186 // response payload. 187 // 188 // +stateify savable 189 type Response struct { 190 opcode linux.FUSEOpcode 191 hdr linux.FUSEHeaderOut 192 data []byte 193 } 194 195 // Error returns the error of the FUSE call. 196 func (r *Response) Error() error { 197 errno := r.hdr.Error 198 if errno >= 0 { 199 return nil 200 } 201 202 sysErrNo := unix.Errno(-errno) 203 return error(sysErrNo) 204 } 205 206 // DataLen returns the size of the response without the header. 207 func (r *Response) DataLen() uint32 { 208 return r.hdr.Len - uint32(r.hdr.SizeBytes()) 209 } 210 211 // UnmarshalPayload unmarshals the response data into m. 212 func (r *Response) UnmarshalPayload(m marshal.Marshallable) error { 213 hdrLen := r.hdr.SizeBytes() 214 haveDataLen := r.hdr.Len - uint32(hdrLen) 215 wantDataLen := uint32(m.SizeBytes()) 216 217 if haveDataLen < wantDataLen { 218 return fmt.Errorf("payload too small. Minimum data lenth required: %d, but got data length %d", wantDataLen, haveDataLen) 219 } 220 221 // The response data is empty unless there is some payload. And so, doesn't 222 // need to be unmarshalled. 223 if r.data == nil { 224 return nil 225 } 226 227 // TODO(github.com/SagerNet/issue/3698): Use the unsafe version once go_marshal is safe to use again. 228 m.UnmarshalBytes(r.data[hdrLen:]) 229 return nil 230 }