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  }