gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/runner/setup_container/setup_container.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 <linux/capability.h>
    16  #include <sys/ioctl.h>
    17  #include <unistd.h>
    18  
    19  #include "test/syscalls/linux/socket_netlink_util.h"
    20  #include "test/util/capability_util.h"
    21  #include "test/util/posix_error.h"
    22  #include "test/util/socket_util.h"
    23  
    24  namespace gvisor {
    25  namespace testing {
    26  
    27  // SetupContainer sets up the networking settings in the current container.
    28  PosixError SetupContainer() {
    29    const PosixErrorOr<bool> have_net_admin = HaveCapability(CAP_NET_ADMIN);
    30    if (!have_net_admin.ok()) {
    31      std::cerr << "Cannot determine if we have CAP_NET_ADMIN." << std::endl;
    32      return have_net_admin.error();
    33    }
    34    if (have_net_admin.ValueOrDie()) {
    35      PosixErrorOr<FileDescriptor> sockfd = Socket(AF_INET, SOCK_DGRAM, 0);
    36      if (!sockfd.ok()) {
    37        std::cerr << "Cannot open socket." << std::endl;
    38        return sockfd.error();
    39      }
    40      int sock = sockfd.ValueOrDie().get();
    41      struct ifreq ifr = {};
    42      strncpy(ifr.ifr_name, "lo", IFNAMSIZ);
    43      if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) {
    44        std::cerr << "Cannot get 'lo' flags: " << strerror(errno) << std::endl;
    45        return PosixError(errno);
    46      }
    47      if ((ifr.ifr_flags & IFF_UP) == 0) {
    48        ifr.ifr_flags |= IFF_UP;
    49        if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) {
    50          std::cerr << "Cannot set 'lo' as UP: " << strerror(errno) << std::endl;
    51          return PosixError(errno);
    52        }
    53      }
    54    } else {
    55      std::cerr
    56          << "Capability CAP_NET_ADMIN not granted, so cannot bring up "
    57          << "'lo' interface. This may cause host-network-related tests to fail."
    58          << std::endl;
    59    }
    60    return NoError();
    61  }
    62  
    63  }  // namespace testing
    64  }  // namespace gvisor
    65  
    66  using ::gvisor::testing::SetupContainer;
    67  
    68  // Binary setup_container initializes the container environment in which tests
    69  // with container=True will run, then execs the actual test binary.
    70  // Usage:
    71  //   ./setup_container test_binary [arguments forwarded to test_binary...]
    72  int main(int argc, char *argv[], char *envp[]) {
    73    if (!SetupContainer().ok()) {
    74      return 1;
    75    }
    76    if (argc < 2) {
    77      std::cerr << "Must provide arguments to exec." << std::endl;
    78      return 2;
    79    }
    80    if (execve(argv[1], &argv[1], envp) == -1) {
    81      std::cerr << "execv returned errno " << errno << std::endl;
    82      return 1;
    83    }
    84  }