From b195ca54f311b5635cb8f7ea32600f10eb57f103 Mon Sep 17 00:00:00 2001 From: Lucas Manning Date: Tue, 16 Aug 2022 11:16:35 -0700 Subject: [PATCH] Netstack: Check that the multicast address matches the endpoint protocol. Reported-by: syzbot+a72cb94d1b5a6f5f0e11@syzkaller.appspotmail.com PiperOrigin-RevId: 467975743 --- pkg/tcpip/tcpip.go | 9 +++- pkg/tcpip/tests/integration/BUILD | 1 + .../integration/multicast_broadcast_test.go | 47 +++++++++++++++++++ .../transport/internal/network/endpoint.go | 2 +- 4 files changed, 56 insertions(+), 3 deletions(-) diff --git a/pkg/tcpip/tcpip.go b/pkg/tcpip/tcpip.go index 20d97d59b..cd981ba60 100644 --- a/pkg/tcpip/tcpip.go +++ b/pkg/tcpip/tcpip.go @@ -45,8 +45,13 @@ import ( "gvisor.dev/gvisor/pkg/waiter" ) -// Using header.IPv4AddressSize would cause an import cycle. -const ipv4AddressSize = 4 +// Using the header package here would cause an import cycle. +const ( + ipv4AddressSize = 4 + ipv4ProtocolNumber = 0x0800 + ipv6AddressSize = 16 + ipv6ProtocolNumber = 0x86dd +) // Errors related to Subnet var ( diff --git a/pkg/tcpip/tests/integration/BUILD b/pkg/tcpip/tests/integration/BUILD index 23380ce93..74ab47b5e 100644 --- a/pkg/tcpip/tests/integration/BUILD +++ b/pkg/tcpip/tests/integration/BUILD @@ -120,6 +120,7 @@ go_test( "//pkg/tcpip/tests/utils", "//pkg/tcpip/testutil", "//pkg/tcpip/transport/icmp", + "//pkg/tcpip/transport/raw", "//pkg/tcpip/transport/udp", "//pkg/waiter", "@com_github_google_go_cmp//cmp:go_default_library", diff --git a/pkg/tcpip/tests/integration/multicast_broadcast_test.go b/pkg/tcpip/tests/integration/multicast_broadcast_test.go index 52b88873f..399cb3861 100644 --- a/pkg/tcpip/tests/integration/multicast_broadcast_test.go +++ b/pkg/tcpip/tests/integration/multicast_broadcast_test.go @@ -32,6 +32,7 @@ import ( "gvisor.dev/gvisor/pkg/tcpip/tests/utils" "gvisor.dev/gvisor/pkg/tcpip/testutil" "gvisor.dev/gvisor/pkg/tcpip/transport/icmp" + "gvisor.dev/gvisor/pkg/tcpip/transport/raw" "gvisor.dev/gvisor/pkg/tcpip/transport/udp" "gvisor.dev/gvisor/pkg/waiter" ) @@ -777,3 +778,49 @@ func TestAddMembershipInterfacePrecedence(t *testing.T) { t.Fatalf("ep.SetSockOpt(&%#v): %s", addOpt, err) } } + +func TestMismatchedMulticastAddressAndProtocol(t *testing.T) { + const nicID = 1 + // MulticastAddr is IPv4, but proto is IPv6. + multicastAddr := tcpip.Address("\xe0\x01\x02\x03") + s := stack.New(stack.Options{ + NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, ipv6.NewProtocol}, + TransportProtocols: []stack.TransportProtocolFactory{icmp.NewProtocol6}, + RawFactory: raw.EndpointFactory{}, + }) + e := channel.New(0, defaultMTU, "") + defer e.Close() + if err := s.CreateNIC(nicID, e); err != nil { + t.Fatalf("CreateNIC(%d, _): %s", nicID, err) + } + protoAddr := tcpip.ProtocolAddress{Protocol: header.IPv4ProtocolNumber, AddressWithPrefix: utils.Ipv4Addr} + if err := s.AddProtocolAddress(nicID, protoAddr, stack.AddressProperties{}); err != nil { + t.Fatalf("AddProtocolAddress(%d, %+v, {}): %s", nicID, protoAddr, err) + } + + var wq waiter.Queue + ep, err := s.NewRawEndpoint(header.ICMPv6ProtocolNumber, header.IPv6ProtocolNumber, &wq, false) + if err != nil { + t.Fatalf("NewEndpoint(%d, %d, _): %s", udp.ProtocolNumber, header.IPv6ProtocolNumber, err) + } + defer ep.Close() + + bindAddr := tcpip.FullAddress{Port: utils.LocalPort} + if err := ep.Bind(bindAddr); err != nil { + t.Fatalf("ep.Bind(%#v): %s", bindAddr, err) + } + + memOpt := tcpip.MembershipOption{ + MulticastAddr: multicastAddr, + NIC: 0, + InterfaceAddr: utils.Ipv4Addr.Address, + } + + // Add membership should succeed when the interface index is specified, + // even if a bad interface address is specified. + addOpt := tcpip.AddMembershipOption(memOpt) + expErr := &tcpip.ErrInvalidOptionValue{} + if err := ep.SetSockOpt(&addOpt); err != expErr { + t.Fatalf("ep.SetSockOpt(&%#v): want %q, got %q", addOpt, expErr, err) + } +} diff --git a/pkg/tcpip/transport/internal/network/endpoint.go b/pkg/tcpip/transport/internal/network/endpoint.go index 5ccb41c91..c5a5b8f91 100644 --- a/pkg/tcpip/transport/internal/network/endpoint.go +++ b/pkg/tcpip/transport/internal/network/endpoint.go @@ -915,7 +915,7 @@ func (e *Endpoint) SetSockOpt(opt tcpip.SettableSocketOption) tcpip.Error { e.multicastAddr = addr case *tcpip.AddMembershipOption: - if !header.IsV4MulticastAddress(v.MulticastAddr) && !header.IsV6MulticastAddress(v.MulticastAddr) { + if !(header.IsV4MulticastAddress(v.MulticastAddr) && e.netProto == header.IPv4ProtocolNumber) && !(header.IsV6MulticastAddress(v.MulticastAddr) && e.netProto == header.IPv6ProtocolNumber) { return &tcpip.ErrInvalidOptionValue{} }