github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/socket/netstack/provider.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 netstack
    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/sentry/fs"
    22  	"github.com/SagerNet/gvisor/pkg/sentry/kernel"
    23  	"github.com/SagerNet/gvisor/pkg/sentry/kernel/auth"
    24  	"github.com/SagerNet/gvisor/pkg/sentry/socket"
    25  	"github.com/SagerNet/gvisor/pkg/syserr"
    26  	"github.com/SagerNet/gvisor/pkg/tcpip"
    27  	"github.com/SagerNet/gvisor/pkg/tcpip/header"
    28  	"github.com/SagerNet/gvisor/pkg/tcpip/network/ipv4"
    29  	"github.com/SagerNet/gvisor/pkg/tcpip/network/ipv6"
    30  	"github.com/SagerNet/gvisor/pkg/tcpip/transport/tcp"
    31  	"github.com/SagerNet/gvisor/pkg/tcpip/transport/udp"
    32  	"github.com/SagerNet/gvisor/pkg/waiter"
    33  )
    34  
    35  // LINT.IfChange
    36  
    37  // provider is an inet socket provider.
    38  type provider struct {
    39  	family   int
    40  	netProto tcpip.NetworkProtocolNumber
    41  }
    42  
    43  // getTransportProtocol figures out transport protocol. Currently only TCP,
    44  // UDP, and ICMP are supported. The bool return value is true when this socket
    45  // is associated with a transport protocol. This is only false for SOCK_RAW,
    46  // IPPROTO_IP sockets.
    47  func getTransportProtocol(ctx context.Context, stype linux.SockType, protocol int) (tcpip.TransportProtocolNumber, bool, *syserr.Error) {
    48  	switch stype {
    49  	case linux.SOCK_STREAM:
    50  		if protocol != 0 && protocol != unix.IPPROTO_TCP {
    51  			return 0, true, syserr.ErrInvalidArgument
    52  		}
    53  		return tcp.ProtocolNumber, true, nil
    54  
    55  	case linux.SOCK_DGRAM:
    56  		switch protocol {
    57  		case 0, unix.IPPROTO_UDP:
    58  			return udp.ProtocolNumber, true, nil
    59  		case unix.IPPROTO_ICMP:
    60  			return header.ICMPv4ProtocolNumber, true, nil
    61  		case unix.IPPROTO_ICMPV6:
    62  			return header.ICMPv6ProtocolNumber, true, nil
    63  		}
    64  
    65  	case linux.SOCK_RAW:
    66  		// Raw sockets require CAP_NET_RAW.
    67  		creds := auth.CredentialsFromContext(ctx)
    68  		if !creds.HasCapability(linux.CAP_NET_RAW) {
    69  			return 0, true, syserr.ErrNotPermitted
    70  		}
    71  
    72  		switch protocol {
    73  		case unix.IPPROTO_ICMP:
    74  			return header.ICMPv4ProtocolNumber, true, nil
    75  		case unix.IPPROTO_ICMPV6:
    76  			return header.ICMPv6ProtocolNumber, true, nil
    77  		case unix.IPPROTO_UDP:
    78  			return header.UDPProtocolNumber, true, nil
    79  		case unix.IPPROTO_TCP:
    80  			return header.TCPProtocolNumber, true, nil
    81  		// IPPROTO_RAW signifies that the raw socket isn't assigned to
    82  		// a transport protocol. Users will be able to write packets'
    83  		// IP headers and won't receive anything.
    84  		case unix.IPPROTO_RAW:
    85  			return tcpip.TransportProtocolNumber(0), false, nil
    86  		}
    87  	}
    88  	return 0, true, syserr.ErrProtocolNotSupported
    89  }
    90  
    91  // Socket creates a new socket object for the AF_INET, AF_INET6, or AF_PACKET
    92  // family.
    93  func (p *provider) Socket(t *kernel.Task, stype linux.SockType, protocol int) (*fs.File, *syserr.Error) {
    94  	// Fail right away if we don't have a stack.
    95  	stack := t.NetworkContext()
    96  	if stack == nil {
    97  		// Don't propagate an error here. Instead, allow the socket
    98  		// code to continue searching for another provider.
    99  		return nil, nil
   100  	}
   101  	eps, ok := stack.(*Stack)
   102  	if !ok {
   103  		return nil, nil
   104  	}
   105  
   106  	// Packet sockets are handled separately, since they are neither INET
   107  	// nor INET6 specific.
   108  	if p.family == linux.AF_PACKET {
   109  		return packetSocket(t, eps, stype, protocol)
   110  	}
   111  
   112  	// Figure out the transport protocol.
   113  	transProto, associated, err := getTransportProtocol(t, stype, protocol)
   114  	if err != nil {
   115  		return nil, err
   116  	}
   117  
   118  	// Create the endpoint.
   119  	var ep tcpip.Endpoint
   120  	var e tcpip.Error
   121  	wq := &waiter.Queue{}
   122  	if stype == linux.SOCK_RAW {
   123  		ep, e = eps.Stack.NewRawEndpoint(transProto, p.netProto, wq, associated)
   124  	} else {
   125  		ep, e = eps.Stack.NewEndpoint(transProto, p.netProto, wq)
   126  
   127  		// Assign task to PacketOwner interface to get the UID and GID for
   128  		// iptables owner matching.
   129  		if e == nil {
   130  			ep.SetOwner(t)
   131  		}
   132  	}
   133  	if e != nil {
   134  		return nil, syserr.TranslateNetstackError(e)
   135  	}
   136  
   137  	return New(t, p.family, stype, int(transProto), wq, ep)
   138  }
   139  
   140  func packetSocket(t *kernel.Task, epStack *Stack, stype linux.SockType, protocol int) (*fs.File, *syserr.Error) {
   141  	// Packet sockets require CAP_NET_RAW.
   142  	creds := auth.CredentialsFromContext(t)
   143  	if !creds.HasCapability(linux.CAP_NET_RAW) {
   144  		return nil, syserr.ErrNotPermitted
   145  	}
   146  
   147  	// "cooked" packets don't contain link layer information.
   148  	var cooked bool
   149  	switch stype {
   150  	case linux.SOCK_DGRAM:
   151  		cooked = true
   152  	case linux.SOCK_RAW:
   153  		cooked = false
   154  	default:
   155  		return nil, syserr.ErrProtocolNotSupported
   156  	}
   157  
   158  	// protocol is passed in network byte order, but netstack wants it in
   159  	// host order.
   160  	netProto := tcpip.NetworkProtocolNumber(socket.Ntohs(uint16(protocol)))
   161  
   162  	wq := &waiter.Queue{}
   163  	ep, err := epStack.Stack.NewPacketEndpoint(cooked, netProto, wq)
   164  	if err != nil {
   165  		return nil, syserr.TranslateNetstackError(err)
   166  	}
   167  
   168  	return New(t, linux.AF_PACKET, stype, protocol, wq, ep)
   169  }
   170  
   171  // LINT.ThenChange(./provider_vfs2.go)
   172  
   173  // Pair just returns nil sockets (not supported).
   174  func (*provider) Pair(*kernel.Task, linux.SockType, int) (*fs.File, *fs.File, *syserr.Error) {
   175  	return nil, nil, nil
   176  }
   177  
   178  // init registers socket providers for AF_INET, AF_INET6, and AF_PACKET.
   179  func init() {
   180  	// Providers backed by netstack.
   181  	p := []provider{
   182  		{
   183  			family:   linux.AF_INET,
   184  			netProto: ipv4.ProtocolNumber,
   185  		},
   186  		{
   187  			family:   linux.AF_INET6,
   188  			netProto: ipv6.ProtocolNumber,
   189  		},
   190  		{
   191  			family: linux.AF_PACKET,
   192  		},
   193  	}
   194  
   195  	for i := range p {
   196  		socket.RegisterProvider(p[i].family, &p[i])
   197  	}
   198  }