From dc5eed4f677d129be3c2f19eaccb8ea9a70fb750 Mon Sep 17 00:00:00 2001 From: Nicolas Lacasse Date: Thu, 25 Apr 2024 10:21:23 -0700 Subject: [PATCH] Fix check for IPPROTO_ICMP, since SocketType.proto it is not a bitmask. And add a comment above the socket type check, since that *is* a bitmask. This uncovered a bug in the hostnet handling of IP_MULTICAST_IF socket option. The kernel allows different-sized structures to be passed, but we were only forwarding the first 4 bytes. PiperOrigin-RevId: 628115391 --- pkg/sentry/socket/hostinet/sockopt.go | 2 +- .../linux/socket_ipv4_datagram_based_socket_unbound.cc | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/sentry/socket/hostinet/sockopt.go b/pkg/sentry/socket/hostinet/sockopt.go index 30b1945ff..10e60ff46 100644 --- a/pkg/sentry/socket/hostinet/sockopt.go +++ b/pkg/sentry/socket/hostinet/sockopt.go @@ -60,7 +60,7 @@ var SockOpts = []SockOpt{ {linux.SOL_IP, linux.IP_ADD_MEMBERSHIP, 0, false, true}, {linux.SOL_IP, linux.IP_DROP_MEMBERSHIP, 0, false, true}, {linux.SOL_IP, linux.IP_HDRINCL, sizeofInt32, true, true}, - {linux.SOL_IP, linux.IP_MULTICAST_IF, uint64(linux.SizeOfInetAddr), true, true}, + {linux.SOL_IP, linux.IP_MULTICAST_IF, 0 /* kernel allows multiple structures to be passed */, true, true}, {linux.SOL_IP, linux.IP_MULTICAST_LOOP, 0 /* can be 32-bit int or 8-bit uint */, true, true}, {linux.SOL_IP, linux.IP_MULTICAST_TTL, 0 /* can be 32-bit int or 8-bit uint */, true, true}, {linux.SOL_IP, linux.IP_PKTINFO, sizeofInt32, true, true}, diff --git a/test/syscalls/linux/socket_ipv4_datagram_based_socket_unbound.cc b/test/syscalls/linux/socket_ipv4_datagram_based_socket_unbound.cc index 71c4c50ea..942cf28b9 100644 --- a/test/syscalls/linux/socket_ipv4_datagram_based_socket_unbound.cc +++ b/test/syscalls/linux/socket_ipv4_datagram_based_socket_unbound.cc @@ -22,11 +22,13 @@ namespace gvisor { namespace testing { void IPv4DatagramBasedUnboundSocketTest::SetUp() { + // Require raw socket capability to create a raw socket. Note that + // SocketKind.type is a bitmask. if (GetParam().type & SOCK_RAW) { SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveRawIPSocketCapability())); } - if (GetParam().protocol & IPPROTO_ICMP) { + if (GetParam().protocol == IPPROTO_ICMP) { // By default, ICMP sockets cannot be created on Linux, even with root // privs. So we only run the test with gVisor and not hostinet, and even // then require CAP_NET_RAW.