Pass NEWLINK netlink commands to network stacks

The NEWLINK commands contains many properties and here is no reason to have
another abstract interface between the Sentry and network stacks.

PiperOrigin-RevId: 627916629
This commit is contained in:
Andrei Vagin
2024-04-24 18:42:44 -07:00
committed by gVisor bot
parent 9c7a659d7b
commit 129734a352
8 changed files with 138 additions and 57 deletions
+1
View File
@@ -44,6 +44,7 @@ go_library(
"//pkg/refs",
"//pkg/sentry/fsimpl/nsfs",
"//pkg/sentry/kernel/auth",
"//pkg/sentry/socket/netlink/nlmsg",
"//pkg/sentry/socket/unix/transport",
"//pkg/sync",
"//pkg/sync/locking",
+6
View File
@@ -17,6 +17,9 @@ package inet
import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/sentry/socket/netlink/nlmsg"
"gvisor.dev/gvisor/pkg/syserr"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
@@ -39,6 +42,9 @@ type Stack interface {
// idx.
AddInterfaceAddr(idx int32, addr InterfaceAddr) error
// SetInterface modifies or adds a new interface.
SetInterface(ctx context.Context, msg *nlmsg.Message) *syserr.Error
// RemoveInterfaceAddr removes an address from the network interface
// identified by idx.
RemoveInterfaceAddr(idx int32, addr InterfaceAddr) error
+8
View File
@@ -19,6 +19,9 @@ import (
"fmt"
"time"
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/sentry/socket/netlink/nlmsg"
"gvisor.dev/gvisor/pkg/syserr"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
@@ -61,6 +64,11 @@ func (s *TestStack) RemoveInterface(idx int32) error {
return nil
}
// SetInterface implements Stack.
func (s *TestStack) SetInterface(ctx context.Context, msg *nlmsg.Message) *syserr.Error {
panic("unimplemented")
}
// InterfaceAddrs implements Stack.
func (s *TestStack) InterfaceAddrs() map[int32][]InterfaceAddr {
return s.InterfaceAddrsMap
+1
View File
@@ -39,6 +39,7 @@ go_library(
"//pkg/sentry/kernel/time",
"//pkg/sentry/socket",
"//pkg/sentry/socket/control",
"//pkg/sentry/socket/netlink/nlmsg",
"//pkg/sentry/vfs",
"//pkg/syserr",
"//pkg/tcpip",
+60
View File
@@ -23,10 +23,12 @@ import (
"strconv"
"strings"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/sentry/inet"
"gvisor.dev/gvisor/pkg/sentry/socket/netlink/nlmsg"
"gvisor.dev/gvisor/pkg/syserr"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/stack"
@@ -165,6 +167,64 @@ func (s *Stack) InterfaceAddrs() map[int32][]inet.InterfaceAddr {
return addrs
}
// SetInterface implements inet.Stack.SetInterface.
func (s *Stack) SetInterface(ctx context.Context, msg *nlmsg.Message) *syserr.Error {
var ifinfomsg linux.InterfaceInfoMessage
attrs, ok := msg.GetData(&ifinfomsg)
if !ok {
return syserr.ErrInvalidArgument
}
for !attrs.Empty() {
// The index is unspecified, search by the interface name.
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
}
if ifinfomsg.Index != 0 {
// Device name changing isn't supported yet.
return syserr.ErrNotSupported
}
ifname := string(value[:len(value)-1])
for idx, ifa := range s.Interfaces() {
if ifname == ifa.Name {
ifinfomsg.Index = idx
break
}
}
default:
ctx.Warningf("unexpected attribute: %x", ahdr.Type)
return syserr.ErrNotSupported
}
}
if ifinfomsg.Index == 0 {
return syserr.ErrNoDevice
}
flags := msg.Header().Flags
if flags&(linux.NLM_F_EXCL|linux.NLM_F_REPLACE) != 0 {
return syserr.ErrExists
}
if ifinfomsg.Flags != 0 || ifinfomsg.Change != 0 {
if ifinfomsg.Change & ^uint32(linux.IFF_UP) != 0 {
ctx.Warningf("Unsupported ifi_change flags: %x", ifinfomsg.Change)
return syserr.ErrInvalidArgument
}
if ifinfomsg.Flags & ^uint32(linux.IFF_UP) != 0 {
ctx.Warningf("Unsupported ifi_flags: %x", ifinfomsg.Change)
return syserr.ErrInvalidArgument
}
// Netstack interfaces are always up.
}
return nil
}
// AddInterfaceAddr implements inet.Stack.AddInterfaceAddr.
func (*Stack) AddInterfaceAddr(idx int32, addr inet.InterfaceAddr) error {
return addInterfaceAddr(idx, addr)
+1 -57
View File
@@ -169,63 +169,7 @@ func (p *Protocol) newLink(ctx context.Context, msg *nlmsg.Message, ms *nlmsg.Me
return syserr.ErrProtocolNotSupported
}
var ifinfomsg linux.InterfaceInfoMessage
attrs, ok := msg.GetData(&ifinfomsg)
if !ok {
return syserr.ErrInvalidArgument
}
for !attrs.Empty() {
// The index is unspecified, search by the interface name.
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
}
if ifinfomsg.Index != 0 {
// Device name changing isn't supported yet.
return syserr.ErrNotSupported
}
ifname := string(value[:len(value)-1])
for idx, ifa := range stack.Interfaces() {
if ifname == ifa.Name {
ifinfomsg.Index = idx
break
}
}
default:
ctx.Warningf("unexpected attribute: %x", ahdr.Type)
return syserr.ErrNotSupported
}
}
if ifinfomsg.Index == 0 {
return syserr.ErrNoDevice
}
flags := msg.Header().Flags
if flags&linux.NLM_F_EXCL != 0 {
return syserr.ErrExists
}
if flags&linux.NLM_F_REPLACE != 0 {
return syserr.ErrExists
}
if ifinfomsg.Flags != 0 || ifinfomsg.Change != 0 {
if ifinfomsg.Change & ^uint32(linux.IFF_UP) != 0 {
ctx.Warningf("Unsupported ifi_change flags: %x", ifinfomsg.Change)
return syserr.ErrInvalidArgument
}
if ifinfomsg.Flags & ^uint32(linux.IFF_UP) != 0 {
ctx.Warningf("Unsupported ifi_flags: %x", ifinfomsg.Change)
return syserr.ErrInvalidArgument
}
// Netstack interfaces are always up.
}
return nil
return stack.SetInterface(ctx, msg)
}
// delLink handles RTM_DELLINK requests.
+1
View File
@@ -39,6 +39,7 @@ go_library(
"//pkg/sentry/kernel/time",
"//pkg/sentry/socket",
"//pkg/sentry/socket/netfilter",
"//pkg/sentry/socket/netlink/nlmsg",
"//pkg/sentry/vfs",
"//pkg/sync",
"//pkg/syserr",
+60
View File
@@ -18,10 +18,12 @@ import (
"fmt"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/refs"
"gvisor.dev/gvisor/pkg/sentry/inet"
"gvisor.dev/gvisor/pkg/sentry/socket/netlink/nlmsg"
"gvisor.dev/gvisor/pkg/syserr"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/header"
@@ -99,6 +101,64 @@ func (s *Stack) RemoveInterface(idx int32) error {
return syserr.TranslateNetstackError(s.Stack.RemoveNIC(nic)).ToError()
}
// SetInterface implements inet.Stack.SetInterface.
func (s *Stack) SetInterface(ctx context.Context, msg *nlmsg.Message) *syserr.Error {
var ifinfomsg linux.InterfaceInfoMessage
attrs, ok := msg.GetData(&ifinfomsg)
if !ok {
return syserr.ErrInvalidArgument
}
for !attrs.Empty() {
// The index is unspecified, search by the interface name.
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
}
if ifinfomsg.Index != 0 {
// Device name changing isn't supported yet.
return syserr.ErrNotSupported
}
ifname := string(value[:len(value)-1])
for idx, ifa := range s.Interfaces() {
if ifname == ifa.Name {
ifinfomsg.Index = idx
break
}
}
default:
ctx.Warningf("unexpected attribute: %x", ahdr.Type)
return syserr.ErrNotSupported
}
}
if ifinfomsg.Index == 0 {
return syserr.ErrNoDevice
}
flags := msg.Header().Flags
if flags&(linux.NLM_F_EXCL|linux.NLM_F_REPLACE) != 0 {
return syserr.ErrExists
}
if ifinfomsg.Flags != 0 || ifinfomsg.Change != 0 {
if ifinfomsg.Change & ^uint32(linux.IFF_UP) != 0 {
ctx.Warningf("Unsupported ifi_change flags: %x", ifinfomsg.Change)
return syserr.ErrInvalidArgument
}
if ifinfomsg.Flags & ^uint32(linux.IFF_UP) != 0 {
ctx.Warningf("Unsupported ifi_flags: %x", ifinfomsg.Change)
return syserr.ErrInvalidArgument
}
// Netstack interfaces are always up.
}
return nil
}
// InterfaceAddrs implements inet.Stack.InterfaceAddrs.
func (s *Stack) InterfaceAddrs() map[int32][]inet.InterfaceAddr {
nicAddrs := make(map[int32][]inet.InterfaceAddr)