github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/socket/netlink/socket_vfs2.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 netlink 16 17 import ( 18 "github.com/SagerNet/gvisor/pkg/abi/linux" 19 "github.com/SagerNet/gvisor/pkg/context" 20 "github.com/SagerNet/gvisor/pkg/errors/linuxerr" 21 "github.com/SagerNet/gvisor/pkg/sentry/arch" 22 "github.com/SagerNet/gvisor/pkg/sentry/kernel" 23 "github.com/SagerNet/gvisor/pkg/sentry/socket" 24 "github.com/SagerNet/gvisor/pkg/sentry/socket/unix" 25 "github.com/SagerNet/gvisor/pkg/sentry/socket/unix/transport" 26 "github.com/SagerNet/gvisor/pkg/sentry/vfs" 27 "github.com/SagerNet/gvisor/pkg/syserr" 28 "github.com/SagerNet/gvisor/pkg/syserror" 29 "github.com/SagerNet/gvisor/pkg/tcpip" 30 "github.com/SagerNet/gvisor/pkg/usermem" 31 "github.com/SagerNet/gvisor/pkg/waiter" 32 ) 33 34 // SocketVFS2 is the base VFS2 socket type for netlink sockets. 35 // 36 // This implementation only supports userspace sending and receiving messages 37 // to/from the kernel. 38 // 39 // SocketVFS2 implements socket.SocketVFS2 and transport.Credentialer. 40 // 41 // +stateify savable 42 type SocketVFS2 struct { 43 vfsfd vfs.FileDescription 44 vfs.FileDescriptionDefaultImpl 45 vfs.DentryMetadataFileDescriptionImpl 46 vfs.LockFD 47 48 socketOpsCommon 49 } 50 51 var _ socket.SocketVFS2 = (*SocketVFS2)(nil) 52 var _ transport.Credentialer = (*SocketVFS2)(nil) 53 54 // NewVFS2 creates a new SocketVFS2. 55 func NewVFS2(t *kernel.Task, skType linux.SockType, protocol Protocol) (*SocketVFS2, *syserr.Error) { 56 // Datagram endpoint used to buffer kernel -> user messages. 57 ep := transport.NewConnectionless(t) 58 59 // Bind the endpoint for good measure so we can connect to it. The 60 // bound address will never be exposed. 61 if err := ep.Bind(tcpip.FullAddress{Addr: "dummy"}, nil); err != nil { 62 ep.Close(t) 63 return nil, err 64 } 65 66 // Create a connection from which the kernel can write messages. 67 connection, err := ep.(transport.BoundEndpoint).UnidirectionalConnect(t) 68 if err != nil { 69 ep.Close(t) 70 return nil, err 71 } 72 73 fd := &SocketVFS2{ 74 socketOpsCommon: socketOpsCommon{ 75 ports: t.Kernel().NetlinkPorts(), 76 protocol: protocol, 77 skType: skType, 78 ep: ep, 79 connection: connection, 80 sendBufferSize: defaultSendBufferSize, 81 }, 82 } 83 fd.LockFD.Init(&vfs.FileLocks{}) 84 return fd, nil 85 } 86 87 // Release implements vfs.FileDescriptionImpl.Release. 88 func (s *SocketVFS2) Release(ctx context.Context) { 89 t := kernel.TaskFromContext(ctx) 90 t.Kernel().DeleteSocketVFS2(&s.vfsfd) 91 s.socketOpsCommon.Release(ctx) 92 } 93 94 // Readiness implements waiter.Waitable.Readiness. 95 func (s *SocketVFS2) Readiness(mask waiter.EventMask) waiter.EventMask { 96 return s.socketOpsCommon.Readiness(mask) 97 } 98 99 // EventRegister implements waiter.Waitable.EventRegister. 100 func (s *SocketVFS2) EventRegister(e *waiter.Entry, mask waiter.EventMask) { 101 s.socketOpsCommon.EventRegister(e, mask) 102 } 103 104 // EventUnregister implements waiter.Waitable.EventUnregister. 105 func (s *SocketVFS2) EventUnregister(e *waiter.Entry) { 106 s.socketOpsCommon.EventUnregister(e) 107 } 108 109 // Ioctl implements vfs.FileDescriptionImpl. 110 func (*SocketVFS2) Ioctl(context.Context, usermem.IO, arch.SyscallArguments) (uintptr, error) { 111 // TODO(b/68878065): no ioctls supported. 112 return 0, syserror.ENOTTY 113 } 114 115 // PRead implements vfs.FileDescriptionImpl. 116 func (s *SocketVFS2) PRead(ctx context.Context, dst usermem.IOSequence, offset int64, opts vfs.ReadOptions) (int64, error) { 117 return 0, linuxerr.ESPIPE 118 } 119 120 // Read implements vfs.FileDescriptionImpl. 121 func (s *SocketVFS2) Read(ctx context.Context, dst usermem.IOSequence, opts vfs.ReadOptions) (int64, error) { 122 // All flags other than RWF_NOWAIT should be ignored. 123 // TODO(github.com/SagerNet/issue/2601): Support RWF_NOWAIT. 124 if opts.Flags != 0 { 125 return 0, syserror.EOPNOTSUPP 126 } 127 128 if dst.NumBytes() == 0 { 129 return 0, nil 130 } 131 return dst.CopyOutFrom(ctx, &unix.EndpointReader{ 132 Endpoint: s.ep, 133 }) 134 } 135 136 // PWrite implements vfs.FileDescriptionImpl. 137 func (s *SocketVFS2) PWrite(ctx context.Context, src usermem.IOSequence, offset int64, opts vfs.WriteOptions) (int64, error) { 138 return 0, linuxerr.ESPIPE 139 } 140 141 // Write implements vfs.FileDescriptionImpl. 142 func (s *SocketVFS2) Write(ctx context.Context, src usermem.IOSequence, opts vfs.WriteOptions) (int64, error) { 143 // All flags other than RWF_NOWAIT should be ignored. 144 // TODO(github.com/SagerNet/issue/2601): Support RWF_NOWAIT. 145 if opts.Flags != 0 { 146 return 0, syserror.EOPNOTSUPP 147 } 148 149 n, err := s.sendMsg(ctx, src, nil, 0, socket.ControlMessages{}) 150 return int64(n), err.ToError() 151 }