github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/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/syscalls/linux/socket_test_util.h"
    21  #include "test/util/capability_util.h"
    22  #include "test/util/posix_error.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() && !IsRunningOnGvisor()) {
    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    }
    55    return NoError();
    56  }
    57  
    58  }  // namespace testing
    59  }  // namespace gvisor
    60  
    61  using ::gvisor::testing::SetupContainer;
    62  
    63  // Binary setup_container initializes the container environment in which tests
    64  // with container=True will run, then execs the actual test binary.
    65  // Usage:
    66  //   ./setup_container test_binary [arguments forwarded to test_binary...]
    67  int main(int argc, char *argv[], char *envp[]) {
    68    if (!SetupContainer().ok()) {
    69      return 1;
    70    }
    71    if (argc < 2) {
    72      std::cerr << "Must provide arguments to exec." << std::endl;
    73      return 2;
    74    }
    75    if (execve(argv[1], &argv[1], envp) == -1) {
    76      std::cerr << "execv returned errno " << errno << std::endl;
    77      return 1;
    78    }
    79  }