// Copyright 2016 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <getopt.h>
#include <signal.h>
#include <sys/mount.h>
#include <sys/types.h>

#include <algorithm>
#include <functional>
#include <memory>
#include <ostream>
#include <sstream>
#include <string>
#include <vector>

#include <base/at_exit.h>
#include <base/bind.h>
#include <base/callback_forward.h>
#include <base/callback_helpers.h>
#include <base/command_line.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/files/scoped_file.h>
#include <base/json/json_writer.h>
#include <base/logging.h>
#include <base/macros.h>
#include <base/posix/eintr_wrapper.h>
#include <base/process/launch.h>
#include <base/stl_util.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <brillo/daemons/daemon.h>
#include <brillo/syslog_logging.h>
#include <libminijail.h>
#include <scoped_minijail.h>

#include <libcontainer/config.h>
#include <libcontainer/container.h>
#include <libcontainer/libcontainer.h>

#include "run_oci/container_config_parser.h"
#include "run_oci/container_options.h"
#include "run_oci/run_oci_utils.h"

namespace run_oci {

namespace {

constexpr char kRunContainersPath[] = "/run/containers";

constexpr char kProcSelfMountsPath[] = "/proc/self/mounts";

constexpr char kContainerPidFilename[] = "container.pid";
constexpr char kConfigJsonFilename[] = "config.json";
constexpr char kRunOciFilename[] = ".run_oci";
constexpr char kLogFilename[] = "log";

// PIDs can be up to 8 characters, plus the terminating NUL byte. Rounding it up
// to the next power-of-two.
constexpr size_t kMaxPidFileLength = 16;

const std::map<std::string, int> kSignalMap = {
#define SIGNAL_MAP_ENTRY(name) \
  { #name, SIG##name }
    SIGNAL_MAP_ENTRY(HUP),   SIGNAL_MAP_ENTRY(INT),    SIGNAL_MAP_ENTRY(QUIT),
    SIGNAL_MAP_ENTRY(ILL),   SIGNAL_MAP_ENTRY(TRAP),   SIGNAL_MAP_ENTRY(ABRT),
    SIGNAL_MAP_ENTRY(BUS),   SIGNAL_MAP_ENTRY(FPE),    SIGNAL_MAP_ENTRY(KILL),
    SIGNAL_MAP_ENTRY(USR1),  SIGNAL_MAP_ENTRY(SEGV),   SIGNAL_MAP_ENTRY(USR2),
    SIGNAL_MAP_ENTRY(PIPE),  SIGNAL_MAP_ENTRY(ALRM),   SIGNAL_MAP_ENTRY(TERM),
    SIGNAL_MAP_ENTRY(CLD),   SIGNAL_MAP_ENTRY(CHLD),   SIGNAL_MAP_ENTRY(CONT),
    SIGNAL_MAP_ENTRY(STOP),  SIGNAL_MAP_ENTRY(TSTP),   SIGNAL_MAP_ENTRY(TTIN),
    SIGNAL_MAP_ENTRY(TTOU),  SIGNAL_MAP_ENTRY(URG),    SIGNAL_MAP_ENTRY(XCPU),
    SIGNAL_MAP_ENTRY(XFSZ),  SIGNAL_MAP_ENTRY(VTALRM), SIGNAL_MAP_ENTRY(PROF),
    SIGNAL_MAP_ENTRY(WINCH), SIGNAL_MAP_ENTRY(POLL),   SIGNAL_MAP_ENTRY(IO),
    SIGNAL_MAP_ENTRY(PWR),   SIGNAL_MAP_ENTRY(SYS),
#undef SIGNAL_MAP_ENTRY
};

std::ostream& operator<<(std::ostream& o, const OciHook& hook) {
  o << "Hook{path=\"" << hook.path.value() << "\", args=[";
  bool first = true;
  for (const auto& arg : hook.args) {
    if (!first)
      o << ", ";
    first = false;
    o << arg;
  }
  o << "]}";
  return o;
}

// Converts a single UID map to a string.
std::string GetIdMapString(const OciLinuxNamespaceMapping& map) {
  std::ostringstream oss;
  oss << map.containerID << " " << map.hostID << " " << map.size;
  return oss.str();
}

// Converts an array of UID mappings given in |maps| to the string format the
// kernel understands and puts that string in |map_string_out|.
std::string IdStringFromMap(const std::vector<OciLinuxNamespaceMapping>& maps) {
  std::ostringstream oss;
  bool first = true;
  for (const auto& map : maps) {
    if (first)
      first = false;
    else
      oss << ",";
    oss << GetIdMapString(map);
  }
  return oss.str();
}

// Sanitize |flags| that can be used for filesystem of a given |type|.
int SanitizeFlags(const std::string& type, int flags) {
  int sanitized_flags = flags;
  // Right now, only sanitize sysfs and procfs.
  if (type != "sysfs" && type != "proc")
    return flags;

  // sysfs and proc should always have nodev, noexec, nosuid.
  // Warn the user if these weren't specified, then turn them on.
  sanitized_flags |= (MS_NODEV | MS_NOEXEC | MS_NOSUID);
  if (flags ^ sanitized_flags)
    LOG(WARNING) << "Sanitized mount of type " << type << ".";

  return sanitized_flags;
}

// Returns the path for |path| relative to |bundle_dir|.
base::FilePath MakeAbsoluteFilePathRelativeTo(const base::FilePath& bundle_dir,
                                              const base::FilePath& path) {
  if (path.IsAbsolute())
    return path;
  return bundle_dir.Append(path);
}

// Adds the mounts specified in |mounts| to |config_out|.
void ConfigureMounts(const std::vector<OciMount>& mounts,
                     const base::FilePath& bundle_dir,
                     uid_t uid,
                     gid_t gid,
                     container_config* config_out) {
  // Get all the mountpoints in the external mount namespace upfront. This will
  // be used in case we need to perform any remounts, in order to preserve
  // flags that won't be changing.
  std::vector<run_oci::Mountpoint> mountpoints = run_oci::GetMountpointsUnder(
      base::FilePath("/"), base::FilePath(kProcSelfMountsPath));

  // Sort the list of mountpoints. For calculating remount flags, we are
  // interested in the deepest mount a particular path is located.  Since this
  // is a tree structure, traversing the list of mounts in inverse lexicographic
  // order and stopping in the first mount that is a prefix of the path works.
  std::sort(mountpoints.begin(), mountpoints.end(),
            [](const run_oci::Mountpoint& a, const run_oci::Mountpoint& b) {
              return b.path < a.path;
            });

  for (const auto& mount : mounts) {
    int mount_flags, negated_mount_flags, bind_mount_flags,
        mount_propagation_flags;
    bool loopback;
    std::string verity_options;
    std::string options = ParseMountOptions(
        mount.options, &mount_flags, &negated_mount_flags, &bind_mount_flags,
        &mount_propagation_flags, &loopback, &verity_options);

    base::FilePath source = mount.source;
    bool new_mount = true;
    if (mount.type == "bind") {
      // libminijail disallows relative bind-mounts.
      source = MakeAbsoluteFilePathRelativeTo(bundle_dir, mount.source);
      new_mount = false;
    }

    // Loopback devices have to be mounted outside.
    bool mount_in_ns = !mount.performInIntermediateNamespace && !loopback;

    // Bind-mounts cannot adjust the mount flags in the same call to mount(2),
    // so in order to do so, an explicit remount is needed. In order to avoid
    // clobbering unnecessary flags, we try to grab them from the closest
    // original mount point.
    int original_flags = 0;
    if (!new_mount) {
      for (const auto& mountpoint : mountpoints) {
        if (!base::StartsWith(source.value(), mountpoint.path.value(),
                              base::CompareCase::SENSITIVE)) {
          continue;
        }
        original_flags = mountpoint.mountflags;
        break;
      }
    }
    int new_flags = (original_flags & ~negated_mount_flags) | mount_flags;

    if (new_mount) {
      // This is a brand new mount. We pass in all the arguments that were
      // provided in the config.
      mount_flags = SanitizeFlags(mount.type, mount_flags);
      container_config_add_mount(
          config_out, "mount", source.value().c_str(),
          mount.destination.value().c_str(), mount.type.c_str(),
          options.empty() ? nullptr : options.c_str(),
          verity_options.empty() ? nullptr : verity_options.c_str(),
          mount_flags, uid, gid, 0750, mount_in_ns, true /* create */,
          loopback);
    } else if (bind_mount_flags) {
      // Bind-mounts only get the MS_BIND and maybe MS_REC|MS_RDONLY mount
      // flags.
      container_config_add_mount(
          config_out, "mount", source.value().c_str(),
          mount.destination.value().c_str(), mount.type.c_str(),
          nullptr /* options */, nullptr /* verity_options */,
          bind_mount_flags | (new_flags & MS_RDONLY), uid, gid, 0750,
          mount_in_ns, true /* create */, false /* loopback */);
    }
    if (mount_propagation_flags) {
      // Mount propagation flags need to be updated separately from the original
      // mount. Only the destination is important.
      container_config_add_mount(
          config_out, "mount", "" /* source */,
          mount.destination.value().c_str(), "" /* type */,
          nullptr /* options */, nullptr /* verity_options */,
          mount_propagation_flags, uid, gid, 0750, mount_in_ns,
          false /* create */, false /* loopback */);
    }
    if (!new_mount && new_flags != original_flags) {
      // Adding MS_BIND to the MS_REMOUNT will make the kernel apply the new
      // flags to the mount itself and not the superblock. This makes the
      // operation work in unprivileged user namespaces, since the container is
      // only allowed to modify its copy of the mount and not the underlying
      // superblock.
      new_flags |= MS_REMOUNT | MS_BIND;
      container_config_add_mount(
          config_out, "mount", "" /* source */,
          mount.destination.value().c_str(), "" /* type */,
          nullptr /* options */, nullptr /* verity_options */, new_flags, uid,
          gid, 0750, mount_in_ns, false /* create */, false /* loopback */);
    }
  }
}

// Adds the devices specified in |devices| to |config_out|.
void ConfigureDevices(const std::vector<OciLinuxDevice>& devices,
                      container_config* config_out) {
  for (const auto& device : devices) {
    container_config_add_device(
        config_out, device.type.c_str()[0], device.path.value().c_str(),
        device.fileMode, device.dynamicMajor ? -1 : device.major,
        device.dynamicMinor ? -1 : device.minor, device.dynamicMajor,
        device.dynamicMinor, device.uid, device.gid,
        0,  // Cgroup permission are now in 'resources'.
        0, 0);
  }
}

// Adds the cgroup device permissions specified in |devices| to |config_out|.
void ConfigureCgroupDevices(const std::vector<OciLinuxCgroupDevice>& devices,
                            container_config* config_out) {
  for (const auto& device : devices) {
    bool read_set = device.access.find('r') != std::string::npos;
    bool write_set = device.access.find('w') != std::string::npos;
    bool make_set = device.access.find('m') != std::string::npos;
    container_config_add_cgroup_device(
        config_out, device.allow, device.type.c_str()[0], device.major,
        device.minor, read_set, write_set, make_set);
  }
}

// Fills the libcontainer container_config struct given in |config_out| by
// pulling the apropriate fields from the OCI configuration given in |oci|.
bool ContainerConfigFromOci(const OciConfig& oci,
                            const base::FilePath& bundle_dir,
                            const std::vector<std::string>& extra_args,
                            container_config* config_out) {
  // Process configuration
  container_config_config_root(config_out, bundle_dir.value().c_str());
  container_config_uid(config_out, oci.process.user.uid);
  container_config_gid(config_out, oci.process.user.gid);
  container_config_additional_gids(config_out,
                                   oci.process.user.additionalGids.data(),
                                   oci.process.user.additionalGids.size());
  base::FilePath root_dir =
      MakeAbsoluteFilePathRelativeTo(bundle_dir, oci.root.path);
  container_config_premounted_runfs(config_out, root_dir.value().c_str());

  std::vector<const char*> argv;
  for (const auto& arg : oci.process.args)
    argv.push_back(arg.c_str());
  for (const auto& arg : extra_args)
    argv.push_back(arg.c_str());
  container_config_program_argv(config_out, argv.data(), argv.size());

  std::vector<const char*> namespaces;
  for (const auto& ns : oci.linux_config.namespaces) {
    namespaces.push_back(ns.type.c_str());
  }
  container_config_namespaces(config_out, namespaces.data(), namespaces.size());

  if (container_config_has_namespace(config_out, "user")) {
    if (oci.linux_config.uidMappings.empty() ||
        oci.linux_config.gidMappings.empty()) {
      LOG(ERROR) << "User namespaces require at least one uid/gid mapping";
      return false;
    }

    std::string uid_maps = IdStringFromMap(oci.linux_config.uidMappings);
    container_config_uid_map(config_out, uid_maps.c_str());

    std::string gid_maps = IdStringFromMap(oci.linux_config.gidMappings);
    container_config_gid_map(config_out, gid_maps.c_str());
  }

  ConfigureMounts(oci.mounts, bundle_dir, oci.process.user.uid,
                  oci.process.user.gid, config_out);
  ConfigureDevices(oci.linux_config.devices, config_out);
  ConfigureCgroupDevices(oci.linux_config.resources.devices, config_out);

  for (const auto& limit : oci.process.rlimits) {
    if (container_config_add_rlimit(config_out, limit.type, limit.soft,
                                    limit.hard)) {
      return false;
    }
  }

  return true;
}

// Reads json configuration of a container from |config_path| and filles
// |oci_out| with the specified container configuration.
bool OciConfigFromFile(const base::FilePath& config_path,
                       const OciConfigPtr& oci_out) {
  std::string config_json_data;
  if (!base::ReadFileToString(config_path, &config_json_data)) {
    PLOG(ERROR) << "Fail to read container config: " << config_path.value();
    return false;
  }

  if (!run_oci::ParseContainerConfig(config_json_data, oci_out)) {
    LOG(ERROR) << "Fail to parse container config: " << config_path.value();
    return false;
  }

  return true;
}

// Appends additional mounts specified in |bind_mounts| to the configuration
// given in |config_out|.
bool AppendMounts(const BindMounts& bind_mounts, container_config* config_out) {
  for (const auto& mount : bind_mounts) {
    if (container_config_add_mount(
            config_out, "mount", mount.first.value().c_str(),
            mount.second.value().c_str(), "bind", nullptr /* data */,
            nullptr /* verity */, MS_MGC_VAL | MS_BIND, 0, 0, 0750,
            true /* mount_in_ns */, true /* create */, false /* loopback */)) {
      PLOG(ERROR) << "Failed to add mount of " << mount.first.value();
      return false;
    }
  }

  return true;
}

// Generates OCI-compliant, JSON-formatted container state. This is
// pretty-printed so that bash scripts can more easily grab the fields instead
// of having to parse the JSON blob.
std::string ContainerState(pid_t child_pid,
                           const std::string& container_id,
                           const base::FilePath& bundle_dir,
                           const base::FilePath& container_dir,
                           const std::string& status) {
  base::Value state(base::Value::Type::DICTIONARY);
  state.SetKey("ociVersion", base::Value("1.0"));
  state.SetKey("id", base::Value(container_id));
  state.SetKey("status", base::Value(status));
  state.SetKey("bundle",
               base::Value(base::MakeAbsoluteFilePath(bundle_dir).value()));
  state.SetKey("pid", base::Value(child_pid));
  base::Value annotations(base::Value::Type::DICTIONARY);
  annotations.SetKey(
      "org.chromium.run_oci.container_root",
      base::Value(base::MakeAbsoluteFilePath(container_dir).value()));
  state.SetKey("annotations", std::move(annotations));
  std::string state_json;
  if (!base::JSONWriter::WriteWithOptions(
          state, base::JSONWriter::OPTIONS_PRETTY_PRINT, &state_json)) {
    LOG(ERROR) << "Failed to serialize the container state";
    return std::string();
  }
  return state_json;
}

// Runs one hook.
bool RunOneHook(const OciHook& hook,
                const std::string& hook_type,
                const std::string& container_state) {
  base::LaunchOptions options;
  if (!hook.env.empty()) {
    options.clear_environment = true;
    options.environment = hook.env;
  }

  base::ScopedFD write_pipe_read_fd, write_pipe_write_fd;
  if (!run_oci::Pipe(&write_pipe_read_fd, &write_pipe_write_fd, 0)) {
    PLOG(ERROR) << "Bad write pipe";
    return false;
  }
  base::FileHandleMappingVector fds_to_remap{
      {write_pipe_read_fd.get(), STDIN_FILENO}, {STDERR_FILENO, STDERR_FILENO}};
  options.fds_to_remap = std::move(fds_to_remap);

  std::vector<std::string> args;
  if (hook.args.empty()) {
    args.push_back(hook.path.value());
  } else {
    args = hook.args;
    // Overwrite the first argument with the path since base::LaunchProcess does
    // not take an additional parameter for the executable name. Since the OCI
    // spec mandates that the path should be absolute, it's better to use that
    // rather than rely on whatever short name was passed in |args|.
    args[0] = hook.path.value();
  }

  DVLOG(1) << "Running " << hook_type << " " << hook;

  base::Process child = base::LaunchProcess(args, options);
  write_pipe_read_fd.reset();
  if (!base::WriteFileDescriptor(write_pipe_write_fd.get(),
                                 container_state.c_str(),
                                 container_state.size())) {
    PLOG(ERROR) << "Failed to send container state";
  }
  write_pipe_write_fd.reset();
  int exit_code;
  if (!child.WaitForExitWithTimeout(hook.timeout, &exit_code)) {
    LOG(ERROR) << "Timeout exceeded running " << hook_type << " hook " << hook;
    if (!child.Terminate(0, true))
      LOG(ERROR) << "Failed to terminate " << hook_type << " hook " << hook;
    return false;
  }
  if (exit_code != 0) {
    LOG(ERROR) << hook_type << " hook " << hook << " exited with status "
               << exit_code;
    return false;
  }
  return true;
}

bool RunHooks(const std::vector<OciHook>& hooks,
              pid_t* child_pid,
              const std::string& container_id,
              const base::FilePath& bundle_dir,
              const base::FilePath& container_dir,
              const std::string& hook_stage,
              const std::string& status) {
  if (*child_pid == -1 && hook_stage != "precreate") {
    // If the child PID is not present, that means that the container failed to
    // run at least to a point where there was a PID at all. Hooks do not need
    // to be run in that case.
    return false;
  }
  bool success = true;
  std::string container_state = ContainerState(
      *child_pid, container_id, bundle_dir, container_dir, status);
  for (const auto& hook : hooks)
    success &= RunOneHook(hook, hook_stage, container_state);
  if (!success)
    LOG(WARNING) << "Error running " << hook_stage << " hooks";
  return success;
}

bool SaveChildPidAndRunHooks(const std::vector<OciHook>& hooks,
                             pid_t* child_pid,
                             const std::string& container_id,
                             const base::FilePath& bundle_dir,
                             const base::FilePath& container_dir,
                             const std::string& hook_stage,
                             const std::string& status,
                             pid_t container_pid) {
  *child_pid = container_pid;
  return RunHooks(hooks, child_pid, container_id, bundle_dir, container_dir,
                  hook_stage, status);
}

// Perform any pre-execve(2) setup of the process state, in the context of the
// container.
int SetupProcessState(void* payload) {
  const OciProcess* process = reinterpret_cast<const OciProcess*>(payload);
  if (!process->env.empty()) {
    if (clearenv() != 0) {
      PLOG(ERROR) << "Failed to clear environment";
      return -errno;
    }
    for (const auto& entry : process->env) {
      if (setenv(entry.first.c_str(), entry.second.c_str(), true) != 0) {
        PLOG(ERROR) << "Failed to set " << entry.first << "=" << entry.second;
        return -errno;
      }
    }
  }
  if (umask(process->umask) == -1) {
    PLOG(ERROR) << "Failed to set umask to " << process->umask;
    return -errno;
  }

  return 0;
}

void CleanUpContainer(const base::FilePath& container_dir) {
  std::vector<run_oci::Mountpoint> mountpoints = run_oci::GetMountpointsUnder(
      container_dir, base::FilePath(kProcSelfMountsPath));

  // Sort the list of mountpoints. Since this is a tree structure, unmounting
  // recursively can be achieved by traversing this list in inverse
  // lexicographic order.
  std::sort(mountpoints.begin(), mountpoints.end(),
            [](const run_oci::Mountpoint& a, const run_oci::Mountpoint& b) {
              return b.path < a.path;
            });
  for (const auto& mountpoint : mountpoints) {
    if (umount2(mountpoint.path.value().c_str(), MNT_DETACH))
      PLOG(ERROR) << "Failed to unmount " << mountpoint.path.value();
  }

  if (!base::DeleteFile(container_dir, true /*recursive*/)) {
    PLOG(ERROR) << "Failed to clean up the container directory "
                << container_dir.value();
  }
}

// Runs an OCI image with the configuration found at |bundle_dir|.
// If |detach_after_start| is true, a new directory under kRunContainersPath
// will be created to store the state of the container.
// If |detach_after_start| is true, blocks until the program specified in
// config.json exits, otherwise blocks until after the post-start hooks have
// finished.
// Returns -1 on error.
int RunOci(const base::FilePath& bundle_dir,
           const std::string& container_id,
           const ContainerOptions& container_options,
           bool detach_after_start) {
  LOG(INFO) << "Starting container " << container_id;

  base::FilePath container_dir;
  const base::FilePath container_config_file =
      bundle_dir.Append(kConfigJsonFilename);

  OciConfigPtr oci_config(new OciConfig());
  if (!OciConfigFromFile(container_config_file, oci_config))
    return -1;

  pid_t child_pid = -1;
  if (!oci_config->pre_create_hooks.empty()) {
    // Run the precreate hooks now.
    if (!RunHooks(oci_config->pre_create_hooks, &child_pid, container_id,
                  bundle_dir, container_dir, "precreate", "creating")) {
      LOG(ERROR) << "Error running precreate hooks";
      return -1;
    }
  }

  // Inject options passed in from the commandline.
  if (oci_config->linux_config.cgroupsPath.empty()) {
    // The OCI spec says that absolute paths for |cgroupsPath| are treated as
    // relative to the root of the cgroup hierarchy.
    oci_config->linux_config.cgroupsPath =
        base::FilePath("/" + container_options.cgroup_parent);
  }

  container_dir = base::FilePath(kRunContainersPath).Append(container_id);
  base::ScopedClosureRunner cleanup(
      base::Bind(CleanUpContainer, container_dir));
  // Not using base::CreateDirectory() since we want to error out when the
  // directory exists a priori.
  if (mkdir(container_dir.value().c_str(), 0755) != 0) {
    PLOG(ERROR) << "Failed to create the container directory";
    return -1;
  }

  if (!base::CreateSymbolicLink(container_config_file,
                                container_dir.Append(kConfigJsonFilename))) {
    PLOG(ERROR) << "Failed to create the config.json symlink";
    return -1;
  }

  // Create an empty file, just to tag this container as being
  // run_oci-managed.
  const base::FilePath tag_file = container_dir.Append(kRunOciFilename);
  if (base::WriteFile(tag_file, "", 0) != 0) {
    LOG(ERROR) << "Failed to create tag file: " << tag_file.value();
    return -1;
  }

  // Create a symlink to quickly be able to navigate to the root of the
  // container.
  base::FilePath rootfs_path =
      MakeAbsoluteFilePathRelativeTo(bundle_dir, oci_config->root.path);
  base::FilePath rootfs_symlink =
      container_dir.Append("mountpoints/container-root");
  if (!base::CreateDirectory(rootfs_symlink.DirName())) {
    PLOG(ERROR) << "Failed to create mountpoints directory";
    return -1;
  }
  if (!base::CreateSymbolicLink(rootfs_path, rootfs_symlink)) {
    PLOG(ERROR) << "Failed to create mountpoints/container-root symlink";
    return -1;
  }
  if (!container_options.log_file.empty() &&
      !base::CreateSymbolicLink(container_options.log_file,
                                container_dir.Append(kLogFilename))) {
    PLOG(ERROR) << "Failed to create log symlink";
  }

  bool needs_intermediate_mount_ns = false;
  for (const auto& mount : oci_config->mounts) {
    if (!mount.performInIntermediateNamespace)
      continue;
    needs_intermediate_mount_ns = true;
    break;
  }
  if (needs_intermediate_mount_ns) {
    if (!HasCapSysAdmin()) {
      PLOG(ERROR) << "Specifying 'performInIntermediateNamespace' for any "
                     "mount requires having the CAP_SYS_ADMIN capability";
      return -1;
    }
    ScopedMinijail jail(minijail_new());
    if (!jail) {
      PLOG(ERROR) << "Failed to create a minijail for the intermediate mount "
                     "namespace.";
      return -1;
    }
    minijail_namespace_vfs(jail.get());
    minijail_skip_remount_private(jail.get());
    minijail_enter(jail.get());

    DCHECK_EQ(oci_config->linux_config.rootfsPropagation &
                  ~(MS_SHARED | MS_SLAVE | MS_PRIVATE | MS_UNBINDABLE | MS_REC),
              0);
    // TODO(lhchavez): Also support rootfsPropagation for the
    // non-intermediate-namespace case.
    if (mount(nullptr, "/", nullptr, oci_config->linux_config.rootfsPropagation,
              nullptr) == -1) {
      PLOG(ERROR) << "Failed to set the root propagation flags";
      return -1;
    }
  }

  libcontainer::Config config;
  if (!ContainerConfigFromOci(*oci_config, bundle_dir,
                              container_options.extra_program_args,
                              config.get())) {
    PLOG(ERROR) << "Failed to create container from oci config.";
    return -1;
  }

  AppendMounts(container_options.bind_mounts, config.get());
  // Create a container based on the config.  The run_dir argument will be
  // unused as this container will be run in place where it was mounted.
  libcontainer::Container container(oci_config->hostname,
                                    base::FilePath("/unused"));

  // Close all open FDs in the container except stdio, so that we get unified
  // logs.
  const int inherited_fds[] = {STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO};
  if (container_config_inherit_fds(config.get(), inherited_fds,
                                   base::size(inherited_fds))) {
    LOG(WARNING) << "Failed to inherit stdout/stderr.";
  }

  if (!oci_config->process.capabilities.empty()) {
    container_config_set_capmask(
        config.get(), oci_config->process.capabilities["effective"].to_ullong(),
        oci_config->process.capabilities.find("ambient") !=
            oci_config->process.capabilities.end());
  }

  if (!oci_config->process.selinuxLabel.empty()) {
    container_config_set_selinux_context(
        config.get(), oci_config->process.selinuxLabel.c_str());
  }

  // The OCI spec says that absolute paths for |cgroupsPath| must be treated as
  // relative to the cgroups mount point, and relative paths may be interepreted
  // to being relative to a runtime-determined point in the hierarchy. We choose
  // to interpret both cases as relative to the cgroups mount point for the time
  // being.
  std::string cgroup_parent = oci_config->linux_config.cgroupsPath.value();
  if (oci_config->linux_config.cgroupsPath.IsAbsolute())
    cgroup_parent = cgroup_parent.substr(1);
  if (!cgroup_parent.empty()) {
    container_config_set_cgroup_parent(config.get(), cgroup_parent.c_str(),
                                       container_config_get_uid(config.get()),
                                       container_config_get_gid(config.get()));
  }

  if (container_options.use_current_user) {
    OciLinuxNamespaceMapping single_map = {
        getuid(),  // hostID
        0,         // containerID
        1          // size
    };
    std::string map_string = GetIdMapString(single_map);
    container_config_uid_map(config.get(), map_string.c_str());
    container_config_gid_map(config.get(), map_string.c_str());
  }

  if (oci_config->linux_config.cpu.shares) {
    container_config_set_cpu_shares(config.get(),
                                    oci_config->linux_config.cpu.shares);
  }
  if (oci_config->linux_config.cpu.quota &&
      oci_config->linux_config.cpu.period) {
    container_config_set_cpu_cfs_params(config.get(),
                                        oci_config->linux_config.cpu.quota,
                                        oci_config->linux_config.cpu.period);
  }
  if (oci_config->linux_config.cpu.realtimeRuntime &&
      oci_config->linux_config.cpu.realtimePeriod) {
    container_config_set_cpu_rt_params(
        config.get(), oci_config->linux_config.cpu.realtimeRuntime,
        oci_config->linux_config.cpu.realtimePeriod);
  }

  if (!oci_config->linux_config.altSyscall.empty()) {
    container_config_alt_syscall_table(
        config.get(), oci_config->linux_config.altSyscall.c_str());
  }

  if (oci_config->linux_config.skipSecurebits) {
    container_config_set_securebits_skip_mask(
        config.get(), oci_config->linux_config.skipSecurebits);
  }

  container_config_set_run_as_init(config.get(), container_options.run_as_init);

  // Prepare the post-stop hooks to be run. Note that we don't need to run them
  // if the |child_pid| is -1. Either the pre-start hooks or the call to
  // container_pid() will populate the value, and RunHooks() will simply refuse
  // to run if |child_pid| is -1, so we will always do the right thing.
  // The callback is run in the same stack, so std::cref() is safe.
  base::ScopedClosureRunner post_stop_hooks(base::Bind(
      base::IgnoreResult(&RunHooks), std::cref(oci_config->post_stop_hooks),
      base::Unretained(&child_pid), container_id, bundle_dir, container_dir,
      "poststop", "stopped"));

  if (!oci_config->pre_chroot_hooks.empty()) {
    config.AddHook(
        MINIJAIL_HOOK_EVENT_PRE_CHROOT,
        base::Bind(&SaveChildPidAndRunHooks,
                   std::cref(oci_config->pre_chroot_hooks),
                   base::Unretained(&child_pid), container_id, bundle_dir,
                   container_dir, "prechroot", "created"));
  }
  if (!oci_config->pre_start_hooks.empty()) {
    config.AddHook(
        MINIJAIL_HOOK_EVENT_PRE_EXECVE,
        base::Bind(&SaveChildPidAndRunHooks,
                   std::cref(oci_config->pre_start_hooks),
                   base::Unretained(&child_pid), container_id, bundle_dir,
                   container_dir, "prestart", "created"));
  }
  // This needs to run in the context of the container process.
  container_config_set_pre_execve_hook(config.get(), &SetupProcessState,
                                       &oci_config->process);

  int rc;
  rc = container_start(container.get(), config.get());
  if (rc) {
    errno = -rc;
    PLOG(ERROR) << "start failed: " << container_dir.value();
    return -1;
  }

  child_pid = container_pid(container.get());
  const base::FilePath container_pid_path =
      container_dir.Append(kContainerPidFilename);
  std::string child_pid_str = base::StringPrintf("%d\n", child_pid);
  if (base::WriteFile(container_pid_path, child_pid_str.c_str(),
                      child_pid_str.size()) != child_pid_str.size()) {
    PLOG(ERROR) << "Failed to write the container PID to "
                << container_pid_path.value();
    return -1;
  }

  // Create another symlink similar to mountpoints/container-root. Unlike
  // mountpoints/container-root, this one provides the view from inside the
  // container.
  base::FilePath procfs_path(base::StringPrintf("/proc/%d/root", child_pid));
  base::FilePath symlink_path = container_dir.Append("root");
  if (!base::CreateSymbolicLink(procfs_path, symlink_path)) {
    PLOG(ERROR) << "Failed to create root/ symlink";
    container_kill(container.get());
    return -1;
  }

  if (!RunHooks(oci_config->post_start_hooks, &child_pid, container_id,
                bundle_dir, container_dir, "poststart", "running")) {
    LOG(ERROR) << "Error running poststart hooks";
    container_kill(container.get());
    return -1;
  }

  LOG(INFO) << "Container " << container_id << " running";

  if (detach_after_start) {
    // The container has reached a steady state. We can now return and let the
    // container keep running. We don't want to run the post-stop hooks now, but
    // until the user actually deletes the container.
    ignore_result(post_stop_hooks.Release());
    ignore_result(cleanup.Release());
    return 0;
  }

  if (container_options.sigstop_when_ready)
    raise(SIGSTOP);

  return container_wait(container.get());
}

// If this invocation of run_oci is operating on a pre-existing container,
// attempt to perform the same log redirection that was performed in the initial
// start so that all the logging statements appear in the same file and are
// easily correlated.
bool RestoreLogRedirection(const std::string& container_id) {
  const base::FilePath container_dir =
      base::FilePath(kRunContainersPath).Append(container_id);

  const base::FilePath log_file = container_dir.Append(kLogFilename);
  if (!base::PathExists(log_file)) {
    // No redirection needed.
    return true;
  }
  return !run_oci::RedirectLoggingAndStdio(log_file);
}

bool GetContainerPID(const std::string& container_id, pid_t* pid_out) {
  const base::FilePath container_dir =
      base::FilePath(kRunContainersPath).Append(container_id);
  const base::FilePath container_pid_path =
      container_dir.Append(kContainerPidFilename);

  std::string container_pid_str;
  if (!base::ReadFileToStringWithMaxSize(container_pid_path, &container_pid_str,
                                         kMaxPidFileLength)) {
    PLOG(ERROR) << "Failed to read " << container_pid_path.value();
    return false;
  }

  int container_pid;
  if (!base::StringToInt(
          base::TrimWhitespaceASCII(container_pid_str, base::TRIM_ALL),
          &container_pid)) {
    LOG(ERROR) << "Failed to convert the container pid to a number: "
               << container_pid_str;
    return false;
  }

  if (!base::PathExists(container_dir.Append(kRunOciFilename))) {
    LOG(ERROR) << "Container " << container_id << " is not run_oci-managed";
    return false;
  }

  *pid_out = static_cast<pid_t>(container_pid);
  return true;
}

int OciKill(const std::string& container_id, int kill_signal) {
  RestoreLogRedirection(container_id);
  LOG(INFO) << "Sending signal " << kill_signal << " to container "
            << container_id;

  pid_t container_pid;
  if (!GetContainerPID(container_id, &container_pid))
    return -1;

  if (kill(container_pid, kill_signal) == -1) {
    PLOG(ERROR) << "Failed to send signal " << kill_signal;
    return -1;
  }

  return 0;
}

base::FilePath GetBundlePath(const base::FilePath& container_config_file) {
  base::FilePath bundle_path;
  if (!base::ReadSymbolicLink(container_config_file, &bundle_path)) {
    PLOG(ERROR) << "Failed to read symlink " << container_config_file.value();
    return base::FilePath();
  }
  return bundle_path.DirName();
}

int OciDestroy(const std::string& container_id) {
  RestoreLogRedirection(container_id);
  LOG(INFO) << "Destroying container " << container_id;

  const base::FilePath container_dir =
      base::FilePath(kRunContainersPath).Append(container_id);
  const base::FilePath container_config_file =
      container_dir.Append(kConfigJsonFilename);

  if (!base::PathExists(container_dir)) {
    LOG(INFO) << "Container " << container_id << " has already been destroyed";
    return 0;
  }

  pid_t container_pid;
  if (!GetContainerPID(container_id, &container_pid)) {
    LOG(INFO) << "Container " << container_id << " is not running. "
              << "Cleaning up the container directory.";
  } else {
    if (kill(container_pid, 0) == 0) {
      LOG(ERROR) << "Container " << container_id << " is still running.";
      return -1;
    } else if (errno != ESRCH) {
      PLOG(ERROR) << "The state of container " << container_id
                  << " is unknown.";
      return -1;
    }
  }

  OciConfigPtr oci_config(new OciConfig());
  if (!OciConfigFromFile(container_config_file, oci_config)) {
    return -1;
  }

  // We are committed to cleaning everything up now.
  RunHooks(oci_config->post_stop_hooks, &container_pid, container_id,
           GetBundlePath(container_config_file), container_dir, "poststop",
           "stopped");
  CleanUpContainer(container_dir);

  LOG(INFO) << "Container " << container_id << " destroyed";

  return 0;
}

const struct option longopts[] = {
    {"bind_mount", required_argument, nullptr, 'b'},
    {"help", no_argument, nullptr, 'h'},
    {"cgroup_parent", required_argument, nullptr, 'p'},
    {"use_current_user", no_argument, nullptr, 'u'},
    {"signal", required_argument, nullptr, 'S'},
    {"container_path", required_argument, nullptr, 'c'},
    {"log_dir", required_argument, nullptr, 'l'},
    {"log_tag", required_argument, nullptr, 't'},
    {"sigstop_when_ready", no_argument, nullptr, 's'},
    {0, 0, 0, 0},
};

void print_help(const char* argv0) {
  printf(
      "usage: %1$s [OPTIONS] <command> <container id>\n"
      "Commands:\n"
      "  run     creates and runs the container in the foreground.\n"
      "          %1$s will remain alive until the container's\n"
      "          init process exits and all resources are freed.\n"
      "          Running a container in this way does not support\n"
      "          the 'kill' or 'destroy' commands\n"
      "  start   creates and runs the container in the background.\n"
      "          The container can then be torn down with the 'kill'\n"
      "          command, and resources freed with the 'delete' command.\n"
      "  kill    sends the specified signal to the container's init.\n"
      "          the post-stop hooks will not be run at this time.\n"
      "  destroy runs the post-stop hooks and releases all resources.\n"
      "          If the container is not running, it just releases all\n"
      "          resources.\n"
      "\n"
      "Global options:\n"
      "  -h, --help                     Print this message and exit.\n"
      "  -l, --log_dir=<PATH>           Write logging messages to a file\n"
      "                                 in <PATH> instead of syslog.\n"
      "                                 Also redirects hooks' stdout/stderr.\n"
      "  -t, --log_tag=<TAG>            Use <TAG> as the syslog tag.\n"
      "\n"
      "run/start:\n"
      "\n"
      "  %1$s {run,start} [OPTIONS] <container id> [-- <args>]\n"
      "\n"
      "Options for run and start:\n"
      "  -c, --container_path=<PATH>    The path of the container.\n"
      "                                 Defaults to $PWD.\n"
      "  -b, --bind_mount=<A>:<B>       Mount path A to B container.\n"
      "  -p, --cgroup_parent=<NAME>     Set parent cgroup for container.\n"
      "  -u, --use_current_user         Map the current user/group only.\n"
      "  -i, --dont_run_as_init         Do not run the command as init.\n"
      "\n"
      "Options for run:\n"
      "  -s, --sigstop_when_ready      raise SIGSTOP on container is ready.\n"
      "                                 For use with Upstart's 'expect stop'.\n"
      "\n"
      "kill:\n"
      "\n"
      "  %1$s kill [OPTIONS] <container id>\n"
      "\n"
      "Options for kill:\n"
      "  -S, --signal=<SIGNAL>          The signal to send to init.\n"
      "                                 Defaults to TERM.\n"
      "destroy:\n"
      "\n"
      "  %1$s destroy <container id>\n"
      "\n",
      argv0);
}

}  // namespace

}  // namespace run_oci

int main(int argc, char** argv) {
  base::AtExitManager exit_manager;

  run_oci::ContainerOptions container_options;
  base::FilePath bundle_dir = base::MakeAbsoluteFilePath(base::FilePath("."));
  int c;
  int kill_signal = SIGTERM;

  brillo::InitLog(brillo::kLogToSyslog | brillo::kLogHeader |
                  brillo::kLogToStderrIfTty);

  base::FilePath log_dir;

  while ((c = getopt_long(argc, argv, "b:B:c:hp:s:S:uUl:", run_oci::longopts,
                          nullptr)) != -1) {
    switch (c) {
      case 'b': {
        std::istringstream ss(optarg);
        std::string outside_path;
        std::string inside_path;
        std::getline(ss, outside_path, ':');
        std::getline(ss, inside_path, ':');
        if (outside_path.empty() || inside_path.empty()) {
          run_oci::print_help(argv[0]);
          return -1;
        }
        container_options.bind_mounts.push_back(run_oci::BindMount(
            base::MakeAbsoluteFilePath(base::FilePath(outside_path)),
            base::FilePath(inside_path)));
        break;
      }
      case 'c':
        bundle_dir = base::MakeAbsoluteFilePath(base::FilePath(optarg));
        break;
      case 'u':
        container_options.use_current_user = true;
        break;
      case 'p':
        container_options.cgroup_parent = optarg;
        break;
      case 'S': {
        auto it = run_oci::kSignalMap.find(optarg);
        if (it == run_oci::kSignalMap.end()) {
          LOG(ERROR) << "Invalid signal name '" << optarg << "'";
          return -1;
        }
        kill_signal = it->second;
        break;
      }
      case 'i':
        container_options.run_as_init = false;
        break;
      case 'l':
        log_dir = base::FilePath(optarg);
        // Can't use base::MakeAbsoluteFilePath since |log_dir| might not yet
        // exist.
        if (!log_dir.IsAbsolute()) {
          base::FilePath current_directory;
          if (!base::GetCurrentDirectory(&current_directory)) {
            PLOG(ERROR) << "Failed to get current directory";
            return -1;
          }
          log_dir = current_directory.Append(log_dir);
        }
        break;
      case 's':
        container_options.sigstop_when_ready = true;
        break;
      case 't':
        container_options.log_tag = optarg;
        break;
      case 'h':
        run_oci::print_help(argv[0]);
        return 0;
      default:
        run_oci::print_help(argv[0]);
        return 1;
    }
  }

  if (optind >= argc) {
    LOG(ERROR) << "Command is required.";
    run_oci::print_help(argv[0]);
    return -1;
  }
  std::string command(argv[optind++]);

  if (optind >= argc) {
    LOG(ERROR) << "Container id is required.";
    run_oci::print_help(argv[0]);
    return -1;
  }
  std::string container_id(argv[optind++]);
  if (container_id.find(base::FilePath::kSeparators[0]) != std::string::npos) {
    LOG(ERROR) << "Container ID cannot contain path separators.";
    run_oci::print_help(argv[0]);
    return -1;
  }

  for (; optind < argc; optind++)
    container_options.extra_program_args.push_back(std::string(argv[optind]));

  std::unique_ptr<run_oci::SyslogStdioAdapter> syslog_stdio_adapter;
  if (!log_dir.empty()) {
    // If the user has specified a value for |log_dir|, ensure the directory,
    // create a unique(-ish) file and redirect logging and output to it.
    if (!base::DirectoryExists(log_dir)) {
      // Not using base::CreateDirectory() since we want to set more relaxed
      // permissions.
      if (mkdir(log_dir.value().c_str(), 0755) != 0) {
        PLOG(ERROR) << "Failed to create log directory '" << log_dir.value()
                    << "'";
        return -1;
      }
    }
    container_options.log_file = log_dir.Append(base::StringPrintf(
        "%s.%s", container_id.c_str(),
        brillo::GetTimeAsLogString(base::Time::Now()).c_str()));
    if (!run_oci::RedirectLoggingAndStdio(container_options.log_file))
      return -1;
  } else if (!container_options.log_tag.empty()) {
    // brillo::OpenLog can be called safely even after log operations have been
    // made before.
    brillo::OpenLog(container_options.log_tag.c_str(), true /*log_pid*/);

    syslog_stdio_adapter = run_oci::SyslogStdioAdapter::Create();
    if (!syslog_stdio_adapter) {
      LOG(ERROR) << "Failed to create the syslog stdio adapter";
      return -1;
    }
  }

  if (command == "run") {
    int result = run_oci::RunOci(bundle_dir, container_id, container_options,
                                 false /*detach_after_start*/);
    LOG(INFO) << "Container " << container_id << " finished";
    return result;
  } else if (command == "start") {
    return run_oci::RunOci(bundle_dir, container_id, container_options,
                           true /*detach_after_start*/);
  } else if (command == "kill") {
    return run_oci::OciKill(container_id, kill_signal);
  } else if (command == "destroy") {
    return run_oci::OciDestroy(container_id);
  } else {
    LOG(ERROR) << "Unknown command '" << command << "'";
    run_oci::print_help(argv[0]);
    return -1;
  }
}
