// 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 "login_manager/container_config_parser.h"

#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <algorithm>
#include <string>
#include <vector>

#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/json/json_reader.h>
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>
#include <base/values.h>

#include <libcontainer/libcontainer.h>

namespace login_manager {

namespace {

// Parses |mountinfo_data| (the contents of /proc/self/mountinfo) to determine
// whether |rootfs_path| was originally mounted as read-only.
bool IsOriginalRootfsReadOnly(const std::string& mountinfo_data,
                              const base::FilePath& rootfs_path) {
  constexpr size_t kMountinfoMountPointIndex = 4;
  constexpr size_t kMountinfoMountOptionsIndex = 5;
  const size_t kMountinfoMinNumberOfTokens =
      std::max(kMountinfoMountPointIndex, kMountinfoMountOptionsIndex) + 1;

  std::vector<std::string> lines =
      base::SplitString(mountinfo_data, "\n", base::TRIM_WHITESPACE,
                        base::SPLIT_WANT_NONEMPTY);

  for (const auto& line : lines) {
    std::vector<std::string> tokens =
        base::SplitString(line, base::kWhitespaceASCII, base::TRIM_WHITESPACE,
                          base::SPLIT_WANT_NONEMPTY);
    // Some fields in /proc/self/mountinfo are optional. We only need the line
    // to have |kMountinfoMinNumberOfTokens|.
    if (tokens.size() < kMountinfoMinNumberOfTokens)
      continue;
    if (tokens[kMountinfoMountPointIndex] != rootfs_path.value())
      continue;

    std::vector<std::string> options =
        base::SplitString(tokens[kMountinfoMountOptionsIndex], ",",
                          base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);

    return std::find(options.begin(), options.end(), "ro") != options.end();
  }

  LOG(WARNING) << "Did not find mount information for " << rootfs_path.value()
               << ". Assuming mounted read-only.";

  return true;
}

// Sets the rootfs of |config| to point to where the rootfs of the container
// is mounted.
bool ParseRootFileSystemConfig(const base::DictionaryValue& config_root_dict,
                               const base::FilePath& named_path,
                               const std::string& mountinfo_data,
                               ContainerConfigPtr* config_out) {
  // |rootfs_dict| stays owned by |config_root_dict|
  const base::DictionaryValue* rootfs_dict = nullptr;
  if (!config_root_dict.GetDictionary("root", &rootfs_dict)) {
    LOG(ERROR) << "Fail to parse rootfs dictionary from config";
    return false;
  }
  std::string rootfs_path;
  if (!rootfs_dict->GetString("path", &rootfs_path)) {
    LOG(ERROR) << "Fail to get rootfs path from config";
    return false;
  }
  container_config_rootfs(config_out->get(),
                          named_path.Append(rootfs_path).value().c_str());
  // Explicitly set the mount flags of the rootfs.
  //
  // In Chrome OS, the rootfs is mounted nosuid, nodev, noexec. We need the
  // filesystem to be mounted without those three flags within the container for
  // it to work correctly, so explicitly remount with none of those flags. We
  // need to preserve the ro/rw state of the original mount, though, since the
  // internal namespace will reflect whatever flag was passed here instead of
  // respecting the original filesystem's ro/rw state.
  uint32_t flags = 0;
  if (IsOriginalRootfsReadOnly(mountinfo_data,
                               named_path.Append(rootfs_path))) {
    flags |= MS_RDONLY;
  }
  container_config_rootfs_mount_flags(config_out->get(), flags);
  return true;
}

// Fills |config|, |uid|, and |gid| with information about the main process to
// run in the container and the user it should be run as.  |uid| and |gid|
// will be filled with IDs from the initial user namespace, not the IDs within
// the container.
bool ParseProcessConfig(const base::DictionaryValue& config_root_dict,
                        uid_t* uid_out,
                        gid_t* gid_out,
                        ContainerConfigPtr* config_out) {
  // |process_dict| stays owned by |config_root_dict|
  const base::DictionaryValue* process_dict = nullptr;
  if (!config_root_dict.GetDictionary("process", &process_dict)) {
    LOG(ERROR) << "Fail to get main process from config";
    return false;
  }
  // |user_dict| stays owned by |process_dict|
  const base::DictionaryValue* user_dict = nullptr;
  if (!process_dict->GetDictionary("user", &user_dict)) {
    LOG(ERROR) << "Failed to get user info from config";
    return false;
  }
  int uid_val;
  if (!user_dict->GetInteger("uid", &uid_val)) {
    LOG(ERROR) << "Failed to get uid info from config";
    return false;
  }
  container_config_uid(config_out->get(), uid_val);
  *uid_out = uid_val;
  int gid_val;
  if (!user_dict->GetInteger("gid", &gid_val)) {
    LOG(ERROR) << "Failed to get gid info from config";
    return false;
  }
  container_config_gid(config_out->get(), gid_val);
  *gid_out = gid_val;
  // |args_dict| stays owned by |process_dict|
  const base::ListValue* args_list = nullptr;
  if (!process_dict->GetList("args", &args_list)) {
    LOG(ERROR) << "Fail to get main process args from config";
    return false;
  }
  size_t num_args = args_list->GetSize();
  std::vector<std::string> argv_str(num_args);
  for (size_t i = 0; i < num_args; ++i) {
    if (!args_list->GetString(i, &argv_str[i])) {
      LOG(ERROR) << "Fail to get process args from config";
      return false;
    }
  }
  std::vector<const char*> argv(num_args);
  for (size_t i = 0; i < num_args; ++i) {
    argv[i] = argv_str[i].c_str();
  }
  container_config_program_argv(config_out->get(), argv.data(), argv.size());
  return true;
}

// Parses the mount options for a given mount.
bool ParseMountOptions(const base::ListValue& options,
                       std::string* option_string_out,
                       int* flags_out,
                       bool* mount_in_ns_out,
                       bool* create_mount_point_out,
                       bool* is_root_relative_out) {
  *flags_out = 0;
  *mount_in_ns_out = true;
  *create_mount_point_out = true;
  *option_string_out = "";
  *is_root_relative_out = false;
  for (size_t j = 0; j < options.GetSize(); ++j) {
    std::string this_opt;
    if (!options.GetString(j, &this_opt)) {
      LOG(ERROR) << "Fail to get option " << j << "from mount options";
      return false;
    }
    if (this_opt == "nodev") {
      *flags_out |= MS_NODEV;
    } else if (this_opt == "noexec") {
      *flags_out |= MS_NOEXEC;
    } else if (this_opt == "nosuid") {
      *flags_out |= MS_NOSUID;
    } else if (this_opt == "bind") {
      *flags_out |= MS_BIND;
    } else if (this_opt == "ro") {
      *flags_out |= MS_RDONLY;
    } else if (this_opt == "private") {
      *flags_out |= MS_PRIVATE;
    } else if (this_opt == "recursive") {
      *flags_out |= MS_REC;
    } else if (this_opt == "slave") {
      *flags_out |= MS_SLAVE;
    } else if (this_opt == "root_relative") {
      *is_root_relative_out = true;
    } else if (this_opt == "remount") {
      *flags_out |= MS_REMOUNT;
    } else if (this_opt == "mount_outside") {
      // This is a cros-specific option
      *mount_in_ns_out = 0;
    } else if (this_opt == "nocreate") {
      // This is a cros-specific option
      *create_mount_point_out = 0;
    } else {
      // Unknown options get appended to the string passed to mount data.
      if (!option_string_out->empty())
        *option_string_out += ",";
      *option_string_out += this_opt;
    }
  }
  return true;
}

// Parses the info about a mount named |mount_name| that is specified in the
// runtime mount dictionary and adds the mount to the given container
// configuration in |config_out|
bool ParseRuntimeMount(const base::DictionaryValue& runtime_mounts_dict,
                       const base::FilePath& named_path,
                       const std::string& mount_name,
                       const base::FilePath& destination_path,
                       uid_t uid,
                       gid_t gid,
                       ContainerConfigPtr* config_out) {
  // |mount_dict| is owned by |rutime_mounts_dict|
  const base::DictionaryValue* mount_dict = nullptr;
  if (!runtime_mounts_dict.GetDictionary(mount_name, &mount_dict)) {
    LOG(ERROR) << "Fail to get mount " << mount_name << " from runtime";
    return false;
  }

  std::string type;
  if (!mount_dict->GetString("type", &type)) {
    LOG(ERROR) << "Fail to get mount type from runtime";
    return false;
  }

  // |options| are owned by |mount_dict|
  const base::ListValue* options = nullptr;
  if (!mount_dict->GetList("options", &options)) {
    LOG(ERROR) << "Fail to get mount options from runtime";
    return false;
  }
  std::string option_string;
  int flags;
  bool mount_in_ns;
  bool create_mount_point;
  bool root_relative;
  if (!ParseMountOptions(*options, &option_string, &flags, &mount_in_ns,
                         &create_mount_point, &root_relative)) {
    LOG(ERROR) << "Failed to parse mount options for " << mount_name;
    return false;
  }

  std::string source;
  if (!mount_dict->GetString("source", &source)) {
    LOG(ERROR) << "Fail to get mount source from runtime";
    return false;
  }
  base::FilePath source_path(source);
  if ((flags & MS_BIND) && !root_relative) {
    // If it's not an absolute path, append it to the container config dir
    if (!source_path.IsAbsolute()) {
      source_path = named_path.Append(source_path);
    }
  }

  if (container_config_add_mount(config_out->get(),
                                 mount_name.c_str(),
                                 source_path.value().c_str(),
                                 destination_path.value().c_str(),
                                 type.c_str(),
                                 option_string.length() ? option_string.c_str()
                                     : NULL,
                                 flags,
                                 uid,
                                 gid,
                                 0,
                                 mount_in_ns,
                                 create_mount_point,
                                 0)) {
    LOG(ERROR) << "Failed to add mount " << mount_name << " to config";
    return false;
  }

  return true;
}

// Mount information is distributed between the config and the runtime files.
// Parse info from each of the structs to build the mount config and add it to
// the container configuration.
bool ParseMounts(const base::DictionaryValue& config_root_dict,
                 const base::DictionaryValue& runtime_root_dict,
                 const base::FilePath& named_path,
                 uid_t uid,
                 gid_t gid,
                 ContainerConfigPtr* config_out) {
  // |config_mounts_list| stays owned by |config_root_dict|
  const base::ListValue* config_mounts_list = nullptr;
  if (!config_root_dict.GetList("mounts", &config_mounts_list)) {
    LOG(ERROR) << "Fail to get mounts from config dictionary";
    return false;
  }
  // |runtime_mounts_dict| stays owned by |runtime_root_dict|
  const base::DictionaryValue* runtime_mounts_dict = nullptr;
  if (!runtime_root_dict.GetDictionary("mounts", &runtime_mounts_dict)) {
    LOG(ERROR) << "Fail to get mounts dictionary from runtime";
    return false;
  }

  for (size_t i = 0; i < config_mounts_list->GetSize(); i++) {
    const base::DictionaryValue* config_mounts_item;
    if (!config_mounts_list->GetDictionary(i, &config_mounts_item)) {
      LOG(ERROR) << "Fail to get mount list " << i << " from config";
      return false;
    }
    std::string mount_name;
    if (!config_mounts_item->GetString("name", &mount_name)) {
      LOG(ERROR) << "Fail to get mount name " << i << " from config";
      return false;
    }
    std::string destination;
    if (!config_mounts_item->GetString("path", &destination)) {
      LOG(ERROR) << "Fail to get mount path " << i << " from config";
      return false;
    }
    base::FilePath destination_path(destination);

    if (!ParseRuntimeMount(*runtime_mounts_dict, named_path, mount_name,
                           destination_path, uid, gid, config_out)) {
      LOG(ERROR) << "Failed to parse runtime mount info for mount " << i;
      return false;
    }
  }
  return true;
}

// Parse the list of device nodes that the container needs to run.  |config|
// will have all the devices listed in |linux_dict| added to a list that creates
// and sets permissions for them when the container starts.
bool ParseDeviceList(const base::DictionaryValue& linux_dict,
                     ContainerConfigPtr* config_out) {
  // |device_list| is owned by |linux_dict|
  const base::ListValue* device_list = nullptr;
  if (!linux_dict.GetList("devices", &device_list)) {
    LOG(ERROR) << "Fail to get device list";
    return false;
  }
  size_t num_devices = device_list->GetSize();
  for (size_t i = 0; i < num_devices; ++i) {
    const base::DictionaryValue* dev;
    if (!device_list->GetDictionary(i, &dev)) {
      LOG(ERROR) << "Fail to get device " << i;
      return false;
    }
    std::string path;
    if (!dev->GetString("path", &path)) {
      LOG(ERROR) << "Fail to get path for " << path;
      return false;
    }
    int type;
    if (!dev->GetInteger("type", &type)) {
      LOG(ERROR) << "Fail to get type for " << path;
      return false;
    }
    // Only 'c' and 'b' device types supported.
    if (type != 'b' && type != 'c') {
      LOG(ERROR) << "Invalid device type for " << path;
      return false;
    }
    int major;
    if (!dev->GetInteger("major", &major)) {
      LOG(ERROR) << "Fail to get major id of " << path;
      return false;
    }
    int minor;
    if (!dev->GetInteger("minor", &minor)) {
      LOG(ERROR) << "Fail to get minor id of " << path;
      return false;
    }
    // If minor is negative, mirror the current device.
    // This is a cros-specific extension.
    int copy_minor = 0;
    if (path != "nodev" && minor < 0)
      copy_minor = 1;
    std::string permissions;
    if (!dev->GetString("permissions", &permissions)) {
      LOG(ERROR) << "Fail to get device permissions of " << path;
      return false;
    }
    int read_allowed = (permissions.find('r') != std::string::npos);
    int write_allowed = (permissions.find('w') != std::string::npos);
    int modify_allowed = (permissions.find('m') != std::string::npos);
    int fs_permissions;
    if (!dev->GetInteger("fileMode", &fs_permissions)) {
      LOG(ERROR) << "Fail to get permissions of " << path;
      return false;
    }
    int dev_uid;
    if (!dev->GetInteger("uid", &dev_uid)) {
      LOG(ERROR) << "Fail to get uid of " << path;
      return false;
    }
    int dev_gid;
    if (!dev->GetInteger("gid", &dev_gid)) {
      LOG(ERROR) << "Fail to get gid of " << path;
      return false;
    }

    container_config_add_device(config_out->get(),
                                type,
                                path.c_str(),
                                fs_permissions,
                                major,
                                minor,
                                copy_minor,
                                dev_uid,
                                dev_gid,
                                read_allowed,
                                write_allowed,
                                modify_allowed);
  }

  return true;
}

// Parse the CPU cgroup settings for the container.
// CPU cgroup params are optional.
bool ParseCpuDict(const base::DictionaryValue& linux_dict,
                  ContainerConfigPtr* config_out) {
  // |cpu_dict| is owned by |linux_dict|.
  const base::DictionaryValue* cpu_dict = nullptr;
  if (!linux_dict.GetDictionary("cpu", &cpu_dict))
    return false;

  int shares;
  if (cpu_dict->GetInteger("shares", &shares))
    container_config_set_cpu_shares(config_out->get(), shares);

  int quota, period;
  if (cpu_dict->GetInteger("quota", &quota) &&
      cpu_dict->GetInteger("period", &period)) {
    container_config_set_cpu_cfs_params(config_out->get(), quota, period);
  }

  int rt_runtime, rt_period;
  if (cpu_dict->GetInteger("realtimeRuntime", &rt_runtime) &&
      cpu_dict->GetInteger("realtimePeriod", &rt_period)) {
    container_config_set_cpu_rt_params(config_out->get(),
                                       rt_runtime,
                                       rt_period);
  }

  return true;
}

// Parses the linux node which has information about setting up a user
// namespace, alt-syscall table and the list of devices for the container.
bool ParseLinuxConfigDict(const base::DictionaryValue& runtime_root_dict,
                          ContainerConfigPtr* config_out) {
  // |linux_dict| is owned by |runtime_root_dict|
  const base::DictionaryValue* linux_dict = nullptr;
  if (!runtime_root_dict.GetDictionary("linux", &linux_dict)) {
    LOG(ERROR) << "Fail to get linux dictionary from the runtime dictionary";
    return false;
  }

  // User mappings for configuring a user namespace.
  std::string uid_map;
  if (!linux_dict->GetString("uidMappings", &uid_map)) {
    LOG(ERROR) << "Fail to get uid map from the runtime dictionary";
    return false;
  }
  container_config_uid_map(config_out->get(), uid_map.c_str());

  // Group mappings
  std::string gid_map;
  if (!linux_dict->GetString("gidMappings", &gid_map)) {
    LOG(ERROR) << "Fail to get gid map from the runtime dictionary";
    return false;
  }
  container_config_gid_map(config_out->get(), gid_map.c_str());

  // alt-syscall table is a cros-specific entry.
  std::string syscall_table;
  if (!linux_dict->GetString("altSysCallTable", &syscall_table)) {
    LOG(ERROR) << "No altSysCallTable specified";
    return false;
  }
  container_config_alt_syscall_table(config_out->get(), syscall_table.c_str());

  if (!ParseDeviceList(*linux_dict, config_out))
    return false;

  // CPU cgroup params are optional.
  ParseCpuDict(*linux_dict, config_out);

  return true;
}

// Parses the configuration file for the container.  The config file specifies
// basic filesystem info and details about the process to be run.  More specific
// information is gathered from the runtime config file.  In the runtime file
// most of the details come from the "linux" node.  They specify namespace,
// cgroup, and syscall configurations that are critical to keeping the process
// sandboxed.
bool ParseConfigDicts(const base::DictionaryValue& config_root_dict,
                      const base::DictionaryValue& runtime_root_dict,
                      const base::FilePath& named_path,
                      const std::string& mountinfo_data,
                      ContainerConfigPtr* config_out) {
  // Root fs info
  if (!ParseRootFileSystemConfig(config_root_dict, named_path,
                                 mountinfo_data, config_out)) {
    return false;
  }

  // Process info
  uid_t uid;
  gid_t gid;
  if (!ParseProcessConfig(config_root_dict, &uid, &gid, config_out))
    return false;

  // Get a list of mount points and mounts from the config dictionary.
  // The details are filled in while parsing the runtime dictionary.
  if (!ParseMounts(config_root_dict, runtime_root_dict, named_path,
                   uid, gid, config_out)) {
    LOG(ERROR) << "Failed to parse mounts of " << named_path.value();
    return false;
  }

  // Parse linux node.
  if (!ParseLinuxConfigDict(runtime_root_dict, config_out)) {
    LOG(ERROR) << "Failed to parse the linux node of " << named_path.value();
    return false;
  }

  return true;
}

}  // anonymous namespace

bool ParseContainerConfig(const std::string& config_json_data,
                          const std::string& runtime_json_data,
                          const std::string& mountinfo_data,
                          const std::string& container_name,
                          const std::string& parent_cgroup_name,
                          const base::FilePath& named_container_path,
                          ContainerConfigPtr* config_out) {
  // Basic config info comes from config.json
  std::unique_ptr<const base::Value> config_root_val =
      base::JSONReader::Read(config_json_data);
  if (!config_root_val) {
    LOG(ERROR) << "Fail to parse config for " << container_name;
    return false;
  }
  const base::DictionaryValue* config_dict = nullptr;
  if (!config_root_val->GetAsDictionary(&config_dict)) {
    LOG(ERROR) << "Fail to parse root dictionary from config for "
               << container_name;
    return false;
  }

  // Use runtime.json to complete the config struct.
  std::unique_ptr<const base::Value> runtime_root_val =
      base::JSONReader::Read(runtime_json_data);
  if (!runtime_root_val) {
    LOG(ERROR) << "Fail to parse runtime for " << container_name;
    return false;
  }
  const base::DictionaryValue* runtime_dict = nullptr;
  if (!runtime_root_val->GetAsDictionary(&runtime_dict)) {
    LOG(ERROR) << "Fail to parse root dictionary from runtime for "
               << container_name;
    return false;
  }
  if (!ParseConfigDicts(*config_dict, *runtime_dict, named_container_path,
                        mountinfo_data, config_out)) {
    return false;
  }

  // Set the cgroup configuration
  if (container_config_set_cgroup_parent(
          config_out->get(), parent_cgroup_name.c_str(),
          container_config_get_uid(config_out->get()),
          container_config_get_gid(config_out->get()))) {
    LOG(ERROR) << "Failed to configure cgroup structure of " << container_name;
    return false;
  }

  // Hack for android containers that need selinux commands run.
  if (container_name.find("android") != std::string::npos) {
    if (container_config_run_setfiles(config_out->get(), "/sbin/setfiles")) {
      LOG(ERROR) << "Fail to set setfiles for "
                 << container_name;
      return false;
    }
  }

  return true;
}

}  // namespace login_manager
