github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/socket/netstack/provider_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 netstack
    16  
    17  import (
    18  	"github.com/SagerNet/gvisor/pkg/abi/linux"
    19  	"github.com/SagerNet/gvisor/pkg/sentry/kernel"
    20  	"github.com/SagerNet/gvisor/pkg/sentry/kernel/auth"
    21  	"github.com/SagerNet/gvisor/pkg/sentry/socket"
    22  	"github.com/SagerNet/gvisor/pkg/sentry/vfs"
    23  	"github.com/SagerNet/gvisor/pkg/syserr"
    24  	"github.com/SagerNet/gvisor/pkg/tcpip"
    25  	"github.com/SagerNet/gvisor/pkg/tcpip/network/ipv4"
    26  	"github.com/SagerNet/gvisor/pkg/tcpip/network/ipv6"
    27  	"github.com/SagerNet/gvisor/pkg/waiter"
    28  )
    29  
    30  // providerVFS2 is an inet socket provider.
    31  type providerVFS2 struct {
    32  	family   int
    33  	netProto tcpip.NetworkProtocolNumber
    34  }
    35  
    36  // Socket creates a new socket object for the AF_INET, AF_INET6, or AF_PACKET
    37  // family.
    38  func (p *providerVFS2) Socket(t *kernel.Task, stype linux.SockType, protocol int) (*vfs.FileDescription, *syserr.Error) {
    39  	// Fail right away if we don't have a stack.
    40  	stack := t.NetworkContext()
    41  	if stack == nil {
    42  		// Don't propagate an error here. Instead, allow the socket
    43  		// code to continue searching for another provider.
    44  		return nil, nil
    45  	}
    46  	eps, ok := stack.(*Stack)
    47  	if !ok {
    48  		return nil, nil
    49  	}
    50  
    51  	// Packet sockets are handled separately, since they are neither INET
    52  	// nor INET6 specific.
    53  	if p.family == linux.AF_PACKET {
    54  		return packetSocketVFS2(t, eps, stype, protocol)
    55  	}
    56  
    57  	// Figure out the transport protocol.
    58  	transProto, associated, err := getTransportProtocol(t, stype, protocol)
    59  	if err != nil {
    60  		return nil, err
    61  	}
    62  
    63  	// Create the endpoint.
    64  	var ep tcpip.Endpoint
    65  	var e tcpip.Error
    66  	wq := &waiter.Queue{}
    67  	if stype == linux.SOCK_RAW {
    68  		ep, e = eps.Stack.NewRawEndpoint(transProto, p.netProto, wq, associated)
    69  	} else {
    70  		ep, e = eps.Stack.NewEndpoint(transProto, p.netProto, wq)
    71  
    72  		// Assign task to PacketOwner interface to get the UID and GID for
    73  		// iptables owner matching.
    74  		if e == nil {
    75  			ep.SetOwner(t)
    76  		}
    77  	}
    78  	if e != nil {
    79  		return nil, syserr.TranslateNetstackError(e)
    80  	}
    81  
    82  	return NewVFS2(t, p.family, stype, int(transProto), wq, ep)
    83  }
    84  
    85  func packetSocketVFS2(t *kernel.Task, epStack *Stack, stype linux.SockType, protocol int) (*vfs.FileDescription, *syserr.Error) {
    86  	// Packet sockets require CAP_NET_RAW.
    87  	creds := auth.CredentialsFromContext(t)
    88  	if !creds.HasCapability(linux.CAP_NET_RAW) {
    89  		return nil, syserr.ErrNotPermitted
    90  	}
    91  
    92  	// "cooked" packets don't contain link layer information.
    93  	var cooked bool
    94  	switch stype {
    95  	case linux.SOCK_DGRAM:
    96  		cooked = true
    97  	case linux.SOCK_RAW:
    98  		cooked = false
    99  	default:
   100  		return nil, syserr.ErrProtocolNotSupported
   101  	}
   102  
   103  	// protocol is passed in network byte order, but netstack wants it in
   104  	// host order.
   105  	netProto := tcpip.NetworkProtocolNumber(socket.Ntohs(uint16(protocol)))
   106  
   107  	wq := &waiter.Queue{}
   108  	ep, err := epStack.Stack.NewPacketEndpoint(cooked, netProto, wq)
   109  	if err != nil {
   110  		return nil, syserr.TranslateNetstackError(err)
   111  	}
   112  
   113  	return NewVFS2(t, linux.AF_PACKET, stype, protocol, wq, ep)
   114  }
   115  
   116  // Pair just returns nil sockets (not supported).
   117  func (*providerVFS2) Pair(*kernel.Task, linux.SockType, int) (*vfs.FileDescription, *vfs.FileDescription, *syserr.Error) {
   118  	return nil, nil, nil
   119  }
   120  
   121  // init registers socket providers for AF_INET, AF_INET6, and AF_PACKET.
   122  func init() {
   123  	// Providers backed by netstack.
   124  	p := []providerVFS2{
   125  		{
   126  			family:   linux.AF_INET,
   127  			netProto: ipv4.ProtocolNumber,
   128  		},
   129  		{
   130  			family:   linux.AF_INET6,
   131  			netProto: ipv6.ProtocolNumber,
   132  		},
   133  		{
   134  			family: linux.AF_PACKET,
   135  		},
   136  	}
   137  
   138  	for i := range p {
   139  		socket.RegisterProviderVFS2(p[i].family, &p[i])
   140  	}
   141  }