github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/socket/unix/io.go (about) 1 // Copyright 2018 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 unix 16 17 import ( 18 "github.com/SagerNet/gvisor/pkg/context" 19 "github.com/SagerNet/gvisor/pkg/safemem" 20 "github.com/SagerNet/gvisor/pkg/sentry/socket/unix/transport" 21 "github.com/SagerNet/gvisor/pkg/tcpip" 22 ) 23 24 // EndpointWriter implements safemem.Writer that writes to a transport.Endpoint. 25 // 26 // EndpointWriter is not thread-safe. 27 type EndpointWriter struct { 28 Ctx context.Context 29 30 // Endpoint is the transport.Endpoint to write to. 31 Endpoint transport.Endpoint 32 33 // Control is the control messages to send. 34 Control transport.ControlMessages 35 36 // To is the endpoint to send to. May be nil. 37 To transport.BoundEndpoint 38 } 39 40 // WriteFromBlocks implements safemem.Writer.WriteFromBlocks. 41 func (w *EndpointWriter) WriteFromBlocks(srcs safemem.BlockSeq) (uint64, error) { 42 return safemem.FromVecWriterFunc{func(bufs [][]byte) (int64, error) { 43 n, err := w.Endpoint.SendMsg(w.Ctx, bufs, w.Control, w.To) 44 if err != nil { 45 return int64(n), err.ToError() 46 } 47 return int64(n), nil 48 }}.WriteFromBlocks(srcs) 49 } 50 51 // EndpointReader implements safemem.Reader that reads from a 52 // transport.Endpoint. 53 // 54 // EndpointReader is not thread-safe. 55 type EndpointReader struct { 56 Ctx context.Context 57 58 // Endpoint is the transport.Endpoint to read from. 59 Endpoint transport.Endpoint 60 61 // Creds indicates if credential control messages are requested. 62 Creds bool 63 64 // NumRights is the number of SCM_RIGHTS FDs requested. 65 NumRights int 66 67 // Peek indicates that the data should not be consumed from the 68 // endpoint. 69 Peek bool 70 71 // MsgSize is the size of the message that was read from. For stream 72 // sockets, it is the amount read. 73 MsgSize int64 74 75 // From, if not nil, will be set with the address read from. 76 From *tcpip.FullAddress 77 78 // Control contains the received control messages. 79 Control transport.ControlMessages 80 81 // ControlTrunc indicates that SCM_RIGHTS FDs were discarded based on 82 // the value of NumRights. 83 ControlTrunc bool 84 } 85 86 // Truncate calls RecvMsg on the endpoint without writing to a destination. 87 func (r *EndpointReader) Truncate() error { 88 // Ignore bytes read since it will always be zero. 89 _, ms, c, ct, err := r.Endpoint.RecvMsg(r.Ctx, [][]byte{}, r.Creds, r.NumRights, r.Peek, r.From) 90 r.Control = c 91 r.ControlTrunc = ct 92 r.MsgSize = ms 93 if err != nil { 94 return err.ToError() 95 } 96 return nil 97 } 98 99 // ReadToBlocks implements safemem.Reader.ReadToBlocks. 100 func (r *EndpointReader) ReadToBlocks(dsts safemem.BlockSeq) (uint64, error) { 101 return safemem.FromVecReaderFunc{func(bufs [][]byte) (int64, error) { 102 n, ms, c, ct, err := r.Endpoint.RecvMsg(r.Ctx, bufs, r.Creds, r.NumRights, r.Peek, r.From) 103 r.Control = c 104 r.ControlTrunc = ct 105 r.MsgSize = ms 106 if err != nil { 107 return int64(n), err.ToError() 108 } 109 return int64(n), nil 110 }}.ReadToBlocks(dsts) 111 }