gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/sentry/socket/netstack/stack.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 "fmt" 19 20 "gvisor.dev/gvisor/pkg/abi/linux" 21 "gvisor.dev/gvisor/pkg/context" 22 "gvisor.dev/gvisor/pkg/errors/linuxerr" 23 "gvisor.dev/gvisor/pkg/log" 24 "gvisor.dev/gvisor/pkg/refs" 25 "gvisor.dev/gvisor/pkg/sentry/inet" 26 "gvisor.dev/gvisor/pkg/sentry/socket/netlink/nlmsg" 27 "gvisor.dev/gvisor/pkg/syserr" 28 "gvisor.dev/gvisor/pkg/tcpip" 29 "gvisor.dev/gvisor/pkg/tcpip/header" 30 "gvisor.dev/gvisor/pkg/tcpip/network/ipv4" 31 "gvisor.dev/gvisor/pkg/tcpip/network/ipv6" 32 "gvisor.dev/gvisor/pkg/tcpip/stack" 33 "gvisor.dev/gvisor/pkg/tcpip/transport/tcp" 34 ) 35 36 // Stack implements inet.Stack for netstack/tcpip/stack.Stack. 37 // 38 // +stateify savable 39 type Stack struct { 40 Stack *stack.Stack `state:"manual"` 41 } 42 43 // Destroy implements inet.Stack.Destroy. 44 func (s *Stack) Destroy() { 45 s.Stack.Close() 46 refs.CleanupSync.Add(1) 47 go func() { 48 s.Stack.Wait() 49 refs.CleanupSync.Done() 50 }() 51 } 52 53 // SupportsIPv6 implements Stack.SupportsIPv6. 54 func (s *Stack) SupportsIPv6() bool { 55 return s.Stack.CheckNetworkProtocol(ipv6.ProtocolNumber) 56 } 57 58 // Converts Netstack's ARPHardwareType to equivalent linux constants. 59 func toLinuxARPHardwareType(t header.ARPHardwareType) uint16 { 60 switch t { 61 case header.ARPHardwareNone: 62 return linux.ARPHRD_NONE 63 case header.ARPHardwareLoopback: 64 return linux.ARPHRD_LOOPBACK 65 case header.ARPHardwareEther: 66 return linux.ARPHRD_ETHER 67 default: 68 panic(fmt.Sprintf("unknown ARPHRD type: %d", t)) 69 } 70 } 71 72 // Interfaces implements inet.Stack.Interfaces. 73 func (s *Stack) Interfaces() map[int32]inet.Interface { 74 is := make(map[int32]inet.Interface) 75 for id, ni := range s.Stack.NICInfo() { 76 is[int32(id)] = inet.Interface{ 77 Name: ni.Name, 78 Addr: []byte(ni.LinkAddress), 79 Flags: uint32(nicStateFlagsToLinux(ni.Flags)), 80 DeviceType: toLinuxARPHardwareType(ni.ARPHardwareType), 81 MTU: ni.MTU, 82 } 83 } 84 return is 85 } 86 87 // RemoveInterface implements inet.Stack.RemoveInterface. 88 func (s *Stack) RemoveInterface(idx int32) error { 89 nic := tcpip.NICID(idx) 90 91 nicInfo, ok := s.Stack.NICInfo()[nic] 92 if !ok { 93 return syserr.ErrUnknownNICID.ToError() 94 } 95 96 // Don't allow removing the loopback interface. 97 if nicInfo.Flags.Loopback { 98 return syserr.ErrNotSupported.ToError() 99 } 100 101 return syserr.TranslateNetstackError(s.Stack.RemoveNIC(nic)).ToError() 102 } 103 104 // SetInterface implements inet.Stack.SetInterface. 105 func (s *Stack) SetInterface(ctx context.Context, msg *nlmsg.Message) *syserr.Error { 106 var ifinfomsg linux.InterfaceInfoMessage 107 attrs, ok := msg.GetData(&ifinfomsg) 108 if !ok { 109 return syserr.ErrInvalidArgument 110 } 111 for !attrs.Empty() { 112 // The index is unspecified, search by the interface name. 113 ahdr, value, rest, ok := attrs.ParseFirst() 114 if !ok { 115 return syserr.ErrInvalidArgument 116 } 117 attrs = rest 118 switch ahdr.Type { 119 case linux.IFLA_IFNAME: 120 if len(value) < 1 { 121 return syserr.ErrInvalidArgument 122 } 123 if ifinfomsg.Index != 0 { 124 // Device name changing isn't supported yet. 125 return syserr.ErrNotSupported 126 } 127 ifname := string(value[:len(value)-1]) 128 for idx, ifa := range s.Interfaces() { 129 if ifname == ifa.Name { 130 ifinfomsg.Index = idx 131 break 132 } 133 } 134 default: 135 ctx.Warningf("unexpected attribute: %x", ahdr.Type) 136 return syserr.ErrNotSupported 137 } 138 } 139 if ifinfomsg.Index == 0 { 140 return syserr.ErrNoDevice 141 } 142 143 flags := msg.Header().Flags 144 if flags&(linux.NLM_F_EXCL|linux.NLM_F_REPLACE) != 0 { 145 return syserr.ErrExists 146 } 147 148 if ifinfomsg.Flags != 0 || ifinfomsg.Change != 0 { 149 if ifinfomsg.Change & ^uint32(linux.IFF_UP) != 0 { 150 ctx.Warningf("Unsupported ifi_change flags: %x", ifinfomsg.Change) 151 return syserr.ErrInvalidArgument 152 } 153 if ifinfomsg.Flags & ^uint32(linux.IFF_UP) != 0 { 154 ctx.Warningf("Unsupported ifi_flags: %x", ifinfomsg.Change) 155 return syserr.ErrInvalidArgument 156 } 157 // Netstack interfaces are always up. 158 } 159 return nil 160 } 161 162 // InterfaceAddrs implements inet.Stack.InterfaceAddrs. 163 func (s *Stack) InterfaceAddrs() map[int32][]inet.InterfaceAddr { 164 nicAddrs := make(map[int32][]inet.InterfaceAddr) 165 for id, ni := range s.Stack.NICInfo() { 166 var addrs []inet.InterfaceAddr 167 for _, a := range ni.ProtocolAddresses { 168 var family uint8 169 switch a.Protocol { 170 case ipv4.ProtocolNumber: 171 family = linux.AF_INET 172 case ipv6.ProtocolNumber: 173 family = linux.AF_INET6 174 default: 175 log.Warningf("Unknown network protocol in %+v", a) 176 continue 177 } 178 179 addrCopy := a.AddressWithPrefix.Address 180 addrs = append(addrs, inet.InterfaceAddr{ 181 Family: family, 182 PrefixLen: uint8(a.AddressWithPrefix.PrefixLen), 183 Addr: addrCopy.AsSlice(), 184 // TODO(b/68878065): Other fields. 185 }) 186 } 187 nicAddrs[int32(id)] = addrs 188 } 189 return nicAddrs 190 } 191 192 // convertAddr converts an InterfaceAddr to a ProtocolAddress. 193 func convertAddr(addr inet.InterfaceAddr) (tcpip.ProtocolAddress, error) { 194 var ( 195 protocol tcpip.NetworkProtocolNumber 196 address tcpip.Address 197 protocolAddress tcpip.ProtocolAddress 198 ) 199 switch addr.Family { 200 case linux.AF_INET: 201 if len(addr.Addr) != header.IPv4AddressSize { 202 return protocolAddress, linuxerr.EINVAL 203 } 204 if addr.PrefixLen > header.IPv4AddressSize*8 { 205 return protocolAddress, linuxerr.EINVAL 206 } 207 protocol = ipv4.ProtocolNumber 208 address = tcpip.AddrFrom4Slice(addr.Addr) 209 case linux.AF_INET6: 210 if len(addr.Addr) != header.IPv6AddressSize { 211 return protocolAddress, linuxerr.EINVAL 212 } 213 if addr.PrefixLen > header.IPv6AddressSize*8 { 214 return protocolAddress, linuxerr.EINVAL 215 } 216 protocol = ipv6.ProtocolNumber 217 address = tcpip.AddrFrom16Slice(addr.Addr) 218 default: 219 return protocolAddress, linuxerr.ENOTSUP 220 } 221 222 protocolAddress = tcpip.ProtocolAddress{ 223 Protocol: protocol, 224 AddressWithPrefix: tcpip.AddressWithPrefix{ 225 Address: address, 226 PrefixLen: int(addr.PrefixLen), 227 }, 228 } 229 return protocolAddress, nil 230 } 231 232 // AddInterfaceAddr implements inet.Stack.AddInterfaceAddr. 233 func (s *Stack) AddInterfaceAddr(idx int32, addr inet.InterfaceAddr) error { 234 protocolAddress, err := convertAddr(addr) 235 if err != nil { 236 return err 237 } 238 239 // Attach address to interface. 240 nicID := tcpip.NICID(idx) 241 if err := s.Stack.AddProtocolAddress(nicID, protocolAddress, stack.AddressProperties{}); err != nil { 242 return syserr.TranslateNetstackError(err).ToError() 243 } 244 245 // Add route for local network if it doesn't exist already. 246 localRoute := tcpip.Route{ 247 Destination: protocolAddress.AddressWithPrefix.Subnet(), 248 Gateway: tcpip.Address{}, // No gateway for local network. 249 NIC: nicID, 250 } 251 252 for _, rt := range s.Stack.GetRouteTable() { 253 if rt.Equal(localRoute) { 254 return nil 255 } 256 } 257 258 // Local route does not exist yet. Add it. 259 s.Stack.AddRoute(localRoute) 260 261 return nil 262 } 263 264 // RemoveInterfaceAddr implements inet.Stack.RemoveInterfaceAddr. 265 func (s *Stack) RemoveInterfaceAddr(idx int32, addr inet.InterfaceAddr) error { 266 protocolAddress, err := convertAddr(addr) 267 if err != nil { 268 return err 269 } 270 271 // Remove addresses matching the address and prefix. 272 nicID := tcpip.NICID(idx) 273 if err := s.Stack.RemoveAddress(nicID, protocolAddress.AddressWithPrefix.Address); err != nil { 274 return syserr.TranslateNetstackError(err).ToError() 275 } 276 277 // Remove the corresponding local network route if it exists. 278 localRoute := tcpip.Route{ 279 Destination: protocolAddress.AddressWithPrefix.Subnet(), 280 Gateway: tcpip.Address{}, // No gateway for local network. 281 NIC: nicID, 282 } 283 s.Stack.RemoveRoutes(func(rt tcpip.Route) bool { 284 return rt.Equal(localRoute) 285 }) 286 287 return nil 288 } 289 290 // TCPReceiveBufferSize implements inet.Stack.TCPReceiveBufferSize. 291 func (s *Stack) TCPReceiveBufferSize() (inet.TCPBufferSize, error) { 292 var rs tcpip.TCPReceiveBufferSizeRangeOption 293 err := s.Stack.TransportProtocolOption(tcp.ProtocolNumber, &rs) 294 return inet.TCPBufferSize{ 295 Min: rs.Min, 296 Default: rs.Default, 297 Max: rs.Max, 298 }, syserr.TranslateNetstackError(err).ToError() 299 } 300 301 // SetTCPReceiveBufferSize implements inet.Stack.SetTCPReceiveBufferSize. 302 func (s *Stack) SetTCPReceiveBufferSize(size inet.TCPBufferSize) error { 303 rs := tcpip.TCPReceiveBufferSizeRangeOption{ 304 Min: size.Min, 305 Default: size.Default, 306 Max: size.Max, 307 } 308 return syserr.TranslateNetstackError(s.Stack.SetTransportProtocolOption(tcp.ProtocolNumber, &rs)).ToError() 309 } 310 311 // TCPSendBufferSize implements inet.Stack.TCPSendBufferSize. 312 func (s *Stack) TCPSendBufferSize() (inet.TCPBufferSize, error) { 313 var ss tcpip.TCPSendBufferSizeRangeOption 314 err := s.Stack.TransportProtocolOption(tcp.ProtocolNumber, &ss) 315 return inet.TCPBufferSize{ 316 Min: ss.Min, 317 Default: ss.Default, 318 Max: ss.Max, 319 }, syserr.TranslateNetstackError(err).ToError() 320 } 321 322 // SetTCPSendBufferSize implements inet.Stack.SetTCPSendBufferSize. 323 func (s *Stack) SetTCPSendBufferSize(size inet.TCPBufferSize) error { 324 ss := tcpip.TCPSendBufferSizeRangeOption{ 325 Min: size.Min, 326 Default: size.Default, 327 Max: size.Max, 328 } 329 return syserr.TranslateNetstackError(s.Stack.SetTransportProtocolOption(tcp.ProtocolNumber, &ss)).ToError() 330 } 331 332 // TCPSACKEnabled implements inet.Stack.TCPSACKEnabled. 333 func (s *Stack) TCPSACKEnabled() (bool, error) { 334 var sack tcpip.TCPSACKEnabled 335 err := s.Stack.TransportProtocolOption(tcp.ProtocolNumber, &sack) 336 return bool(sack), syserr.TranslateNetstackError(err).ToError() 337 } 338 339 // SetTCPSACKEnabled implements inet.Stack.SetTCPSACKEnabled. 340 func (s *Stack) SetTCPSACKEnabled(enabled bool) error { 341 opt := tcpip.TCPSACKEnabled(enabled) 342 return syserr.TranslateNetstackError(s.Stack.SetTransportProtocolOption(tcp.ProtocolNumber, &opt)).ToError() 343 } 344 345 // TCPRecovery implements inet.Stack.TCPRecovery. 346 func (s *Stack) TCPRecovery() (inet.TCPLossRecovery, error) { 347 var recovery tcpip.TCPRecovery 348 if err := s.Stack.TransportProtocolOption(tcp.ProtocolNumber, &recovery); err != nil { 349 return 0, syserr.TranslateNetstackError(err).ToError() 350 } 351 return inet.TCPLossRecovery(recovery), nil 352 } 353 354 // SetTCPRecovery implements inet.Stack.SetTCPRecovery. 355 func (s *Stack) SetTCPRecovery(recovery inet.TCPLossRecovery) error { 356 opt := tcpip.TCPRecovery(recovery) 357 return syserr.TranslateNetstackError(s.Stack.SetTransportProtocolOption(tcp.ProtocolNumber, &opt)).ToError() 358 } 359 360 // Statistics implements inet.Stack.Statistics. 361 func (s *Stack) Statistics(stat any, arg string) error { 362 switch stats := stat.(type) { 363 case *inet.StatDev: 364 for _, ni := range s.Stack.NICInfo() { 365 if ni.Name != arg { 366 continue 367 } 368 // TODO(gvisor.dev/issue/2103) Support stubbed stats. 369 *stats = inet.StatDev{ 370 // Receive section. 371 ni.Stats.Rx.Bytes.Value(), // bytes. 372 ni.Stats.Rx.Packets.Value(), // packets. 373 0, // errs. 374 0, // drop. 375 0, // fifo. 376 0, // frame. 377 0, // compressed. 378 0, // multicast. 379 // Transmit section. 380 ni.Stats.Tx.Bytes.Value(), // bytes. 381 ni.Stats.Tx.Packets.Value(), // packets. 382 0, // errs. 383 0, // drop. 384 0, // fifo. 385 0, // colls. 386 0, // carrier. 387 0, // compressed. 388 } 389 break 390 } 391 case *inet.StatSNMPIP: 392 ip := Metrics.IP 393 // TODO(gvisor.dev/issue/969) Support stubbed stats. 394 *stats = inet.StatSNMPIP{ 395 0, // Ip/Forwarding. 396 0, // Ip/DefaultTTL. 397 ip.PacketsReceived.Value(), // InReceives. 398 0, // Ip/InHdrErrors. 399 ip.InvalidDestinationAddressesReceived.Value(), // InAddrErrors. 400 0, // Ip/ForwDatagrams. 401 0, // Ip/InUnknownProtos. 402 0, // Ip/InDiscards. 403 ip.PacketsDelivered.Value(), // InDelivers. 404 ip.PacketsSent.Value(), // OutRequests. 405 ip.OutgoingPacketErrors.Value(), // OutDiscards. 406 0, // Ip/OutNoRoutes. 407 0, // Support Ip/ReasmTimeout. 408 0, // Support Ip/ReasmReqds. 409 0, // Support Ip/ReasmOKs. 410 0, // Support Ip/ReasmFails. 411 0, // Support Ip/FragOKs. 412 0, // Support Ip/FragFails. 413 0, // Support Ip/FragCreates. 414 } 415 case *inet.StatSNMPICMP: 416 in := Metrics.ICMP.V4.PacketsReceived.ICMPv4PacketStats 417 out := Metrics.ICMP.V4.PacketsSent.ICMPv4PacketStats 418 // TODO(gvisor.dev/issue/969) Support stubbed stats. 419 *stats = inet.StatSNMPICMP{ 420 0, // Icmp/InMsgs. 421 Metrics.ICMP.V4.PacketsSent.Dropped.Value(), // InErrors. 422 0, // Icmp/InCsumErrors. 423 in.DstUnreachable.Value(), // InDestUnreachs. 424 in.TimeExceeded.Value(), // InTimeExcds. 425 in.ParamProblem.Value(), // InParmProbs. 426 in.SrcQuench.Value(), // InSrcQuenchs. 427 in.Redirect.Value(), // InRedirects. 428 in.EchoRequest.Value(), // InEchos. 429 in.EchoReply.Value(), // InEchoReps. 430 in.Timestamp.Value(), // InTimestamps. 431 in.TimestampReply.Value(), // InTimestampReps. 432 in.InfoRequest.Value(), // InAddrMasks. 433 in.InfoReply.Value(), // InAddrMaskReps. 434 0, // Icmp/OutMsgs. 435 Metrics.ICMP.V4.PacketsReceived.Invalid.Value(), // OutErrors. 436 out.DstUnreachable.Value(), // OutDestUnreachs. 437 out.TimeExceeded.Value(), // OutTimeExcds. 438 out.ParamProblem.Value(), // OutParmProbs. 439 out.SrcQuench.Value(), // OutSrcQuenchs. 440 out.Redirect.Value(), // OutRedirects. 441 out.EchoRequest.Value(), // OutEchos. 442 out.EchoReply.Value(), // OutEchoReps. 443 out.Timestamp.Value(), // OutTimestamps. 444 out.TimestampReply.Value(), // OutTimestampReps. 445 out.InfoRequest.Value(), // OutAddrMasks. 446 out.InfoReply.Value(), // OutAddrMaskReps. 447 } 448 case *inet.StatSNMPTCP: 449 tcp := Metrics.TCP 450 // RFC 2012 (updates 1213): SNMPv2-MIB-TCP. 451 *stats = inet.StatSNMPTCP{ 452 1, // RtoAlgorithm. 453 200, // RtoMin. 454 120000, // RtoMax. 455 (1<<64 - 1), // MaxConn. 456 tcp.ActiveConnectionOpenings.Value(), // ActiveOpens. 457 tcp.PassiveConnectionOpenings.Value(), // PassiveOpens. 458 tcp.FailedConnectionAttempts.Value(), // AttemptFails. 459 tcp.EstablishedResets.Value(), // EstabResets. 460 tcp.CurrentEstablished.Value(), // CurrEstab. 461 tcp.ValidSegmentsReceived.Value(), // InSegs. 462 tcp.SegmentsSent.Value(), // OutSegs. 463 tcp.Retransmits.Value(), // RetransSegs. 464 tcp.InvalidSegmentsReceived.Value(), // InErrs. 465 tcp.ResetsSent.Value(), // OutRsts. 466 tcp.ChecksumErrors.Value(), // InCsumErrors. 467 } 468 case *inet.StatSNMPUDP: 469 udp := Metrics.UDP 470 // TODO(gvisor.dev/issue/969) Support stubbed stats. 471 *stats = inet.StatSNMPUDP{ 472 udp.PacketsReceived.Value(), // InDatagrams. 473 udp.UnknownPortErrors.Value(), // NoPorts. 474 0, // Udp/InErrors. 475 udp.PacketsSent.Value(), // OutDatagrams. 476 udp.ReceiveBufferErrors.Value(), // RcvbufErrors. 477 0, // Udp/SndbufErrors. 478 udp.ChecksumErrors.Value(), // Udp/InCsumErrors. 479 0, // Udp/IgnoredMulti. 480 } 481 default: 482 return syserr.ErrEndpointOperation.ToError() 483 } 484 return nil 485 } 486 487 // RouteTable implements inet.Stack.RouteTable. 488 func (s *Stack) RouteTable() []inet.Route { 489 var routeTable []inet.Route 490 491 for _, rt := range s.Stack.GetRouteTable() { 492 var family uint8 493 switch rt.Destination.ID().BitLen() { 494 case header.IPv4AddressSizeBits: 495 family = linux.AF_INET 496 case header.IPv6AddressSizeBits: 497 family = linux.AF_INET6 498 default: 499 log.Warningf("Unknown network protocol in route %+v", rt) 500 continue 501 } 502 503 dstAddr := rt.Destination.ID() 504 routeTable = append(routeTable, inet.Route{ 505 Family: family, 506 DstLen: uint8(rt.Destination.Prefix()), // The CIDR prefix for the destination. 507 508 // Always return unspecified protocol since we have no notion of 509 // protocol for routes. 510 Protocol: linux.RTPROT_UNSPEC, 511 // Set statically to LINK scope for now. 512 // 513 // TODO(gvisor.dev/issue/595): Set scope for routes. 514 Scope: linux.RT_SCOPE_LINK, 515 Type: linux.RTN_UNICAST, 516 517 DstAddr: dstAddr.AsSlice(), 518 OutputInterface: int32(rt.NIC), 519 GatewayAddr: rt.Gateway.AsSlice(), 520 }) 521 } 522 523 return routeTable 524 } 525 526 // IPTables returns the stack's iptables. 527 func (s *Stack) IPTables() (*stack.IPTables, error) { 528 return s.Stack.IPTables(), nil 529 } 530 531 // Pause implements inet.Stack.Pause. 532 func (s *Stack) Pause() { 533 s.Stack.Pause() 534 } 535 536 // Restore implements inet.Stack.Restore. 537 func (s *Stack) Restore() { 538 s.Stack.Restore() 539 } 540 541 // Resume implements inet.Stack.Resume. 542 func (s *Stack) Resume() { 543 s.Stack.Resume() 544 } 545 546 // RegisteredEndpoints implements inet.Stack.RegisteredEndpoints. 547 func (s *Stack) RegisteredEndpoints() []stack.TransportEndpoint { 548 return s.Stack.RegisteredEndpoints() 549 } 550 551 // CleanupEndpoints implements inet.Stack.CleanupEndpoints. 552 func (s *Stack) CleanupEndpoints() []stack.TransportEndpoint { 553 return s.Stack.CleanupEndpoints() 554 } 555 556 // RestoreCleanupEndpoints implements inet.Stack.RestoreCleanupEndpoints. 557 func (s *Stack) RestoreCleanupEndpoints(es []stack.TransportEndpoint) { 558 s.Stack.RestoreCleanupEndpoints(es) 559 } 560 561 // SetForwarding implements inet.Stack.SetForwarding. 562 func (s *Stack) SetForwarding(protocol tcpip.NetworkProtocolNumber, enable bool) error { 563 if err := s.Stack.SetForwardingDefaultAndAllNICs(protocol, enable); err != nil { 564 return fmt.Errorf("SetForwardingDefaultAndAllNICs(%d, %t): %s", protocol, enable, err) 565 } 566 return nil 567 } 568 569 // PortRange implements inet.Stack.PortRange. 570 func (s *Stack) PortRange() (uint16, uint16) { 571 return s.Stack.PortRange() 572 } 573 574 // SetPortRange implements inet.Stack.SetPortRange. 575 func (s *Stack) SetPortRange(start uint16, end uint16) error { 576 return syserr.TranslateNetstackError(s.Stack.SetPortRange(start, end)).ToError() 577 }