diff options
Diffstat (limited to 'pkg/sentry/inet')
-rw-r--r-- | pkg/sentry/inet/BUILD | 20 | ||||
-rw-r--r-- | pkg/sentry/inet/context.go | 35 | ||||
-rw-r--r-- | pkg/sentry/inet/inet.go | 191 | ||||
-rw-r--r-- | pkg/sentry/inet/namespace.go | 102 | ||||
-rw-r--r-- | pkg/sentry/inet/test_stack.go | 118 |
5 files changed, 466 insertions, 0 deletions
diff --git a/pkg/sentry/inet/BUILD b/pkg/sentry/inet/BUILD new file mode 100644 index 000000000..07bf39fed --- /dev/null +++ b/pkg/sentry/inet/BUILD @@ -0,0 +1,20 @@ +load("//tools:defs.bzl", "go_library") + +package( + default_visibility = ["//:sandbox"], + licenses = ["notice"], +) + +go_library( + name = "inet", + srcs = [ + "context.go", + "inet.go", + "namespace.go", + "test_stack.go", + ], + deps = [ + "//pkg/context", + "//pkg/tcpip/stack", + ], +) diff --git a/pkg/sentry/inet/context.go b/pkg/sentry/inet/context.go new file mode 100644 index 000000000..e8cc1bffd --- /dev/null +++ b/pkg/sentry/inet/context.go @@ -0,0 +1,35 @@ +// Copyright 2018 The gVisor Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package inet + +import ( + "gvisor.dev/gvisor/pkg/context" +) + +// contextID is the inet package's type for context.Context.Value keys. +type contextID int + +const ( + // CtxStack is a Context.Value key for a network stack. + CtxStack contextID = iota +) + +// StackFromContext returns the network stack associated with ctx. +func StackFromContext(ctx context.Context) Stack { + if v := ctx.Value(CtxStack); v != nil { + return v.(Stack) + } + return nil +} diff --git a/pkg/sentry/inet/inet.go b/pkg/sentry/inet/inet.go new file mode 100644 index 000000000..2916a0644 --- /dev/null +++ b/pkg/sentry/inet/inet.go @@ -0,0 +1,191 @@ +// Copyright 2018 The gVisor Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package inet defines semantics for IP stacks. +package inet + +import "gvisor.dev/gvisor/pkg/tcpip/stack" + +// Stack represents a TCP/IP stack. +type Stack interface { + // Interfaces returns all network interfaces as a mapping from interface + // indexes to interface properties. Interface indices are strictly positive + // integers. + Interfaces() map[int32]Interface + + // InterfaceAddrs returns all network interface addresses as a mapping from + // interface indexes to a slice of associated interface address properties. + InterfaceAddrs() map[int32][]InterfaceAddr + + // AddInterfaceAddr adds an address to the network interface identified by + // index. + AddInterfaceAddr(idx int32, addr InterfaceAddr) error + + // SupportsIPv6 returns true if the stack supports IPv6 connectivity. + SupportsIPv6() bool + + // TCPReceiveBufferSize returns TCP receive buffer size settings. + TCPReceiveBufferSize() (TCPBufferSize, error) + + // SetTCPReceiveBufferSize attempts to change TCP receive buffer size + // settings. + SetTCPReceiveBufferSize(size TCPBufferSize) error + + // TCPSendBufferSize returns TCP send buffer size settings. + TCPSendBufferSize() (TCPBufferSize, error) + + // SetTCPSendBufferSize attempts to change TCP send buffer size settings. + SetTCPSendBufferSize(size TCPBufferSize) error + + // TCPSACKEnabled returns true if RFC 2018 TCP Selective Acknowledgements + // are enabled. + TCPSACKEnabled() (bool, error) + + // SetTCPSACKEnabled attempts to change TCP selective acknowledgement + // settings. + SetTCPSACKEnabled(enabled bool) error + + // Statistics reports stack statistics. + Statistics(stat interface{}, arg string) error + + // RouteTable returns the network stack's route table. + RouteTable() []Route + + // Resume restarts the network stack after restore. + Resume() + + // RegisteredEndpoints returns all endpoints which are currently registered. + RegisteredEndpoints() []stack.TransportEndpoint + + // CleanupEndpoints returns endpoints currently in the cleanup state. + CleanupEndpoints() []stack.TransportEndpoint + + // RestoreCleanupEndpoints adds endpoints to cleanup tracking. This is useful + // for restoring a stack after a save. + RestoreCleanupEndpoints([]stack.TransportEndpoint) +} + +// Interface contains information about a network interface. +type Interface struct { + // DeviceType is the device type, a Linux ARPHRD_* constant. + DeviceType uint16 + + // Flags is the device flags; see netdevice(7), under "Ioctls", + // "SIOCGIFFLAGS, SIOCSIFFLAGS". + Flags uint32 + + // Name is the device name. + Name string + + // Addr is the hardware device address. + Addr []byte + + // MTU is the maximum transmission unit. + MTU uint32 +} + +// InterfaceAddr contains information about a network interface address. +type InterfaceAddr struct { + // Family is the address family, a Linux AF_* constant. + Family uint8 + + // PrefixLen is the address prefix length. + PrefixLen uint8 + + // Flags is the address flags. + Flags uint8 + + // Addr is the actual address. + Addr []byte +} + +// TCPBufferSize contains settings controlling TCP buffer sizing. +// +// +stateify savable +type TCPBufferSize struct { + // Min is the minimum size. + Min int + + // Default is the default size. + Default int + + // Max is the maximum size. + Max int +} + +// StatDev describes one line of /proc/net/dev, i.e., stats for one network +// interface. +type StatDev [16]uint64 + +// Route contains information about a network route. +type Route struct { + // Family is the address family, a Linux AF_* constant. + Family uint8 + + // DstLen is the length of the destination address. + DstLen uint8 + + // SrcLen is the length of the source address. + SrcLen uint8 + + // TOS is the Type of Service filter. + TOS uint8 + + // Table is the routing table ID. + Table uint8 + + // Protocol is the route origin, a Linux RTPROT_* constant. + Protocol uint8 + + // Scope is the distance to destination, a Linux RT_SCOPE_* constant. + Scope uint8 + + // Type is the route origin, a Linux RTN_* constant. + Type uint8 + + // Flags are route flags. See rtnetlink(7) under "rtm_flags". + Flags uint32 + + // DstAddr is the route destination address (RTA_DST). + DstAddr []byte + + // SrcAddr is the route source address (RTA_SRC). + SrcAddr []byte + + // OutputInterface is the output interface index (RTA_OIF). + OutputInterface int32 + + // GatewayAddr is the route gateway address (RTA_GATEWAY). + GatewayAddr []byte +} + +// Below SNMP metrics are from Linux/usr/include/linux/snmp.h. + +// StatSNMPIP describes Ip line of /proc/net/snmp. +type StatSNMPIP [19]uint64 + +// StatSNMPICMP describes Icmp line of /proc/net/snmp. +type StatSNMPICMP [27]uint64 + +// StatSNMPICMPMSG describes IcmpMsg line of /proc/net/snmp. +type StatSNMPICMPMSG [512]uint64 + +// StatSNMPTCP describes Tcp line of /proc/net/snmp. +type StatSNMPTCP [15]uint64 + +// StatSNMPUDP describes Udp line of /proc/net/snmp. +type StatSNMPUDP [8]uint64 + +// StatSNMPUDPLite describes UdpLite line of /proc/net/snmp. +type StatSNMPUDPLite [8]uint64 diff --git a/pkg/sentry/inet/namespace.go b/pkg/sentry/inet/namespace.go new file mode 100644 index 000000000..029af3025 --- /dev/null +++ b/pkg/sentry/inet/namespace.go @@ -0,0 +1,102 @@ +// Copyright 2020 The gVisor Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package inet + +// Namespace represents a network namespace. See network_namespaces(7). +// +// +stateify savable +type Namespace struct { + // stack is the network stack implementation of this network namespace. + stack Stack `state:"nosave"` + + // creator allows kernel to create new network stack for network namespaces. + // If nil, no networking will function if network is namespaced. + // + // At afterLoad(), creator will be used to create network stack. Stateify + // needs to wait for this field to be loaded before calling afterLoad(). + creator NetworkStackCreator `state:"wait"` + + // isRoot indicates whether this is the root network namespace. + isRoot bool +} + +// NewRootNamespace creates the root network namespace, with creator +// allowing new network namespaces to be created. If creator is nil, no +// networking will function if the network is namespaced. +func NewRootNamespace(stack Stack, creator NetworkStackCreator) *Namespace { + return &Namespace{ + stack: stack, + creator: creator, + isRoot: true, + } +} + +// NewNamespace creates a new network namespace from the root. +func NewNamespace(root *Namespace) *Namespace { + n := &Namespace{ + creator: root.creator, + } + n.init() + return n +} + +// Stack returns the network stack of n. Stack may return nil if no network +// stack is configured. +func (n *Namespace) Stack() Stack { + return n.stack +} + +// IsRoot returns whether n is the root network namespace. +func (n *Namespace) IsRoot() bool { + return n.isRoot +} + +// RestoreRootStack restores the root network namespace with stack. This should +// only be called when restoring kernel. +func (n *Namespace) RestoreRootStack(stack Stack) { + if !n.isRoot { + panic("RestoreRootStack can only be called on root network namespace") + } + if n.stack != nil { + panic("RestoreRootStack called after a stack has already been set") + } + n.stack = stack +} + +func (n *Namespace) init() { + // Root network namespace will have stack assigned later. + if n.isRoot { + return + } + if n.creator != nil { + var err error + n.stack, err = n.creator.CreateStack() + if err != nil { + panic(err) + } + } +} + +// afterLoad is invoked by stateify. +func (n *Namespace) afterLoad() { + n.init() +} + +// NetworkStackCreator allows new instances of a network stack to be created. It +// is used by the kernel to create new network namespaces when requested. +type NetworkStackCreator interface { + // CreateStack creates a new network stack for a network namespace. + CreateStack() (Stack, error) +} diff --git a/pkg/sentry/inet/test_stack.go b/pkg/sentry/inet/test_stack.go new file mode 100644 index 000000000..d8961fc94 --- /dev/null +++ b/pkg/sentry/inet/test_stack.go @@ -0,0 +1,118 @@ +// Copyright 2018 The gVisor Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package inet + +import "gvisor.dev/gvisor/pkg/tcpip/stack" + +// TestStack is a dummy implementation of Stack for tests. +type TestStack struct { + InterfacesMap map[int32]Interface + InterfaceAddrsMap map[int32][]InterfaceAddr + RouteList []Route + SupportsIPv6Flag bool + TCPRecvBufSize TCPBufferSize + TCPSendBufSize TCPBufferSize + TCPSACKFlag bool +} + +// NewTestStack returns a TestStack with no network interfaces. The value of +// all other options is unspecified; tests that rely on specific values must +// set them explicitly. +func NewTestStack() *TestStack { + return &TestStack{ + InterfacesMap: make(map[int32]Interface), + InterfaceAddrsMap: make(map[int32][]InterfaceAddr), + } +} + +// Interfaces implements Stack.Interfaces. +func (s *TestStack) Interfaces() map[int32]Interface { + return s.InterfacesMap +} + +// InterfaceAddrs implements Stack.InterfaceAddrs. +func (s *TestStack) InterfaceAddrs() map[int32][]InterfaceAddr { + return s.InterfaceAddrsMap +} + +// AddInterfaceAddr implements Stack.AddInterfaceAddr. +func (s *TestStack) AddInterfaceAddr(idx int32, addr InterfaceAddr) error { + s.InterfaceAddrsMap[idx] = append(s.InterfaceAddrsMap[idx], addr) + return nil +} + +// SupportsIPv6 implements Stack.SupportsIPv6. +func (s *TestStack) SupportsIPv6() bool { + return s.SupportsIPv6Flag +} + +// TCPReceiveBufferSize implements Stack.TCPReceiveBufferSize. +func (s *TestStack) TCPReceiveBufferSize() (TCPBufferSize, error) { + return s.TCPRecvBufSize, nil +} + +// SetTCPReceiveBufferSize implements Stack.SetTCPReceiveBufferSize. +func (s *TestStack) SetTCPReceiveBufferSize(size TCPBufferSize) error { + s.TCPRecvBufSize = size + return nil +} + +// TCPSendBufferSize implements Stack.TCPSendBufferSize. +func (s *TestStack) TCPSendBufferSize() (TCPBufferSize, error) { + return s.TCPSendBufSize, nil +} + +// SetTCPSendBufferSize implements Stack.SetTCPSendBufferSize. +func (s *TestStack) SetTCPSendBufferSize(size TCPBufferSize) error { + s.TCPSendBufSize = size + return nil +} + +// TCPSACKEnabled implements Stack.TCPSACKEnabled. +func (s *TestStack) TCPSACKEnabled() (bool, error) { + return s.TCPSACKFlag, nil +} + +// SetTCPSACKEnabled implements Stack.SetTCPSACKEnabled. +func (s *TestStack) SetTCPSACKEnabled(enabled bool) error { + s.TCPSACKFlag = enabled + return nil +} + +// Statistics implements inet.Stack.Statistics. +func (s *TestStack) Statistics(stat interface{}, arg string) error { + return nil +} + +// RouteTable implements Stack.RouteTable. +func (s *TestStack) RouteTable() []Route { + return s.RouteList +} + +// Resume implements Stack.Resume. +func (s *TestStack) Resume() {} + +// RegisteredEndpoints implements inet.Stack.RegisteredEndpoints. +func (s *TestStack) RegisteredEndpoints() []stack.TransportEndpoint { + return nil +} + +// CleanupEndpoints implements inet.Stack.CleanupEndpoints. +func (s *TestStack) CleanupEndpoints() []stack.TransportEndpoint { + return nil +} + +// RestoreCleanupEndpoints implements inet.Stack.RestoreCleanupEndpoints. +func (s *TestStack) RestoreCleanupEndpoints([]stack.TransportEndpoint) {} |