gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/packet_socket.cc (about)

     1  // Copyright 2021 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  #include <net/if.h>
    16  #include <netinet/if_ether.h>
    17  #include <netpacket/packet.h>
    18  #include <poll.h>
    19  #include <sys/socket.h>
    20  #include <sys/types.h>
    21  
    22  #include <cerrno>
    23  #include <limits>
    24  
    25  #include "gmock/gmock.h"
    26  #include "gtest/gtest.h"
    27  #include "test/syscalls/linux/ip_socket_test_util.h"
    28  #include "test/util/capability_util.h"
    29  #include "test/util/file_descriptor.h"
    30  #include "test/util/socket_util.h"
    31  #include "test/util/test_util.h"
    32  
    33  namespace gvisor {
    34  namespace testing {
    35  
    36  namespace {
    37  
    38  using ::testing::AnyOf;
    39  using ::testing::Combine;
    40  using ::testing::Eq;
    41  using ::testing::Values;
    42  
    43  class PacketSocketCreationTest
    44      : public ::testing::TestWithParam<std::tuple<int, int>> {
    45   protected:
    46    void SetUp() override {
    47      if (!ASSERT_NO_ERRNO_AND_VALUE(HavePacketSocketCapability())) {
    48        const auto [type, protocol] = GetParam();
    49        ASSERT_THAT(socket(AF_PACKET, type, htons(protocol)),
    50                    SyscallFailsWithErrno(EPERM));
    51        GTEST_SKIP() << "Missing packet socket capability";
    52      }
    53    }
    54  };
    55  
    56  TEST_P(PacketSocketCreationTest, Create) {
    57    const auto [type, protocol] = GetParam();
    58    FileDescriptor fd =
    59        ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_PACKET, type, htons(protocol)));
    60    EXPECT_GE(fd.get(), 0);
    61  }
    62  
    63  INSTANTIATE_TEST_SUITE_P(AllPacketSocketTests, PacketSocketCreationTest,
    64                           Combine(Values(SOCK_DGRAM, SOCK_RAW),
    65                                   Values(0, 1, 255, ETH_P_IP, ETH_P_IPV6,
    66                                          std::numeric_limits<uint16_t>::max())));
    67  
    68  class PacketSocketTest : public ::testing::TestWithParam<int> {
    69   protected:
    70    void SetUp() override {
    71      if (!ASSERT_NO_ERRNO_AND_VALUE(HavePacketSocketCapability())) {
    72        ASSERT_THAT(socket(AF_PACKET, GetParam(), 0),
    73                    SyscallFailsWithErrno(EPERM));
    74        GTEST_SKIP() << "Missing packet socket capability";
    75      }
    76  
    77      socket_ = ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_PACKET, GetParam(), 0));
    78    }
    79  
    80    FileDescriptor socket_;
    81  };
    82  
    83  TEST_P(PacketSocketTest, GetSockName) {
    84    {
    85      // First check the local address of an unbound packet socket.
    86      sockaddr_ll addr;
    87      socklen_t addrlen = sizeof(addr);
    88      ASSERT_THAT(getsockname(socket_.get(), reinterpret_cast<sockaddr*>(&addr),
    89                              &addrlen),
    90                  SyscallSucceeds());
    91      // sockaddr_ll ends with an 8 byte physical address field, but only the
    92      // bytes that are used in the sockaddr_ll.sll_addr field are included in the
    93      // address length. Seems Linux used to return the size of sockaddr_ll, but
    94      // https://github.com/torvalds/linux/commit/0fb375fb9b93b7d822debc6a734052337ccfdb1f
    95      // changed things to only return `sizeof(sockaddr_ll) + sll.sll_addr`.
    96      ASSERT_THAT(addrlen, AnyOf(Eq(sizeof(addr)),
    97                                 Eq(sizeof(addr) - sizeof(addr.sll_addr))));
    98      EXPECT_EQ(addr.sll_family, AF_PACKET);
    99      EXPECT_EQ(addr.sll_ifindex, 0);
   100  
   101      if (IsRunningOnGvisor() && !IsRunningWithHostinet() &&
   102          GvisorPlatform() != Platform::kFuchsia) {
   103        // TODO(https://gvisor.dev/issue/6530): Do not assume all interfaces have
   104        // an ethernet address.
   105        EXPECT_EQ(addr.sll_halen, ETH_ALEN);
   106      } else {
   107        EXPECT_EQ(addr.sll_halen, 0);
   108      }
   109      EXPECT_EQ(ntohs(addr.sll_protocol), 0);
   110      EXPECT_EQ(addr.sll_hatype, 0);
   111    }
   112    // Next we bind the socket to loopback before checking the local address.
   113    const sockaddr_ll bind_addr = {
   114        .sll_family = AF_PACKET,
   115        .sll_protocol = htons(ETH_P_IP),
   116        .sll_ifindex = ASSERT_NO_ERRNO_AND_VALUE(GetLoopbackIndex()),
   117    };
   118    ASSERT_THAT(bind(socket_.get(), reinterpret_cast<const sockaddr*>(&bind_addr),
   119                     sizeof(bind_addr)),
   120                SyscallSucceeds());
   121    {
   122      sockaddr_ll addr;
   123      socklen_t addrlen = sizeof(addr);
   124      ASSERT_THAT(getsockname(socket_.get(), reinterpret_cast<sockaddr*>(&addr),
   125                              &addrlen),
   126                  SyscallSucceeds());
   127      ASSERT_THAT(addrlen,
   128                  AnyOf(Eq(sizeof(addr)),
   129                        Eq(sizeof(addr) - sizeof(addr.sll_addr) + ETH_ALEN)));
   130      EXPECT_EQ(addr.sll_family, AF_PACKET);
   131      EXPECT_EQ(addr.sll_ifindex, bind_addr.sll_ifindex);
   132      EXPECT_EQ(addr.sll_halen, ETH_ALEN);
   133      // Bound to loopback which has the all zeroes address.
   134      for (int i = 0; i < addr.sll_halen; ++i) {
   135        EXPECT_EQ(addr.sll_addr[i], 0) << "byte mismatch @ idx = " << i;
   136      }
   137      EXPECT_EQ(ntohs(addr.sll_protocol), htons(addr.sll_protocol));
   138      if (IsRunningOnGvisor() && !IsRunningWithHostinet() &&
   139          GvisorPlatform() != Platform::kFuchsia) {
   140        // TODO(https://gvisor.dev/issue/6621): Support populating sll_hatype.
   141        EXPECT_EQ(addr.sll_hatype, 0);
   142      } else {
   143        EXPECT_EQ(addr.sll_hatype, ARPHRD_LOOPBACK);
   144      }
   145    }
   146  }
   147  
   148  // Expects that a packet can be read from the given packet socket that contains
   149  // a UDP packet whose source and destination port match the one in the given
   150  // address, and whose payload matches the expected payload.
   151  //
   152  // On success, writes the link-layer source address for the packet into
   153  // the provided output parameter (if it is non-null).
   154  void ExpectReceiveOnPacketSocket(FileDescriptor& socket,
   155                                   bool ethernet_header_included,
   156                                   const sockaddr_in& expected_udp_addr,
   157                                   const uint64_t expected_udp_payload,
   158                                   sockaddr_ll* src_out = nullptr) {
   159    // Declare each section of the packet as a separate stack variable in order
   160    // to ensure all sections are 8-byte aligned.
   161    ethhdr eth;
   162    iphdr ip;
   163    udphdr udp;
   164    uint64_t payload;
   165    char unused;
   166  
   167    constexpr size_t kStorageLen =
   168        sizeof(eth) + sizeof(ip) + sizeof(udp) + sizeof(payload) + sizeof(unused);
   169    char storage[kStorageLen];
   170  
   171    sockaddr_ll src;
   172    socklen_t src_len = sizeof(src);
   173  
   174    char* buf = storage;
   175    size_t buflen = kStorageLen;
   176    auto advance_buf = [&buf, &buflen](size_t amount) {
   177      buf += amount;
   178      buflen -= amount;
   179    };
   180    size_t expected_read_len = buflen - sizeof(unused);
   181    if (!ethernet_header_included) {
   182      advance_buf(sizeof(eth));
   183      expected_read_len -= sizeof(eth);
   184    }
   185  
   186    iovec received_iov = {
   187        .iov_base = buf,
   188        .iov_len = buflen,
   189    };
   190    msghdr received_msg = {
   191        .msg_name = &src,
   192        .msg_namelen = src_len,
   193        .msg_iov = &received_iov,
   194        .msg_iovlen = 1,
   195    };
   196  
   197    // NB: poll indefinitely on Fuchsia to avoid timing out in Infra.
   198    int timeout = GvisorPlatform() == Platform::kFuchsia ? -1 : 1;
   199    ASSERT_THAT(RecvMsgTimeout(socket.get(), &received_msg, timeout),
   200                IsPosixErrorOkAndHolds(expected_read_len));
   201  
   202    // sockaddr_ll ends with an 8 byte physical address field, but ethernet
   203    // addresses only use 6 bytes. Linux used to return sizeof(sockaddr_ll)-2
   204    // here, but returns sizeof(sockaddr_ll) since
   205    // https://github.com/torvalds/linux/commit/b2cf86e1563e33a14a1c69b3e508d15dc12f804c.
   206    ASSERT_THAT(received_msg.msg_namelen,
   207                AnyOf(Eq(sizeof(src)),
   208                      Eq(sizeof(src) - sizeof(src.sll_addr) + ETH_ALEN)));
   209    EXPECT_EQ(src.sll_family, AF_PACKET);
   210    EXPECT_EQ(src.sll_ifindex, ASSERT_NO_ERRNO_AND_VALUE(GetLoopbackIndex()));
   211    EXPECT_EQ(src.sll_halen, ETH_ALEN);
   212    EXPECT_EQ(ntohs(src.sll_protocol), ETH_P_IP);
   213    // This came from the loopback device, so the address is all 0s.
   214    constexpr uint8_t allZeroesMAC[ETH_ALEN] = {};
   215    EXPECT_EQ(memcmp(src.sll_addr, allZeroesMAC, sizeof(allZeroesMAC)), 0);
   216  
   217    if (ethernet_header_included) {
   218      memcpy(&eth, buf, sizeof(eth));
   219      EXPECT_EQ(memcmp(eth.h_dest, allZeroesMAC, sizeof(allZeroesMAC)), 0);
   220      EXPECT_EQ(memcmp(eth.h_source, allZeroesMAC, sizeof(allZeroesMAC)), 0);
   221      EXPECT_EQ(ntohs(eth.h_proto), ETH_P_IP);
   222      advance_buf(sizeof(eth));
   223    }
   224  
   225    // IHL hold the size of the header in 4 byte units.
   226    memcpy(&ip, buf, sizeof(ip));
   227    EXPECT_EQ(ip.ihl, sizeof(iphdr) / 4);
   228    EXPECT_EQ(ip.version, IPVERSION);
   229    const uint16_t ip_pkt_size = sizeof(ip) + sizeof(udp) + sizeof(payload);
   230    EXPECT_EQ(ntohs(ip.tot_len), ip_pkt_size);
   231    EXPECT_EQ(ip.protocol, IPPROTO_UDP);
   232    EXPECT_EQ(ntohl(ip.daddr), INADDR_LOOPBACK);
   233    EXPECT_EQ(ntohl(ip.saddr), INADDR_LOOPBACK);
   234    advance_buf(sizeof(ip));
   235  
   236    memcpy(&udp, buf, sizeof(udp));
   237    EXPECT_EQ(udp.source, expected_udp_addr.sin_port);
   238    EXPECT_EQ(udp.dest, expected_udp_addr.sin_port);
   239    EXPECT_EQ(ntohs(udp.len), ip_pkt_size - sizeof(ip));
   240    advance_buf(sizeof(udp));
   241  
   242    memcpy(&payload, buf, sizeof(payload));
   243    EXPECT_EQ(payload, expected_udp_payload);
   244    if (src_out) {
   245      *src_out = src;
   246    }
   247  }
   248  
   249  TEST_P(PacketSocketTest, RebindProtocol) {
   250    const bool kEthHdrIncluded = GetParam() == SOCK_RAW;
   251  
   252    sockaddr_in udp_bind_addr = {
   253        .sin_family = AF_INET,
   254        .sin_addr = {.s_addr = htonl(INADDR_LOOPBACK)},
   255    };
   256  
   257    FileDescriptor udp_sock =
   258        ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_DGRAM, 0));
   259    {
   260      // Bind the socket so that we have something to send packets to.
   261      //
   262      // If we didn't do this, the UDP packets we send will be responded to with
   263      // ICMP Destination Port Unreachable errors.
   264      ASSERT_THAT(
   265          bind(udp_sock.get(), reinterpret_cast<const sockaddr*>(&udp_bind_addr),
   266               sizeof(udp_bind_addr)),
   267          SyscallSucceeds());
   268      socklen_t addrlen = sizeof(udp_bind_addr);
   269      ASSERT_THAT(
   270          getsockname(udp_sock.get(), reinterpret_cast<sockaddr*>(&udp_bind_addr),
   271                      &addrlen),
   272          SyscallSucceeds());
   273      ASSERT_THAT(addrlen, sizeof(udp_bind_addr));
   274    }
   275  
   276    const int loopback_index = ASSERT_NO_ERRNO_AND_VALUE(GetLoopbackIndex());
   277  
   278    auto send_udp_message = [&](const uint64_t v) {
   279      ASSERT_THAT(
   280          sendto(udp_sock.get(), reinterpret_cast<const char*>(&v), sizeof(v),
   281                 0 /* flags */, reinterpret_cast<const sockaddr*>(&udp_bind_addr),
   282                 sizeof(udp_bind_addr)),
   283          SyscallSucceeds());
   284  
   285      // Make sure the payload has been delivered (in case of asynchronous
   286      // delivery).
   287      char buf[sizeof(v)];
   288      // NB: poll indefinitely on Fuchsia to avoid timing out in Infra.
   289      int timeout = GvisorPlatform() == Platform::kFuchsia ? -1 : 1;
   290      EXPECT_THAT(RecvTimeout(udp_sock.get(), buf, sizeof(v), timeout),
   291                  IsPosixErrorOkAndHolds(sizeof(v)));
   292      ASSERT_EQ(*reinterpret_cast<uint64_t*>(buf), v);
   293    };
   294  
   295    auto bind_to_network_protocol = [&](uint16_t protocol) {
   296      const sockaddr_ll packet_bind_addr = {
   297          .sll_family = AF_PACKET,
   298          .sll_protocol = htons(protocol),
   299          .sll_ifindex = loopback_index,
   300      };
   301  
   302      ASSERT_THAT(bind(socket_.get(),
   303                       reinterpret_cast<const sockaddr*>(&packet_bind_addr),
   304                       sizeof(packet_bind_addr)),
   305                  SyscallSucceeds());
   306    };
   307  
   308    // The packet socket is not bound to IPv4 so we should not receive the sent
   309    // message.
   310    uint64_t counter = 0;
   311    ASSERT_NO_FATAL_FAILURE(send_udp_message(++counter));
   312  
   313    // Bind to IPv4 and expect to receive the UDP packet we send after binding.
   314    ASSERT_NO_FATAL_FAILURE(bind_to_network_protocol(ETH_P_IP));
   315    ASSERT_NO_FATAL_FAILURE(send_udp_message(++counter));
   316    ASSERT_NO_FATAL_FAILURE(ExpectReceiveOnPacketSocket(socket_, kEthHdrIncluded,
   317                                                        udp_bind_addr, counter));
   318  
   319    // Bind the packet socket to a random protocol.
   320    ASSERT_NO_FATAL_FAILURE(bind_to_network_protocol(255));
   321    ASSERT_NO_FATAL_FAILURE(send_udp_message(++counter));
   322  
   323    // Bind back to IPv4 and expect to the UDP packet we send after binding
   324    // back to IPv4.
   325    ASSERT_NO_FATAL_FAILURE(bind_to_network_protocol(ETH_P_IP));
   326    ASSERT_NO_FATAL_FAILURE(send_udp_message(++counter));
   327    ASSERT_NO_FATAL_FAILURE(ExpectReceiveOnPacketSocket(socket_, kEthHdrIncluded,
   328                                                        udp_bind_addr, counter));
   329  
   330    // A zero valued protocol number should not change the bound network protocol.
   331    ASSERT_NO_FATAL_FAILURE(bind_to_network_protocol(0));
   332    ASSERT_NO_FATAL_FAILURE(send_udp_message(++counter));
   333    ASSERT_NO_FATAL_FAILURE(ExpectReceiveOnPacketSocket(socket_, kEthHdrIncluded,
   334                                                        udp_bind_addr, counter));
   335  }
   336  
   337  // Receive sent frames when bound to ETH_P_ALL.
   338  TEST_P(PacketSocketTest, ReceiveSentBoundToProtocolAll) {
   339    // If a packet socket is bound to the loopback interface with protocol
   340    // ETH_P_ALL, it should receive a frame that is sent twice: once on sending
   341    // and again on reception.
   342  
   343    sockaddr_in udp_bind_addr = {
   344        .sin_family = AF_INET,
   345        .sin_addr = {.s_addr = htonl(INADDR_LOOPBACK)},
   346    };
   347  
   348    FileDescriptor udp_sock =
   349        ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_DGRAM, 0));
   350    {
   351      // Bind the socket so that we have something to send packets to.
   352      //
   353      // If we didn't do this, the UDP packets we send will be responded to with
   354      // ICMP Destination Port Unreachable errors.
   355      ASSERT_THAT(
   356          bind(udp_sock.get(), reinterpret_cast<const sockaddr*>(&udp_bind_addr),
   357               sizeof(udp_bind_addr)),
   358          SyscallSucceeds());
   359      socklen_t addrlen = sizeof(udp_bind_addr);
   360      ASSERT_THAT(
   361          getsockname(udp_sock.get(), reinterpret_cast<sockaddr*>(&udp_bind_addr),
   362                      &addrlen),
   363          SyscallSucceeds());
   364      ASSERT_THAT(addrlen, sizeof(udp_bind_addr));
   365      ASSERT_NE(udp_bind_addr.sin_port, 0);
   366    }
   367  
   368    // Bind the packet socket to the loopback interface with ETH_P_ALL.
   369    const struct sockaddr_ll bind_addr = {
   370        .sll_family = AF_PACKET,
   371        .sll_protocol = htons(ETH_P_ALL),
   372        .sll_ifindex = ASSERT_NO_ERRNO_AND_VALUE(GetLoopbackIndex()),
   373        .sll_halen = ETH_ALEN,
   374    };
   375    ASSERT_THAT(bind(socket_.get(), reinterpret_cast<const sockaddr*>(&bind_addr),
   376                     sizeof(bind_addr)),
   377                SyscallSucceeds());
   378  
   379    const uint64_t kContents = 0xAAAAAAAAAAAAAAAA;
   380  
   381    // Send to the same UDP socket so we don't interfere with other tests.
   382    ASSERT_THAT(sendto(udp_sock.get(), &kContents, sizeof(kContents), 0,
   383                       reinterpret_cast<const struct sockaddr*>(&udp_bind_addr),
   384                       sizeof(udp_bind_addr)),
   385                SyscallSucceeds());
   386  
   387    const bool kExpectEthernetHeader = GetParam() == SOCK_RAW;
   388    sockaddr_ll src_addr;
   389  
   390    // Receive the outgoing frame.
   391    ExpectReceiveOnPacketSocket(socket_, kExpectEthernetHeader, udp_bind_addr,
   392                                kContents, &src_addr);
   393    ASSERT_EQ(src_addr.sll_pkttype, PACKET_OUTGOING);
   394  
   395    // Then receive the incoming frame.
   396    ExpectReceiveOnPacketSocket(socket_, kExpectEthernetHeader, udp_bind_addr,
   397                                kContents, &src_addr);
   398    ASSERT_EQ(src_addr.sll_pkttype, PACKET_HOST);
   399  }
   400  
   401  // Verify that the ifindex field of sockaddr_ll must be provided when calling
   402  // sendto on a packet socket (e.g. the interface cannot be inferred from the
   403  // bound address).
   404  TEST_P(PacketSocketTest, SendWithoutTargetDevice) {
   405    if (IsRunningOnGvisor() && GvisorPlatform() != Platform::kFuchsia) {
   406      GTEST_SKIP() << "gVisor does not support sending on packet sockets.";
   407    }
   408  
   409    const uint16_t kArbitraryProtocol = 0xFFFF;
   410  
   411    // Bind the packet socket to the loopback interface. Despite this, subsequent
   412    // sends will require the interface be specified.
   413    const struct sockaddr_ll bind_addr = {
   414        .sll_family = AF_PACKET,
   415        .sll_protocol = htons(kArbitraryProtocol),
   416        .sll_ifindex = ASSERT_NO_ERRNO_AND_VALUE(GetLoopbackIndex()),
   417        .sll_halen = ETH_ALEN,
   418    };
   419    ASSERT_THAT(bind(socket_.get(), reinterpret_cast<const sockaddr*>(&bind_addr),
   420                     sizeof(bind_addr)),
   421                SyscallSucceeds());
   422  
   423    // Prepare a send buffer with a valid Ethernet header.
   424    // This enables sending with SOCK_RAW, and is inconsequential for SOCK_DGRAM.
   425    const uint64_t kContents = 0xAAAAAAAAAAAAAAAA;
   426    struct ethhdr eth = {};
   427    eth.h_proto = htons(kArbitraryProtocol);
   428    char send_buf[sizeof(eth) + sizeof(kContents)];
   429    memcpy(send_buf, &eth, sizeof(eth));
   430    memcpy(send_buf + sizeof(ethhdr), &kContents, sizeof(kContents));
   431  
   432    // Send to a valid address.
   433    const struct sockaddr_ll valid_addr = {
   434        .sll_family = AF_PACKET,
   435        .sll_protocol = htons(kArbitraryProtocol),
   436        .sll_ifindex = ASSERT_NO_ERRNO_AND_VALUE(GetLoopbackIndex()),
   437        .sll_halen = ETH_ALEN,
   438    };
   439    ASSERT_THAT(sendto(socket_.get(), send_buf, sizeof(send_buf), 0,
   440                       reinterpret_cast<const struct sockaddr*>(&valid_addr),
   441                       sizeof(valid_addr)),
   442                SyscallSucceedsWithValue(sizeof(send_buf)));
   443  
   444    // Attempt to send without specifying the interface.
   445    const struct sockaddr_ll no_dev_addr = {
   446        .sll_family = AF_PACKET,
   447        .sll_protocol = htons(kArbitraryProtocol),
   448        .sll_ifindex = 0,
   449        .sll_halen = ETH_ALEN,
   450    };
   451    ASSERT_THAT(sendto(socket_.get(), send_buf, sizeof(send_buf), 0,
   452                       reinterpret_cast<const struct sockaddr*>(&no_dev_addr),
   453                       sizeof(no_dev_addr)),
   454                SyscallFailsWithErrno(ENXIO));
   455  }
   456  
   457  INSTANTIATE_TEST_SUITE_P(AllPacketSocketTests, PacketSocketTest,
   458                           Values(SOCK_DGRAM, SOCK_RAW));
   459  
   460  }  // namespace
   461  
   462  }  // namespace testing
   463  }  // namespace gvisor