github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/test/syscalls/linux/raw_socket_hdrincl.cc (about)

     1  // Copyright 2019 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 <linux/capability.h>
    16  #include <netinet/in.h>
    17  #include <netinet/ip.h>
    18  #include <netinet/ip_icmp.h>
    19  #include <netinet/udp.h>
    20  #include <poll.h>
    21  #include <sys/socket.h>
    22  #include <sys/types.h>
    23  #include <unistd.h>
    24  
    25  #include <algorithm>
    26  #include <cstring>
    27  
    28  #include "gtest/gtest.h"
    29  #include "absl/base/internal/endian.h"
    30  #include "test/syscalls/linux/socket_test_util.h"
    31  #include "test/syscalls/linux/unix_domain_socket_test_util.h"
    32  #include "test/util/capability_util.h"
    33  #include "test/util/file_descriptor.h"
    34  #include "test/util/test_util.h"
    35  
    36  namespace gvisor {
    37  namespace testing {
    38  
    39  namespace {
    40  
    41  // Tests for IPPROTO_RAW raw sockets, which implies IP_HDRINCL.
    42  class RawHDRINCL : public ::testing::Test {
    43   protected:
    44    // Creates a socket to be used in tests.
    45    void SetUp() override;
    46  
    47    // Closes the socket created by SetUp().
    48    void TearDown() override;
    49  
    50    // Returns a valid looback IP header with no payload.
    51    struct iphdr LoopbackHeader();
    52  
    53    // Fills in buf with an IP header, UDP header, and payload. Returns false if
    54    // buf_size isn't large enough to hold everything.
    55    bool FillPacket(char* buf, size_t buf_size, int port, const char* payload,
    56                    uint16_t payload_size);
    57  
    58    // The socket used for both reading and writing.
    59    int socket_;
    60  
    61    // The loopback address.
    62    struct sockaddr_in addr_;
    63  };
    64  
    65  void RawHDRINCL::SetUp() {
    66    if (!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_RAW))) {
    67      ASSERT_THAT(socket(AF_INET, SOCK_RAW, IPPROTO_RAW),
    68                  SyscallFailsWithErrno(EPERM));
    69      GTEST_SKIP();
    70    }
    71  
    72    ASSERT_THAT(socket_ = socket(AF_INET, SOCK_RAW, IPPROTO_RAW),
    73                SyscallSucceeds());
    74  
    75    addr_ = {};
    76  
    77    addr_.sin_port = IPPROTO_IP;
    78    addr_.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    79    addr_.sin_family = AF_INET;
    80  }
    81  
    82  void RawHDRINCL::TearDown() {
    83    // TearDown will be run even if we skip the test.
    84    if (ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_RAW))) {
    85      EXPECT_THAT(close(socket_), SyscallSucceeds());
    86    }
    87  }
    88  
    89  struct iphdr RawHDRINCL::LoopbackHeader() {
    90    struct iphdr hdr = {};
    91    hdr.ihl = 5;
    92    hdr.version = 4;
    93    hdr.tos = 0;
    94    hdr.tot_len = absl::gbswap_16(sizeof(hdr));
    95    hdr.id = 0;
    96    hdr.frag_off = 0;
    97    hdr.ttl = 7;
    98    hdr.protocol = 1;
    99    hdr.daddr = htonl(INADDR_LOOPBACK);
   100    // hdr.check is set by the network stack.
   101    // hdr.tot_len is set by the network stack.
   102    // hdr.saddr is set by the network stack.
   103    return hdr;
   104  }
   105  
   106  bool RawHDRINCL::FillPacket(char* buf, size_t buf_size, int port,
   107                              const char* payload, uint16_t payload_size) {
   108    if (buf_size < sizeof(struct iphdr) + sizeof(struct udphdr) + payload_size) {
   109      return false;
   110    }
   111  
   112    struct iphdr ip = LoopbackHeader();
   113    ip.protocol = IPPROTO_UDP;
   114  
   115    struct udphdr udp = {};
   116    udp.source = absl::gbswap_16(port);
   117    udp.dest = absl::gbswap_16(port);
   118    udp.len = absl::gbswap_16(sizeof(udp) + payload_size);
   119    udp.check = 0;
   120  
   121    memcpy(buf, reinterpret_cast<char*>(&ip), sizeof(ip));
   122    memcpy(buf + sizeof(ip), reinterpret_cast<char*>(&udp), sizeof(udp));
   123    memcpy(buf + sizeof(ip) + sizeof(udp), payload, payload_size);
   124  
   125    return true;
   126  }
   127  
   128  // We should be able to create multiple IPPROTO_RAW sockets. RawHDRINCL::Setup
   129  // creates the first one, so we only have to create one more here.
   130  TEST_F(RawHDRINCL, MultipleCreation) {
   131    int s2;
   132    ASSERT_THAT(s2 = socket(AF_INET, SOCK_RAW, IPPROTO_RAW), SyscallSucceeds());
   133  
   134    ASSERT_THAT(close(s2), SyscallSucceeds());
   135  }
   136  
   137  // Test that shutting down an unconnected socket fails.
   138  TEST_F(RawHDRINCL, FailShutdownWithoutConnect) {
   139    ASSERT_THAT(shutdown(socket_, SHUT_WR), SyscallFailsWithErrno(ENOTCONN));
   140    ASSERT_THAT(shutdown(socket_, SHUT_RD), SyscallFailsWithErrno(ENOTCONN));
   141  }
   142  
   143  // Test that listen() fails.
   144  TEST_F(RawHDRINCL, FailListen) {
   145    ASSERT_THAT(listen(socket_, 1), SyscallFailsWithErrno(ENOTSUP));
   146  }
   147  
   148  // Test that accept() fails.
   149  TEST_F(RawHDRINCL, FailAccept) {
   150    struct sockaddr saddr;
   151    socklen_t addrlen;
   152    ASSERT_THAT(accept(socket_, &saddr, &addrlen),
   153                SyscallFailsWithErrno(ENOTSUP));
   154  }
   155  
   156  // Test that the socket is writable immediately.
   157  TEST_F(RawHDRINCL, PollWritableImmediately) {
   158    struct pollfd pfd = {};
   159    pfd.fd = socket_;
   160    pfd.events = POLLOUT;
   161    ASSERT_THAT(RetryEINTR(poll)(&pfd, 1, 0), SyscallSucceedsWithValue(1));
   162  }
   163  
   164  // Test that the socket isn't readable.
   165  TEST_F(RawHDRINCL, NotReadable) {
   166    // Try to receive data with MSG_DONTWAIT, which returns immediately if there's
   167    // nothing to be read.
   168    char buf[117];
   169    ASSERT_THAT(RetryEINTR(recv)(socket_, buf, sizeof(buf), MSG_DONTWAIT),
   170                SyscallFailsWithErrno(EAGAIN));
   171  }
   172  
   173  // Test that we can connect() to a valid IP (loopback).
   174  TEST_F(RawHDRINCL, ConnectToLoopback) {
   175    ASSERT_THAT(connect(socket_, reinterpret_cast<struct sockaddr*>(&addr_),
   176                        sizeof(addr_)),
   177                SyscallSucceeds());
   178  }
   179  
   180  TEST_F(RawHDRINCL, SendWithoutConnectFails) {
   181    struct iphdr hdr = LoopbackHeader();
   182    ASSERT_THAT(send(socket_, &hdr, sizeof(hdr), 0),
   183                SyscallFailsWithErrno(EDESTADDRREQ));
   184  }
   185  
   186  // HDRINCL implies write-only. Verify that we can't read a packet sent to
   187  // loopback.
   188  TEST_F(RawHDRINCL, NotReadableAfterWrite) {
   189    ASSERT_THAT(connect(socket_, reinterpret_cast<struct sockaddr*>(&addr_),
   190                        sizeof(addr_)),
   191                SyscallSucceeds());
   192  
   193    // Construct a packet with an IP header, UDP header, and payload.
   194    constexpr char kPayload[] = "odst";
   195    char packet[sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(kPayload)];
   196    ASSERT_TRUE(FillPacket(packet, sizeof(packet), 40000 /* port */, kPayload,
   197                           sizeof(kPayload)));
   198  
   199    socklen_t addrlen = sizeof(addr_);
   200    ASSERT_NO_FATAL_FAILURE(
   201        sendto(socket_, reinterpret_cast<void*>(&packet), sizeof(packet), 0,
   202               reinterpret_cast<struct sockaddr*>(&addr_), addrlen));
   203  
   204    struct pollfd pfd = {};
   205    pfd.fd = socket_;
   206    pfd.events = POLLIN;
   207    ASSERT_THAT(RetryEINTR(poll)(&pfd, 1, 1000), SyscallSucceedsWithValue(0));
   208  }
   209  
   210  TEST_F(RawHDRINCL, WriteTooSmall) {
   211    ASSERT_THAT(connect(socket_, reinterpret_cast<struct sockaddr*>(&addr_),
   212                        sizeof(addr_)),
   213                SyscallSucceeds());
   214  
   215    // This is smaller than the size of an IP header.
   216    constexpr char kBuf[] = "JP5";
   217    ASSERT_THAT(send(socket_, kBuf, sizeof(kBuf), 0),
   218                SyscallFailsWithErrno(EINVAL));
   219  }
   220  
   221  // Bind to localhost.
   222  TEST_F(RawHDRINCL, BindToLocalhost) {
   223    ASSERT_THAT(
   224        bind(socket_, reinterpret_cast<struct sockaddr*>(&addr_), sizeof(addr_)),
   225        SyscallSucceeds());
   226  }
   227  
   228  // Bind to a different address.
   229  TEST_F(RawHDRINCL, BindToInvalid) {
   230    struct sockaddr_in bind_addr = {};
   231    bind_addr.sin_family = AF_INET;
   232    bind_addr.sin_addr = {1};  // 1.0.0.0 - An address that we can't bind to.
   233    ASSERT_THAT(bind(socket_, reinterpret_cast<struct sockaddr*>(&bind_addr),
   234                     sizeof(bind_addr)),
   235                SyscallFailsWithErrno(EADDRNOTAVAIL));
   236  }
   237  
   238  // Send and receive a packet.
   239  TEST_F(RawHDRINCL, SendAndReceive) {
   240    int port = 40000;
   241    if (!IsRunningOnGvisor()) {
   242      port = static_cast<short>(ASSERT_NO_ERRNO_AND_VALUE(
   243          PortAvailable(0, AddressFamily::kIpv4, SocketType::kUdp, false)));
   244    }
   245  
   246    // IPPROTO_RAW sockets are write-only. We'll have to open another socket to
   247    // read what we write.
   248    FileDescriptor udp_sock =
   249        ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_RAW, IPPROTO_UDP));
   250  
   251    // Construct a packet with an IP header, UDP header, and payload.
   252    constexpr char kPayload[] = "toto";
   253    char packet[sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(kPayload)];
   254    ASSERT_TRUE(
   255        FillPacket(packet, sizeof(packet), port, kPayload, sizeof(kPayload)));
   256  
   257    socklen_t addrlen = sizeof(addr_);
   258    ASSERT_NO_FATAL_FAILURE(sendto(socket_, &packet, sizeof(packet), 0,
   259                                   reinterpret_cast<struct sockaddr*>(&addr_),
   260                                   addrlen));
   261  
   262    // Receive the payload.
   263    char recv_buf[sizeof(packet)];
   264    struct sockaddr_in src;
   265    socklen_t src_size = sizeof(src);
   266    ASSERT_THAT(recvfrom(udp_sock.get(), recv_buf, sizeof(recv_buf), 0,
   267                         reinterpret_cast<struct sockaddr*>(&src), &src_size),
   268                SyscallSucceedsWithValue(sizeof(packet)));
   269    EXPECT_EQ(
   270        memcmp(kPayload, recv_buf + sizeof(struct iphdr) + sizeof(struct udphdr),
   271               sizeof(kPayload)),
   272        0);
   273    // The network stack should have set the source address.
   274    EXPECT_EQ(src.sin_family, AF_INET);
   275    EXPECT_EQ(absl::gbswap_32(src.sin_addr.s_addr), INADDR_LOOPBACK);
   276    // The packet ID should not be 0, as the packet has DF=0.
   277    struct iphdr* iphdr = reinterpret_cast<struct iphdr*>(recv_buf);
   278    EXPECT_NE(iphdr->id, 0);
   279  }
   280  
   281  // Send and receive a packet where the sendto address is not the same as the
   282  // provided destination.
   283  TEST_F(RawHDRINCL, SendAndReceiveDifferentAddress) {
   284    int port = 40000;
   285    if (!IsRunningOnGvisor()) {
   286      port = static_cast<short>(ASSERT_NO_ERRNO_AND_VALUE(
   287          PortAvailable(0, AddressFamily::kIpv4, SocketType::kUdp, false)));
   288    }
   289  
   290    // IPPROTO_RAW sockets are write-only. We'll have to open another socket to
   291    // read what we write.
   292    FileDescriptor udp_sock =
   293        ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_RAW, IPPROTO_UDP));
   294  
   295    // Construct a packet with an IP header, UDP header, and payload.
   296    constexpr char kPayload[] = "toto";
   297    char packet[sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(kPayload)];
   298    ASSERT_TRUE(
   299        FillPacket(packet, sizeof(packet), port, kPayload, sizeof(kPayload)));
   300    // Overwrite the IP destination address with an IP we can't get to.
   301    constexpr int32_t kUnreachable = 42;
   302    struct iphdr iphdr = {};
   303    memcpy(&iphdr, packet, sizeof(iphdr));
   304    iphdr.daddr = kUnreachable;
   305    memcpy(packet, &iphdr, sizeof(iphdr));
   306  
   307    // Send to localhost via loopback.
   308    socklen_t addrlen = sizeof(addr_);
   309    ASSERT_NO_FATAL_FAILURE(sendto(socket_, &packet, sizeof(packet), 0,
   310                                   reinterpret_cast<struct sockaddr*>(&addr_),
   311                                   addrlen));
   312  
   313    // Receive the payload. Despite an unreachable destination address, sendto
   314    // should have sent the packet through loopback.
   315    char recv_buf[sizeof(packet)];
   316    struct sockaddr_in src;
   317    socklen_t src_size = sizeof(src);
   318    ASSERT_THAT(recvfrom(udp_sock.get(), recv_buf, sizeof(recv_buf), 0,
   319                         reinterpret_cast<struct sockaddr*>(&src), &src_size),
   320                SyscallSucceedsWithValue(sizeof(packet)));
   321    EXPECT_EQ(
   322        memcmp(kPayload, recv_buf + sizeof(struct iphdr) + sizeof(struct udphdr),
   323               sizeof(kPayload)),
   324        0);
   325    // The network stack should have set the source address.
   326    EXPECT_EQ(src.sin_family, AF_INET);
   327    EXPECT_EQ(absl::gbswap_32(src.sin_addr.s_addr), INADDR_LOOPBACK);
   328    // The packet ID should not be 0, as the packet has DF=0.
   329    struct iphdr recv_iphdr = {};
   330    memcpy(&recv_iphdr, recv_buf, sizeof(recv_iphdr));
   331    EXPECT_NE(recv_iphdr.id, 0);
   332    // The destination address is kUnreachable despite arriving via loopback.
   333    EXPECT_EQ(recv_iphdr.daddr, kUnreachable);
   334  }
   335  
   336  // Send and receive a packet w/ the IP_HDRINCL option set.
   337  TEST_F(RawHDRINCL, SendAndReceiveIPHdrIncl) {
   338    int port = 40000;
   339    if (!IsRunningOnGvisor()) {
   340      port = static_cast<short>(ASSERT_NO_ERRNO_AND_VALUE(
   341          PortAvailable(0, AddressFamily::kIpv4, SocketType::kUdp, false)));
   342    }
   343  
   344    FileDescriptor recv_sock =
   345        ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_RAW, IPPROTO_UDP));
   346  
   347    FileDescriptor send_sock =
   348        ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_RAW, IPPROTO_UDP));
   349  
   350    // Enable IP_HDRINCL option so that we can build and send w/ an IP
   351    // header.
   352    constexpr int kSockOptOn = 1;
   353    ASSERT_THAT(setsockopt(send_sock.get(), SOL_IP, IP_HDRINCL, &kSockOptOn,
   354                           sizeof(kSockOptOn)),
   355                SyscallSucceeds());
   356    // This is not strictly required but we do it to make sure that setting
   357    // IP_HDRINCL on a non IPPROTO_RAW socket does not prevent it from receiving
   358    // packets.
   359    ASSERT_THAT(setsockopt(recv_sock.get(), SOL_IP, IP_HDRINCL, &kSockOptOn,
   360                           sizeof(kSockOptOn)),
   361                SyscallSucceeds());
   362  
   363    // Construct a packet with an IP header, UDP header, and payload.
   364    constexpr char kPayload[] = "toto";
   365    char packet[sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(kPayload)];
   366    ASSERT_TRUE(
   367        FillPacket(packet, sizeof(packet), port, kPayload, sizeof(kPayload)));
   368  
   369    socklen_t addrlen = sizeof(addr_);
   370    ASSERT_NO_FATAL_FAILURE(sendto(send_sock.get(), &packet, sizeof(packet), 0,
   371                                   reinterpret_cast<struct sockaddr*>(&addr_),
   372                                   addrlen));
   373  
   374    // Receive the payload.
   375    char recv_buf[sizeof(packet)];
   376    struct sockaddr_in src;
   377    socklen_t src_size = sizeof(src);
   378    ASSERT_THAT(recvfrom(recv_sock.get(), recv_buf, sizeof(recv_buf), 0,
   379                         reinterpret_cast<struct sockaddr*>(&src), &src_size),
   380                SyscallSucceedsWithValue(sizeof(packet)));
   381    EXPECT_EQ(
   382        memcmp(kPayload, recv_buf + sizeof(struct iphdr) + sizeof(struct udphdr),
   383               sizeof(kPayload)),
   384        0);
   385    // The network stack should have set the source address.
   386    EXPECT_EQ(src.sin_family, AF_INET);
   387    EXPECT_EQ(absl::gbswap_32(src.sin_addr.s_addr), INADDR_LOOPBACK);
   388    struct iphdr iphdr = {};
   389    memcpy(&iphdr, recv_buf, sizeof(iphdr));
   390    EXPECT_NE(iphdr.id, 0);
   391  
   392    // Also verify that the packet we just sent was not delivered to the
   393    // IPPROTO_RAW socket.
   394    {
   395      char recv_buf[sizeof(packet)];
   396      struct sockaddr_in src;
   397      socklen_t src_size = sizeof(src);
   398      ASSERT_THAT(recvfrom(socket_, recv_buf, sizeof(recv_buf), MSG_DONTWAIT,
   399                           reinterpret_cast<struct sockaddr*>(&src), &src_size),
   400                  SyscallFailsWithErrno(EAGAIN));
   401    }
   402  }
   403  
   404  }  // namespace
   405  
   406  }  // namespace testing
   407  }  // namespace gvisor