From 222258a585465cdc0072dc44e676d8b5e48304b2 Mon Sep 17 00:00:00 2001 From: Jing Chen Date: Sat, 6 Jul 2024 00:46:26 -0700 Subject: [PATCH] Support RTM_SETLINK in gVisor. RTM_NEWLINK is the preferred way to change a link's configs. RTM_SETLINK is needed by setting up Docker in gVisor. PiperOrigin-RevId: 649789500 --- pkg/sentry/socket/netlink/route/protocol.go | 21 +++++++++++++++++++-- test/syscalls/linux/socket_netlink_route.cc | 15 +++++++++++---- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/pkg/sentry/socket/netlink/route/protocol.go b/pkg/sentry/socket/netlink/route/protocol.go index c3629a4f8..80f224a0a 100644 --- a/pkg/sentry/socket/netlink/route/protocol.go +++ b/pkg/sentry/socket/netlink/route/protocol.go @@ -162,6 +162,7 @@ func (p *Protocol) getLink(ctx context.Context, s *netlink.Socket, msg *nlmsg.Me return nil } +// newLink handles RTM_NEWLINK reqeusts. func (p *Protocol) newLink(ctx context.Context, s *netlink.Socket, msg *nlmsg.Message, ms *nlmsg.MessageSet) *syserr.Error { stack := s.Stack() if stack == nil { @@ -172,6 +173,21 @@ func (p *Protocol) newLink(ctx context.Context, s *netlink.Socket, msg *nlmsg.Me return stack.SetInterface(ctx, msg) } +// setLink handles RTM_SETLINK requests. +func (p *Protocol) setLink(ctx context.Context, s *netlink.Socket, msg *nlmsg.Message, ms *nlmsg.MessageSet) *syserr.Error { + stack := s.Stack() + if stack == nil { + // No network stack. + return syserr.ErrProtocolNotSupported + } + + if msg.Header().Flags&linux.NLM_F_CREATE == linux.NLM_F_CREATE { + return syserr.ErrInvalidArgument + } + + return stack.SetInterface(ctx, msg) +} + // delLink handles RTM_DELLINK requests. func (p *Protocol) delLink(ctx context.Context, s *netlink.Socket, msg *nlmsg.Message, ms *nlmsg.MessageSet) *syserr.Error { stack := s.Stack() @@ -594,14 +610,15 @@ func (p *Protocol) ProcessMessage(ctx context.Context, s *netlink.Socket, msg *n return p.getLink(ctx, s, msg, ms) case linux.RTM_DELLINK: return p.delLink(ctx, s, msg, ms) + case linux.RTM_SETLINK: + // RTM_NEWLINK is backward compatible to RTM_SETLINK. + return p.setLink(ctx, s, msg, ms) case linux.RTM_GETROUTE: return p.dumpRoutes(ctx, s, msg, ms) case linux.RTM_NEWADDR: return p.newAddr(ctx, s, msg, ms) case linux.RTM_DELADDR: return p.delAddr(ctx, s, msg, ms) - case linux.RTM_SETLINK: - return nil default: return syserr.ErrNotSupported } diff --git a/test/syscalls/linux/socket_netlink_route.cc b/test/syscalls/linux/socket_netlink_route.cc index b7ef64324..14b860d72 100644 --- a/test/syscalls/linux/socket_netlink_route.cc +++ b/test/syscalls/linux/socket_netlink_route.cc @@ -207,7 +207,14 @@ TEST(NetlinkRouteTest, GetLinkByIndex) { EXPECT_TRUE(found) << "Netlink response does not contain any links."; } -TEST(NetlinkRouteTest, ChangeLinkName) { +// NetlinkRouteTest with a single parameter that must be RTM_NEWLINK or +// RTM_SETLINK. +using NetlinkSetLinkTest = ::testing::TestWithParam; + +INSTANTIATE_TEST_SUITE_P(_, NetlinkSetLinkTest, + ::testing::Values(RTM_NEWLINK, RTM_SETLINK)); + +TEST_P(NetlinkSetLinkTest, ChangeLinkName) { SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_ADMIN))); SKIP_IF(IsRunningWithHostinet()); // Hosts that run with old kernel allow renaming only when @@ -231,7 +238,7 @@ TEST(NetlinkRouteTest, ChangeLinkName) { // Change the link name. struct request req = {}; req.hdr.nlmsg_len = sizeof(req); - req.hdr.nlmsg_type = RTM_NEWLINK; + req.hdr.nlmsg_type = GetParam(); req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; req.hdr.nlmsg_seq = kSeq; req.ifm.ifi_family = AF_UNSPEC; @@ -265,7 +272,7 @@ TEST(NetlinkRouteTest, ChangeLinkName) { EXPECT_TRUE(found) << "Netlink response does not contain any links."; } -TEST(NetlinkRouteTest, ChangeMTU) { +TEST_P(NetlinkSetLinkTest, ChangeMTU) { SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_ADMIN))); SKIP_IF(IsRunningWithHostinet()); SKIP_IF(!IsRunningOnGvisor()); @@ -283,7 +290,7 @@ TEST(NetlinkRouteTest, ChangeMTU) { // Change the MTU. req.hdr.nlmsg_len = sizeof(req); - req.hdr.nlmsg_type = RTM_NEWLINK; + req.hdr.nlmsg_type = GetParam(); req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; req.hdr.nlmsg_seq = kSeq; req.ifm.ifi_family = AF_UNSPEC;