github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/unet/unet_unsafe.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 unet 16 17 import ( 18 "io" 19 "unsafe" 20 21 "golang.org/x/sys/unix" 22 ) 23 24 // wait blocks until the socket FD is ready for reading or writing, depending 25 // on the value of write. 26 // 27 // Returns errClosing if the Socket is in the process of closing. 28 func (s *Socket) wait(write bool) error { 29 for { 30 // Checking the FD on each loop is not strictly necessary, it 31 // just avoids an extra poll call. 32 fd := s.fd.Load() 33 if fd < 0 { 34 return errClosing 35 } 36 37 events := []unix.PollFd{ 38 { 39 // The actual socket FD. 40 Fd: fd, 41 Events: unix.POLLIN, 42 }, 43 { 44 // The eventfd, signaled when we are closing. 45 Fd: int32(s.efd.FD()), 46 Events: unix.POLLIN, 47 }, 48 } 49 if write { 50 events[0].Events = unix.POLLOUT 51 } 52 53 _, _, e := unix.Syscall6(unix.SYS_PPOLL, uintptr(unsafe.Pointer(&events[0])), 2, 0, 0, 0, 0) 54 if e == unix.EINTR { 55 continue 56 } 57 if e != 0 { 58 return e 59 } 60 61 if events[1].Revents&unix.POLLIN == unix.POLLIN { 62 // eventfd signaled, we're closing. 63 return errClosing 64 } 65 66 return nil 67 } 68 } 69 70 // buildIovec builds an iovec slice from the given []byte slice. 71 // 72 // iovecs is used as an initial slice, to avoid excessive allocations. 73 func buildIovec(bufs [][]byte, iovecs []unix.Iovec) ([]unix.Iovec, int) { 74 var length int 75 for i := range bufs { 76 if l := len(bufs[i]); l > 0 { 77 iovecs = append(iovecs, unix.Iovec{ 78 Base: &bufs[i][0], 79 Len: uint64(l), 80 }) 81 length += l 82 } 83 } 84 return iovecs, length 85 } 86 87 // ReadVec reads into the pre-allocated bufs. Returns bytes read. 88 // 89 // The pre-allocatted space used by ReadVec is based upon slice lengths. 90 // 91 // This function is not guaranteed to read all available data, it 92 // returns as soon as a single recvmsg call succeeds. 93 func (r *SocketReader) ReadVec(bufs [][]byte) (int, error) { 94 iovecs, length := buildIovec(bufs, make([]unix.Iovec, 0, 2)) 95 96 var msg unix.Msghdr 97 if len(r.source) != 0 { 98 msg.Name = &r.source[0] 99 msg.Namelen = uint32(len(r.source)) 100 } 101 102 if len(r.ControlMessage) != 0 { 103 msg.Control = &r.ControlMessage[0] 104 msg.Controllen = uint64(len(r.ControlMessage)) 105 } 106 107 if len(iovecs) != 0 { 108 msg.Iov = &iovecs[0] 109 msg.Iovlen = uint64(len(iovecs)) 110 } 111 112 // n is the bytes received. 113 var n uintptr 114 115 fd, ok := r.socket.enterFD() 116 if !ok { 117 return 0, unix.EBADF 118 } 119 // Leave on returns below. 120 for { 121 var e unix.Errno 122 123 // Try a non-blocking recv first, so we don't give up the go runtime M. 124 n, _, e = unix.RawSyscall(unix.SYS_RECVMSG, uintptr(fd), uintptr(unsafe.Pointer(&msg)), unix.MSG_DONTWAIT|unix.MSG_TRUNC) 125 if e == 0 { 126 break 127 } 128 if e == unix.EINTR { 129 continue 130 } 131 if !r.blocking { 132 r.socket.gate.Leave() 133 return 0, e 134 } 135 if e != unix.EAGAIN && e != unix.EWOULDBLOCK { 136 r.socket.gate.Leave() 137 return 0, e 138 } 139 140 // Wait for the socket to become readable. 141 err := r.socket.wait(false) 142 if err == errClosing { 143 err = unix.EBADF 144 } 145 if err != nil { 146 r.socket.gate.Leave() 147 return 0, err 148 } 149 } 150 151 r.socket.gate.Leave() 152 153 if msg.Controllen < uint64(len(r.ControlMessage)) { 154 r.ControlMessage = r.ControlMessage[:msg.Controllen] 155 } 156 157 if msg.Namelen < uint32(len(r.source)) { 158 r.source = r.source[:msg.Namelen] 159 } 160 161 // All unet sockets are SOCK_STREAM or SOCK_SEQPACKET, both of which 162 // indicate that the other end is closed by returning a 0 length read 163 // with no error. 164 if n == 0 { 165 return 0, io.EOF 166 } 167 168 if r.race != nil { 169 // See comments on Socket.race. 170 r.race.Add(1) 171 } 172 173 if int(n) > length { 174 return length, errMessageTruncated 175 } 176 177 return int(n), nil 178 } 179 180 // WriteVec writes the bufs to the socket. Returns bytes written. 181 // 182 // This function is not guaranteed to send all data, it returns 183 // as soon as a single sendmsg call succeeds. 184 func (w *SocketWriter) WriteVec(bufs [][]byte) (int, error) { 185 iovecs, _ := buildIovec(bufs, make([]unix.Iovec, 0, 2)) 186 187 if w.race != nil { 188 // See comments on Socket.race. 189 w.race.Add(1) 190 } 191 192 var msg unix.Msghdr 193 if len(w.to) != 0 { 194 msg.Name = &w.to[0] 195 msg.Namelen = uint32(len(w.to)) 196 } 197 198 if len(w.ControlMessage) != 0 { 199 msg.Control = &w.ControlMessage[0] 200 msg.Controllen = uint64(len(w.ControlMessage)) 201 } 202 203 if len(iovecs) > 0 { 204 msg.Iov = &iovecs[0] 205 msg.Iovlen = uint64(len(iovecs)) 206 } 207 208 fd, ok := w.socket.enterFD() 209 if !ok { 210 return 0, unix.EBADF 211 } 212 // Leave on returns below. 213 for { 214 // Try a non-blocking send first, so we don't give up the go runtime M. 215 n, _, e := unix.RawSyscall(unix.SYS_SENDMSG, uintptr(fd), uintptr(unsafe.Pointer(&msg)), unix.MSG_DONTWAIT|unix.MSG_NOSIGNAL) 216 if e == 0 { 217 w.socket.gate.Leave() 218 return int(n), nil 219 } 220 if e == unix.EINTR { 221 continue 222 } 223 if !w.blocking { 224 w.socket.gate.Leave() 225 return 0, e 226 } 227 if e != unix.EAGAIN && e != unix.EWOULDBLOCK { 228 w.socket.gate.Leave() 229 return 0, e 230 } 231 232 // Wait for the socket to become writeable. 233 err := w.socket.wait(true) 234 if err == errClosing { 235 err = unix.EBADF 236 } 237 if err != nil { 238 w.socket.gate.Leave() 239 return 0, err 240 } 241 } 242 // Unreachable, no s.gate.Leave needed. 243 } 244 245 // getsockopt issues a getsockopt unix. 246 func getsockopt(fd int, level int, optname int, buf []byte) (uint32, error) { 247 l := uint32(len(buf)) 248 _, _, e := unix.RawSyscall6(unix.SYS_GETSOCKOPT, uintptr(fd), uintptr(level), uintptr(optname), uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&l)), 0) 249 if e != 0 { 250 return 0, e 251 } 252 253 return l, nil 254 } 255 256 // setsockopt issues a setsockopt unix. 257 func setsockopt(fd int, level int, optname int, buf []byte) error { 258 _, _, e := unix.RawSyscall6(unix.SYS_SETSOCKOPT, uintptr(fd), uintptr(level), uintptr(optname), uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)), 0) 259 if e != 0 { 260 return e 261 } 262 263 return nil 264 } 265 266 // getsockname issues a getsockname unix. 267 func getsockname(fd int, buf []byte) (uint32, error) { 268 l := uint32(len(buf)) 269 _, _, e := unix.RawSyscall(unix.SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&l))) 270 if e != 0 { 271 return 0, e 272 } 273 274 return l, nil 275 } 276 277 // getpeername issues a getpeername unix. 278 func getpeername(fd int, buf []byte) (uint32, error) { 279 l := uint32(len(buf)) 280 _, _, e := unix.RawSyscall(unix.SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&l))) 281 if e != 0 { 282 return 0, e 283 } 284 285 return l, nil 286 }