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 }