github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/socket/hostinet/socket_vfs2.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 hostinet 16 17 import ( 18 "golang.org/x/sys/unix" 19 "github.com/SagerNet/gvisor/pkg/abi/linux" 20 "github.com/SagerNet/gvisor/pkg/context" 21 "github.com/SagerNet/gvisor/pkg/errors/linuxerr" 22 "github.com/SagerNet/gvisor/pkg/fdnotifier" 23 "github.com/SagerNet/gvisor/pkg/sentry/arch" 24 "github.com/SagerNet/gvisor/pkg/sentry/fsimpl/sockfs" 25 "github.com/SagerNet/gvisor/pkg/sentry/hostfd" 26 "github.com/SagerNet/gvisor/pkg/sentry/kernel" 27 "github.com/SagerNet/gvisor/pkg/sentry/socket" 28 "github.com/SagerNet/gvisor/pkg/sentry/vfs" 29 "github.com/SagerNet/gvisor/pkg/syserr" 30 "github.com/SagerNet/gvisor/pkg/syserror" 31 "github.com/SagerNet/gvisor/pkg/usermem" 32 "github.com/SagerNet/gvisor/pkg/waiter" 33 ) 34 35 // +stateify savable 36 type socketVFS2 struct { 37 vfsfd vfs.FileDescription 38 vfs.FileDescriptionDefaultImpl 39 vfs.LockFD 40 41 // We store metadata for hostinet sockets internally. Technically, we should 42 // access metadata (e.g. through stat, chmod) on the host for correctness, 43 // but this is not very useful for inet socket fds, which do not belong to a 44 // concrete file anyway. 45 vfs.DentryMetadataFileDescriptionImpl 46 47 socketOpsCommon 48 } 49 50 var _ = socket.SocketVFS2(&socketVFS2{}) 51 52 func newVFS2Socket(t *kernel.Task, family int, stype linux.SockType, protocol int, fd int, flags uint32) (*vfs.FileDescription, *syserr.Error) { 53 mnt := t.Kernel().SocketMount() 54 d := sockfs.NewDentry(t, mnt) 55 defer d.DecRef(t) 56 57 s := &socketVFS2{ 58 socketOpsCommon: socketOpsCommon{ 59 family: family, 60 stype: stype, 61 protocol: protocol, 62 fd: fd, 63 }, 64 } 65 s.LockFD.Init(&vfs.FileLocks{}) 66 if err := fdnotifier.AddFD(int32(fd), &s.queue); err != nil { 67 return nil, syserr.FromError(err) 68 } 69 vfsfd := &s.vfsfd 70 if err := vfsfd.Init(s, linux.O_RDWR|(flags&linux.O_NONBLOCK), mnt, d, &vfs.FileDescriptionOptions{ 71 DenyPRead: true, 72 DenyPWrite: true, 73 UseDentryMetadata: true, 74 }); err != nil { 75 fdnotifier.RemoveFD(int32(s.fd)) 76 return nil, syserr.FromError(err) 77 } 78 return vfsfd, nil 79 } 80 81 // Release implements vfs.FileDescriptionImpl.Release. 82 func (s *socketVFS2) Release(ctx context.Context) { 83 kernel.KernelFromContext(ctx).DeleteSocketVFS2(&s.vfsfd) 84 s.socketOpsCommon.Release(ctx) 85 } 86 87 // Readiness implements waiter.Waitable.Readiness. 88 func (s *socketVFS2) Readiness(mask waiter.EventMask) waiter.EventMask { 89 return s.socketOpsCommon.Readiness(mask) 90 } 91 92 // EventRegister implements waiter.Waitable.EventRegister. 93 func (s *socketVFS2) EventRegister(e *waiter.Entry, mask waiter.EventMask) { 94 s.socketOpsCommon.EventRegister(e, mask) 95 } 96 97 // EventUnregister implements waiter.Waitable.EventUnregister. 98 func (s *socketVFS2) EventUnregister(e *waiter.Entry) { 99 s.socketOpsCommon.EventUnregister(e) 100 } 101 102 // Ioctl implements vfs.FileDescriptionImpl. 103 func (s *socketVFS2) Ioctl(ctx context.Context, uio usermem.IO, args arch.SyscallArguments) (uintptr, error) { 104 return ioctl(ctx, s.fd, uio, args) 105 } 106 107 // PRead implements vfs.FileDescriptionImpl.PRead. 108 func (s *socketVFS2) PRead(ctx context.Context, dst usermem.IOSequence, offset int64, opts vfs.ReadOptions) (int64, error) { 109 return 0, linuxerr.ESPIPE 110 } 111 112 // Read implements vfs.FileDescriptionImpl. 113 func (s *socketVFS2) Read(ctx context.Context, dst usermem.IOSequence, opts vfs.ReadOptions) (int64, error) { 114 // All flags other than RWF_NOWAIT should be ignored. 115 // TODO(github.com/SagerNet/issue/2601): Support RWF_NOWAIT. 116 if opts.Flags != 0 { 117 return 0, syserror.EOPNOTSUPP 118 } 119 120 reader := hostfd.GetReadWriterAt(int32(s.fd), -1, opts.Flags) 121 n, err := dst.CopyOutFrom(ctx, reader) 122 hostfd.PutReadWriterAt(reader) 123 return int64(n), err 124 } 125 126 // PWrite implements vfs.FileDescriptionImpl. 127 func (s *socketVFS2) PWrite(ctx context.Context, dst usermem.IOSequence, offset int64, opts vfs.WriteOptions) (int64, error) { 128 return 0, linuxerr.ESPIPE 129 } 130 131 // Write implements vfs.FileDescriptionImpl. 132 func (s *socketVFS2) Write(ctx context.Context, src usermem.IOSequence, opts vfs.WriteOptions) (int64, error) { 133 // All flags other than RWF_NOWAIT should be ignored. 134 // TODO(github.com/SagerNet/issue/2601): Support RWF_NOWAIT. 135 if opts.Flags != 0 { 136 return 0, syserror.EOPNOTSUPP 137 } 138 139 writer := hostfd.GetReadWriterAt(int32(s.fd), -1, opts.Flags) 140 n, err := src.CopyInTo(ctx, writer) 141 hostfd.PutReadWriterAt(writer) 142 return int64(n), err 143 } 144 145 type socketProviderVFS2 struct { 146 family int 147 } 148 149 // Socket implements socket.ProviderVFS2.Socket. 150 func (p *socketProviderVFS2) Socket(t *kernel.Task, stypeflags linux.SockType, protocol int) (*vfs.FileDescription, *syserr.Error) { 151 // Check that we are using the host network stack. 152 stack := t.NetworkContext() 153 if stack == nil { 154 return nil, nil 155 } 156 if _, ok := stack.(*Stack); !ok { 157 return nil, nil 158 } 159 160 // Only accept TCP and UDP. 161 stype := stypeflags & linux.SOCK_TYPE_MASK 162 switch stype { 163 case unix.SOCK_STREAM: 164 switch protocol { 165 case 0, unix.IPPROTO_TCP: 166 // ok 167 default: 168 return nil, nil 169 } 170 case unix.SOCK_DGRAM: 171 switch protocol { 172 case 0, unix.IPPROTO_UDP: 173 // ok 174 default: 175 return nil, nil 176 } 177 default: 178 return nil, nil 179 } 180 181 // Conservatively ignore all flags specified by the application and add 182 // SOCK_NONBLOCK since socketOperations requires it. Pass a protocol of 0 183 // to simplify the syscall filters, since 0 and IPPROTO_* are equivalent. 184 fd, err := unix.Socket(p.family, int(stype)|unix.SOCK_NONBLOCK|unix.SOCK_CLOEXEC, 0) 185 if err != nil { 186 return nil, syserr.FromError(err) 187 } 188 return newVFS2Socket(t, p.family, stype, protocol, fd, uint32(stypeflags&unix.SOCK_NONBLOCK)) 189 } 190 191 // Pair implements socket.Provider.Pair. 192 func (p *socketProviderVFS2) Pair(t *kernel.Task, stype linux.SockType, protocol int) (*vfs.FileDescription, *vfs.FileDescription, *syserr.Error) { 193 // Not supported by AF_INET/AF_INET6. 194 return nil, nil, nil 195 }