summaryrefslogtreecommitdiffhomepage
path: root/pkg
diff options
context:
space:
mode:
authorMikael Magnusson <mikma@users.sourceforge.net>2021-02-06 01:18:47 +0100
committerMikael Magnusson <mikma@users.sourceforge.net>2021-09-21 20:01:55 +0200
commit9ed2c54502009fb4b1c7179214a031c12518dfed (patch)
tree08f2275e4f25af379a75bf5577dcdb9905573e2a /pkg
parentb2718e250d7ef39048f03b9cc5eeeccf23d5ca8e (diff)
WIP: GRE runsc
Diffstat (limited to 'pkg')
-rw-r--r--pkg/abi/linux/netlink_route.go40
-rw-r--r--pkg/sentry/inet/inet.go3
-rw-r--r--pkg/sentry/socket/hostinet/stack.go5
-rw-r--r--pkg/sentry/socket/netlink/route/BUILD2
-rw-r--r--pkg/sentry/socket/netlink/route/protocol.go115
-rw-r--r--pkg/sentry/socket/netstack/BUILD1
-rw-r--r--pkg/sentry/socket/netstack/stack.go45
7 files changed, 211 insertions, 0 deletions
diff --git a/pkg/abi/linux/netlink_route.go b/pkg/abi/linux/netlink_route.go
index 581a11b24..514d8cb21 100644
--- a/pkg/abi/linux/netlink_route.go
+++ b/pkg/abi/linux/netlink_route.go
@@ -165,6 +165,45 @@ const (
IFLA_GSO_MAX_SIZE = 41
)
+// Interface link info attributes, from uapi/linux/if_link.h.
+const (
+ IFLA_INFO_UNSPEC = 0
+ IFLA_INFO_KIND = 1
+ IFLA_INFO_DATA = 2
+ IFLA_INFO_XSTATS = 3
+ IFLA_INFO_SLAVE_KIND = 4
+ IFLA_INFO_SLAVE_DATA = 5
+)
+
+// Interface link GRE attributes, from uapi/linux/if_link.h.
+const (
+ IFLA_GRE_UNSPEC = 0
+ IFLA_GRE_LINK = 1
+ IFLA_GRE_IFLAGS = 2
+ IFLA_GRE_OFLAGS = 3
+ IFLA_GRE_IKEY = 4
+ IFLA_GRE_OKEY = 5
+ IFLA_GRE_LOCAL = 6
+ IFLA_GRE_REMOTE = 7
+ IFLA_GRE_TTL = 8
+ IFLA_GRE_TOS = 9
+ IFLA_GRE_PMTUDISC = 10
+ IFLA_GRE_ENCAP_LIMIT = 11
+ IFLA_GRE_FLOWINFO = 12
+ IFLA_GRE_FLAGS = 13
+ IFLA_GRE_ENCAP_TYPE = 14
+ IFLA_GRE_ENCAP_FLAGS = 15
+ IFLA_GRE_ENCAP_SPORT = 16
+ IFLA_GRE_ENCAP_DPORT = 17
+ IFLA_GRE_COLLECT_METADATA = 18
+ IFLA_GRE_IGNORE_DF = 19
+ IFLA_GRE_FWMARK = 20
+ IFLA_GRE_ERSPAN_INDEX = 21
+ IFLA_GRE_ERSPAN_VER = 22
+ IFLA_GRE_ERSPAN_DIR = 23
+ IFLA_GRE_ERSPAN_HWID = 24
+)
+
// InterfaceAddrMessage is struct ifaddrmsg, from uapi/linux/if_addr.h.
//
// +marshal
@@ -194,6 +233,7 @@ const (
ARPHRD_NONE = 65534
ARPHRD_ETHER = 1
ARPHRD_LOOPBACK = 772
+ ARPHRD_IPGRE = 778
)
// RouteMessage is struct rtmsg, from uapi/linux/rtnetlink.h.
diff --git a/pkg/sentry/inet/inet.go b/pkg/sentry/inet/inet.go
index b121fc1b4..81462571c 100644
--- a/pkg/sentry/inet/inet.go
+++ b/pkg/sentry/inet/inet.go
@@ -34,6 +34,9 @@ type Stack interface {
// interface indexes to a slice of associated interface address properties.
InterfaceAddrs() map[int32][]InterfaceAddr
+ // AddGREInterface adds a GRE tunnel interface
+ AddGREInterface(name string, local, remote InterfaceAddr) (int32, error)
+
// AddInterfaceAddr adds an address to the network interface identified by
// idx.
AddInterfaceAddr(idx int32, addr InterfaceAddr) error
diff --git a/pkg/sentry/socket/hostinet/stack.go b/pkg/sentry/socket/hostinet/stack.go
index 61111ac6c..31e4ab445 100644
--- a/pkg/sentry/socket/hostinet/stack.go
+++ b/pkg/sentry/socket/hostinet/stack.go
@@ -323,6 +323,11 @@ func (s *Stack) InterfaceAddrs() map[int32][]inet.InterfaceAddr {
return addrs
}
+// AddGREInterface implements inet.Stack.AddGREInterface.
+func (s *Stack) AddGREInterface(name string, local, remote inet.InterfaceAddr) (int32, error) {
+ return -1, linuxerr.EACCES
+}
+
// AddInterfaceAddr implements inet.Stack.AddInterfaceAddr.
func (*Stack) AddInterfaceAddr(int32, inet.InterfaceAddr) error {
return linuxerr.EACCES
diff --git a/pkg/sentry/socket/netlink/route/BUILD b/pkg/sentry/socket/netlink/route/BUILD
index c6c04b4e3..77eb76a5e 100644
--- a/pkg/sentry/socket/netlink/route/BUILD
+++ b/pkg/sentry/socket/netlink/route/BUILD
@@ -10,7 +10,9 @@ go_library(
visibility = ["//pkg/sentry:internal"],
deps = [
"//pkg/abi/linux",
+ "//pkg/binary",
"//pkg/context",
+ "//pkg/hostarch",
"//pkg/marshal/primitive",
"//pkg/sentry/inet",
"//pkg/sentry/kernel",
diff --git a/pkg/sentry/socket/netlink/route/protocol.go b/pkg/sentry/socket/netlink/route/protocol.go
index d526acb73..5851b8826 100644
--- a/pkg/sentry/socket/netlink/route/protocol.go
+++ b/pkg/sentry/socket/netlink/route/protocol.go
@@ -20,7 +20,9 @@ import (
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/binary"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/marshal/primitive"
"gvisor.dev/gvisor/pkg/sentry/inet"
"gvisor.dev/gvisor/pkg/sentry/kernel"
@@ -161,6 +163,117 @@ func (p *Protocol) getLink(ctx context.Context, msg *netlink.Message, ms *netlin
return nil
}
+// newLink handles RTM_NEWLINK requests.
+func (p *Protocol) newLink(ctx context.Context, msg *netlink.Message, ms *netlink.MessageSet) *syserr.Error {
+ stack := inet.StackFromContext(ctx)
+ if stack == nil {
+ // No network devices.
+ return nil
+ }
+
+ // Parse message.
+ var ifi linux.InterfaceInfoMessage
+ attrs, ok := msg.GetData(&ifi)
+ if !ok {
+ return syserr.ErrInvalidArgument
+ }
+
+ if attrs.Empty() {
+ return nil
+ }
+
+ // Parse attributes.
+ var byName []byte
+ var kind string
+ var local []byte
+ var remote []byte
+
+ for !attrs.Empty() {
+ ahdr, value, rest, ok := attrs.ParseFirst()
+ if !ok {
+ return syserr.ErrInvalidArgument
+ }
+ attrs = rest
+
+ switch ahdr.Type {
+ case linux.IFLA_IFNAME:
+ if len(value) < 1 {
+ return syserr.ErrInvalidArgument
+ }
+ byName = value[:len(value)-1]
+ case linux.IFLA_LINKINFO:
+ var data []byte
+
+ attrs := netlink.AttrsView(value)
+ for !attrs.Empty() {
+ ahdr, value, rest, ok := attrs.ParseFirst()
+ if !ok {
+ return syserr.ErrInvalidArgument
+ }
+ attrs = rest
+
+ switch ahdr.Type {
+ case linux.IFLA_INFO_KIND:
+ if len(value) < 1 {
+ return syserr.ErrInvalidArgument
+ }
+ kind = string(value)
+ case linux.IFLA_INFO_DATA:
+ data = value
+ }
+ }
+
+ if data == nil {
+ return syserr.ErrInvalidArgument
+ }
+
+ switch kind {
+ case "gre":
+ local = make([]byte,4,4)
+ remote = make([]byte,4,4)
+ case "ip6gre":
+ local = make([]byte,16,16)
+ remote = make([]byte,16,16)
+ default:
+ return syserr.ErrInvalidArgument
+ }
+
+ attrs = netlink.AttrsView(data)
+ for !attrs.Empty() {
+ ahdr, value, rest, ok := attrs.ParseFirst()
+ if !ok {
+ return syserr.ErrInvalidArgument
+ }
+ attrs = rest
+
+ switch ahdr.Type {
+ case linux.IFLA_GRE_LOCAL:
+ binary.Unmarshal(value, hostarch.ByteOrder, &local)
+ case linux.IFLA_GRE_REMOTE:
+ binary.Unmarshal(value, hostarch.ByteOrder, &remote)
+ }
+ }
+ }
+ }
+
+ if kind == "" {
+ return syserr.ErrInvalidArgument
+ }
+
+ localAddr := inet.InterfaceAddr{
+ Addr: local,
+ }
+ remoteAddr := inet.InterfaceAddr{
+ Addr: remote,
+ }
+ _, err := stack.AddGREInterface(string(byName), localAddr, remoteAddr)
+ if err != nil {
+ return syserr.ErrInvalidArgument
+ }
+
+ return nil
+}
+
// delLink handles RTM_DELLINK requests.
func (p *Protocol) delLink(ctx context.Context, msg *netlink.Message, ms *netlink.MessageSet) *syserr.Error {
stack := inet.StackFromContext(ctx)
@@ -578,6 +691,8 @@ func (p *Protocol) ProcessMessage(ctx context.Context, msg *netlink.Message, ms
switch hdr.Type {
case linux.RTM_GETLINK:
return p.getLink(ctx, msg, ms)
+ case linux.RTM_NEWLINK:
+ return p.newLink(ctx, msg, ms)
case linux.RTM_DELLINK:
return p.delLink(ctx, msg, ms)
case linux.RTM_GETROUTE:
diff --git a/pkg/sentry/socket/netstack/BUILD b/pkg/sentry/socket/netstack/BUILD
index bf5ec4558..94be6344a 100644
--- a/pkg/sentry/socket/netstack/BUILD
+++ b/pkg/sentry/socket/netstack/BUILD
@@ -51,6 +51,7 @@ go_library(
"//pkg/tcpip/transport",
"//pkg/tcpip/transport/tcp",
"//pkg/tcpip/transport/udp",
+ "//pkg/tcpip/link/tunnel",
"//pkg/usermem",
"//pkg/waiter",
"@org_golang_x_sys//unix:go_default_library",
diff --git a/pkg/sentry/socket/netstack/stack.go b/pkg/sentry/socket/netstack/stack.go
index ea199f223..751ba74ac 100644
--- a/pkg/sentry/socket/netstack/stack.go
+++ b/pkg/sentry/socket/netstack/stack.go
@@ -28,6 +28,7 @@ import (
"gvisor.dev/gvisor/pkg/tcpip/network/ipv6"
"gvisor.dev/gvisor/pkg/tcpip/stack"
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
+ "gvisor.dev/gvisor/pkg/tcpip/link/tunnel"
)
// Stack implements inet.Stack for netstack/tcpip/stack.Stack.
@@ -51,6 +52,8 @@ func toLinuxARPHardwareType(t header.ARPHardwareType) uint16 {
return linux.ARPHRD_LOOPBACK
case header.ARPHardwareEther:
return linux.ARPHRD_ETHER
+ case header.ARPHardwareIPGRE:
+ return linux.ARPHRD_IPGRE
default:
panic(fmt.Sprintf("unknown ARPHRD type: %d", t))
}
@@ -74,6 +77,12 @@ func (s *Stack) Interfaces() map[int32]inet.Interface {
// RemoveInterface implements inet.Stack.RemoveInterface.
func (s *Stack) RemoveInterface(idx int32) error {
nic := tcpip.NICID(idx)
+ name := s.Stack.FindNICNameFromID(nic)
+
+ if name == "lo" || name == "eth0" {
+ return syserr.ErrNotPermitted.ToError()
+ }
+
return syserr.TranslateNetstackError(s.Stack.RemoveNIC(nic)).ToError()
}
@@ -146,6 +155,42 @@ func convertAddr(addr inet.InterfaceAddr) (tcpip.ProtocolAddress, error) {
return protocolAddress, nil
}
+func (s *Stack) nextInterfaceIndex() tcpip.NICID {
+ var maxIdx tcpip.NICID = 0
+
+ for id, _ := range s.Stack.NICInfo() {
+ if id > maxIdx {
+ maxIdx = id
+ }
+ }
+
+ return maxIdx + 1
+}
+
+func (s *Stack) AddGREInterface(name string, local, remote inet.InterfaceAddr) (int32, error) {
+ var mtu uint32 = 1280
+ var idx tcpip.NICID = s.nextInterfaceIndex()
+
+ localAddr := tcpip.Address(local.Addr)
+ remoteAddr := tcpip.Address(remote.Addr)
+
+ greEP := tunnel.New(mtu)
+ if remoteAddr == header.IPv4Any {
+ greEP.Endpoint.LinkEPCapabilities = stack.CapabilityResolutionRequired
+ }
+
+ if err := s.Stack.CreateNICWithOptions(idx, greEP, stack.NICOptions{Name: name}); err != nil {
+ return -1, syserr.TranslateNetstackError(err).ToError()
+ }
+
+ err := greEP.Start(s.Stack, idx, &localAddr, &remoteAddr)
+ if err != nil {
+ return -1, syserr.TranslateNetstackError(err).ToError()
+ }
+
+ return int32(idx), nil
+}
+
// AddInterfaceAddr implements inet.Stack.AddInterfaceAddr.
func (s *Stack) AddInterfaceAddr(idx int32, addr inet.InterfaceAddr) error {
protocolAddress, err := convertAddr(addr)