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

#include <linux/securebits.h>
#include <sys/capability.h>
#include <sys/mount.h>
#include <sys/resource.h>
#include <unistd.h>

#include <map>
#include <regex>  // NOLINT(build/c++11)
#include <string>
#include <utility>
#include <vector>

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

namespace run_oci {

namespace {

// Gets an integer from the given dictionary.
template <typename T>
bool ParseIntFromDict(const base::Value& dict, const char* name, T* val_out) {
  base::Optional<double> double_val = dict.FindDoubleKey(name);
  if (!double_val.has_value()) {
    return false;
  }
  *val_out = static_cast<T>(*double_val);
  return true;
}

// Parse a list-type Value structure as vector of integers.
template <typename T>
bool ParseIntList(const base::Value& list_val, std::vector<T>* val_out) {
  for (const base::Value& entry : list_val.GetList()) {
    if (!entry.is_double() && !entry.is_int()) {
      return false;
    }
    val_out->emplace_back(static_cast<T>(entry.GetDouble()));
  }
  return true;
}

// Parses basic platform configuration.
bool ParsePlatformConfig(const base::Value& config_root_dict,
                         OciConfigPtr const& config_out) {
  // |platform_dict| stays owned by |config_root_dict|
  const base::Value* platform_dict = config_root_dict.FindDictKey("platform");
  if (!platform_dict) {
    LOG(ERROR) << "Fail to parse platform dictionary from config";
    return false;
  }

  const std::string* os = platform_dict->FindStringKey("os");
  if (!os) {
    return false;
  }
  config_out->platform.os = *os;

  const std::string* arch = platform_dict->FindStringKey("arch");
  if (!arch) {
    return false;
  }
  config_out->platform.arch = *arch;

  return true;
}

// Parses root fs info.
bool ParseRootFileSystemConfig(const base::Value& config_root_dict,
                               OciConfigPtr const& config_out) {
  // |rootfs_dict| stays owned by |config_root_dict|
  const base::Value* rootfs_dict = config_root_dict.FindDictKey("root");
  if (!rootfs_dict) {
    LOG(ERROR) << "Fail to parse rootfs dictionary from config";
    return false;
  }
  const std::string* path = rootfs_dict->FindStringKey("path");
  if (!path) {
    LOG(ERROR) << "Fail to get rootfs path from config";
    return false;
  }
  config_out->root.path = base::FilePath(*path);
  base::Optional<bool> read_only = rootfs_dict->FindBoolKey("readonly");
  if (read_only.has_value())
    config_out->root.readonly = *read_only;
  return true;
}

// Fills |config_out| with information about the capability sets in the
// container.
bool ParseCapabilitiesConfig(const base::Value& capabilities_dict,
                             std::map<std::string, CapSet>* config_out) {
  constexpr const char* kCapabilitySetNames[] = {
      "effective", "bounding", "inheritable", "permitted", "ambient"};
  const std::string kAmbientCapabilitySetName = "ambient";

  CapSet caps_superset;
  for (const char* set_name : kCapabilitySetNames) {
    // |capset_list| stays owned by |capabilities_dict|.
    const base::Value* capset_list = capabilities_dict.FindListKey(set_name);
    if (!capset_list)
      continue;
    CapSet caps;
    cap_value_t cap_value;
    for (const auto& cap_name_value : capset_list->GetList()) {
      if (!cap_name_value.is_string()) {
        LOG(ERROR) << "Capability list " << set_name
                   << " contains a non-string";
        return false;
      }
      std::string cap_name = cap_name_value.GetString();
      if (cap_from_name(cap_name.c_str(), &cap_value) == -1) {
        LOG(ERROR) << "Unrecognized capability name: " << cap_name;
        return false;
      }
      caps[cap_value] = true;
    }
    (*config_out)[set_name] = caps;
    caps_superset = caps;
  }

  // We currently only support sets that are identical, except that ambient is
  // optional.
  for (const char* set_name : kCapabilitySetNames) {
    auto it = config_out->find(set_name);
    if (it == config_out->end() && set_name == kAmbientCapabilitySetName) {
      // Ambient capabilities are optional.
      continue;
    }
    if (it == config_out->end()) {
      LOG(ERROR)
          << "If capabilities are set, all capability sets should be present";
      return false;
    }
    if (it->second != caps_superset) {
      LOG(ERROR)
          << "If capabilities are set, all capability sets should be identical";
      return false;
    }
  }

  return true;
}

const std::map<std::string, int> kRlimitMap = {
#define RLIMIT_MAP_ENTRY(limit) \
  { "RLIMIT_" #limit, RLIMIT_##limit }
    RLIMIT_MAP_ENTRY(CPU),      RLIMIT_MAP_ENTRY(FSIZE),
    RLIMIT_MAP_ENTRY(DATA),     RLIMIT_MAP_ENTRY(STACK),
    RLIMIT_MAP_ENTRY(CORE),     RLIMIT_MAP_ENTRY(RSS),
    RLIMIT_MAP_ENTRY(NPROC),    RLIMIT_MAP_ENTRY(NOFILE),
    RLIMIT_MAP_ENTRY(MEMLOCK),  RLIMIT_MAP_ENTRY(AS),
    RLIMIT_MAP_ENTRY(LOCKS),    RLIMIT_MAP_ENTRY(SIGPENDING),
    RLIMIT_MAP_ENTRY(MSGQUEUE), RLIMIT_MAP_ENTRY(NICE),
    RLIMIT_MAP_ENTRY(RTPRIO),   RLIMIT_MAP_ENTRY(RTTIME),
#undef RLIMIT_MAP_ENTRY
};

// Fills |config_out| with information about the capability sets in the
// container.
bool ParseRlimitsConfig(const base::Value& rlimits_list,
                        std::vector<OciProcessRlimit>* rlimits_out) {
  size_t num_limits = rlimits_list.GetList().size();
  for (size_t i = 0; i < num_limits; ++i) {
    const base::Value& rlimits_dict = rlimits_list.GetList()[i];
    if (!rlimits_dict.is_dict()) {
      LOG(ERROR) << "Fail to get rlimit item " << i;
      return false;
    }

    const std::string* rlimit_name = rlimits_dict.FindStringKey("type");
    if (!rlimit_name) {
      LOG(ERROR) << "Fail to get type of rlimit " << i;
      return false;
    }
    const auto it = kRlimitMap.find(*rlimit_name);
    if (it == kRlimitMap.end()) {
      LOG(ERROR) << "Unrecognized rlimit name: " << *rlimit_name;
      return false;
    }

    OciProcessRlimit limit;
    limit.type = it->second;
    if (!ParseIntFromDict(rlimits_dict, "hard", &limit.hard)) {
      LOG(ERROR) << "Fail to get hard limit of rlimit " << i;
      return false;
    }
    if (!ParseIntFromDict(rlimits_dict, "soft", &limit.soft)) {
      LOG(ERROR) << "Fail to get soft limit of rlimit " << i;
      return false;
    }
    rlimits_out->push_back(limit);
  }

  return true;
}

// Fills |config_out| with information about the main process to run in the
// container and the user it should be run as.
bool ParseProcessConfig(const base::Value& config_root_dict,
                        OciConfigPtr const& config_out) {
  // |process_dict| stays owned by |config_root_dict|
  const base::Value* process_dict = config_root_dict.FindDictKey("process");
  if (!process_dict) {
    LOG(ERROR) << "Fail to get main process from config";
    return false;
  }
  base::Optional<bool> terminal = process_dict->FindBoolKey("terminal");
  if (terminal.has_value())
    config_out->process.terminal = *terminal;
  // |user_dict| stays owned by |process_dict|
  const base::Value* user_dict = process_dict->FindDictKey("user");
  if (!user_dict) {
    LOG(ERROR) << "Failed to get user info from config";
    return false;
  }
  if (!ParseIntFromDict(*user_dict, "uid", &config_out->process.user.uid))
    return false;
  if (!ParseIntFromDict(*user_dict, "gid", &config_out->process.user.gid))
    return false;

  // If additionalGids field is specified, parse it as a valid list of integers.
  const base::Value* list_val = user_dict->FindListKey("additionalGids");
  if (list_val &&
      !ParseIntList(*list_val, &config_out->process.user.additionalGids)) {
    LOG(ERROR) << "Invalid process.user.additionalGids";
    return false;
  }

  // |args_list| stays owned by |process_dict|
  const base::Value* args_list = process_dict->FindListKey("args");
  if (!args_list) {
    LOG(ERROR) << "Fail to get main process args from config";
    return false;
  }
  for (const auto& arg : args_list->GetList()) {
    if (!arg.is_string()) {
      LOG(ERROR) << "Fail to get process args from config";
      return false;
    }
    config_out->process.args.push_back(arg.GetString());
  }
  // |env_list| stays owned by |process_dict|
  const base::Value* env_list = process_dict->FindListKey("env");
  if (env_list) {
    for (const auto& env_value : env_list->GetList()) {
      if (!env_value.is_string()) {
        LOG(ERROR) << "Fail to get process env from config";
        return false;
      }
      const std::string& env = env_value.GetString();
      std::vector<std::string> kvp = base::SplitString(
          env, "=", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
      if (kvp.size() != 2) {
        LOG(ERROR) << "Fail to parse env \"" << env
                   << "\". Must be in name=value format.";
        return false;
      }
      config_out->process.env.insert(std::make_pair(kvp[0], kvp[1]));
    }
  }
  const std::string* path = process_dict->FindStringKey("cwd");
  if (!path) {
    LOG(ERROR) << "failed to get cwd of process";
    return false;
  }
  config_out->process.cwd = base::FilePath(*path);
  base::Optional<int> umask_int = process_dict->FindIntKey("umask");
  if (umask_int.has_value())
    config_out->process.umask = static_cast<mode_t>(*umask_int);
  else
    config_out->process.umask = 0022;  // Optional

  // selinuxLabel is optional.
  const std::string* selinux_label =
      process_dict->FindStringKey("selinuxLabel");
  if (selinux_label)
    config_out->process.selinuxLabel = *selinux_label;
  // |capabilities_dict| stays owned by |process_dict|
  const base::Value* capabilities_dict =
      process_dict->FindDictKey("capabilities");
  if (capabilities_dict) {
    if (!ParseCapabilitiesConfig(*capabilities_dict,
                                 &config_out->process.capabilities)) {
      return false;
    }
  }

  // |rlimit_list| stays owned by |process_dict|
  const base::Value* rlimits_list = process_dict->FindListKey("rlimits");
  if (rlimits_list) {
    if (!ParseRlimitsConfig(*rlimits_list, &config_out->process.rlimits)) {
      return false;
    }
  }

  return true;
}

// Parses the 'mounts' field.  The necessary mounts for running the container
// are specified here.
bool ParseMounts(const base::Value& config_root_dict,
                 OciConfigPtr const& config_out) {
  // |config_mounts_list| stays owned by |config_root_dict|
  const base::Value* config_mounts_list =
      config_root_dict.FindListKey("mounts");
  if (!config_mounts_list) {
    LOG(ERROR) << "Fail to get mounts from config dictionary";
    return false;
  }

  for (size_t i = 0; i < config_mounts_list->GetList().size(); ++i) {
    const base::Value& mount_dict = config_mounts_list->GetList()[i];
    if (!mount_dict.is_dict()) {
      LOG(ERROR) << "Fail to get mount item " << i;
      return false;
    }
    OciMount mount;
    const std::string* path = mount_dict.FindStringKey("destination");
    if (!path) {
      LOG(ERROR) << "Fail to get mount path for mount " << i;
      return false;
    }
    mount.destination = base::FilePath(*path);
    const std::string* type = mount_dict.FindStringKey("type");
    if (!type) {
      LOG(ERROR) << "Fail to get mount type for mount " << i;
      return false;
    }
    mount.type = *type;
    const std::string* source = mount_dict.FindStringKey("source");
    if (!source) {
      LOG(ERROR) << "Fail to get mount source for mount " << i;
      return false;
    }
    mount.source = base::FilePath(*source);
    base::Optional<bool> intermediate_namespace =
        mount_dict.FindBoolKey("performInIntermediateNamespace");
    mount.performInIntermediateNamespace =
        intermediate_namespace.value_or(false);

    // |options| are owned by |mount_dict|
    const base::Value* options = mount_dict.FindListKey("options");
    if (options) {
      for (size_t j = 0; j < options->GetList().size(); ++j) {
        const base::Value& this_opt = options->GetList()[j];
        if (!this_opt.is_string()) {
          LOG(ERROR) << "Fail to get option " << j << " from mount options";
          return false;
        }
        mount.options.push_back(this_opt.GetString());
      }
    }

    config_out->mounts.push_back(mount);
  }
  return true;
}

// Parses the linux resource list
bool ParseResources(const base::Value& resources_dict,
                    OciLinuxResources* resources_out) {
  // |device_list| is owned by |resources_dict|
  const base::Value* device_list = resources_dict.FindListKey("devices");
  if (!device_list) {
    // The device list is optional.
    return true;
  }
  size_t num_devices = device_list->GetList().size();
  for (size_t i = 0; i < num_devices; ++i) {
    OciLinuxCgroupDevice device;

    const base::Value& dev = device_list->GetList()[i];
    if (!dev.is_dict()) {
      LOG(ERROR) << "Fail to get device " << i;
      return false;
    }

    base::Optional<bool> allow = dev.FindBoolKey("allow");
    if (!allow.has_value()) {
      LOG(ERROR) << "Fail to get allow value for device " << i;
      return false;
    }
    device.allow = *allow;
    const std::string* access = dev.FindStringKey("access");
    // Optional, default to all perms.
    device.access = access ? *access : "rwm";
    const std::string* type = dev.FindStringKey("type");
    // Optional, default to both a means all.
    device.type = type ? *type : "a";
    if (!ParseIntFromDict(dev, "major", &device.major))
      device.major = -1;  // Optional, -1 will map to all devices.
    if (!ParseIntFromDict(dev, "minor", &device.minor))
      device.minor = -1;  // Optional, -1 will map to all devices.

    resources_out->devices.push_back(device);
  }

  return true;
}

// Parses the list of namespaces and fills |namespaces_out| with them.
bool ParseNamespaces(const base::Value* namespaces_list,
                     std::vector<OciNamespace>* namespaces_out) {
  for (size_t i = 0; i < namespaces_list->GetList().size(); ++i) {
    OciNamespace new_namespace;
    const base::Value& ns = namespaces_list->GetList()[i];
    if (!ns.is_dict()) {
      LOG(ERROR) << "Failed to get namespace " << i;
      return false;
    }
    const std::string* type = ns.FindStringKey("type");
    if (!type) {
      LOG(ERROR) << "Namespace " << i << " missing type";
      return false;
    }
    new_namespace.type = *type;
    const std::string* path = ns.FindStringKey("path");
    if (path)
      new_namespace.path = base::FilePath(*path);
    namespaces_out->push_back(new_namespace);
  }
  return true;
}

// Parse the list of device nodes that the container needs to run.
bool ParseDeviceList(const base::Value& linux_dict,
                     OciConfigPtr const& config_out) {
  // |device_list| is owned by |linux_dict|
  const base::Value* device_list = linux_dict.FindListKey("devices");
  if (!device_list) {
    // The device list is optional.
    return true;
  }
  size_t num_devices = device_list->GetList().size();
  for (size_t i = 0; i < num_devices; ++i) {
    OciLinuxDevice device;

    const base::Value& dev = device_list->GetList()[i];
    if (!dev.is_dict()) {
      LOG(ERROR) << "Fail to get device " << i;
      return false;
    }
    const std::string* path = dev.FindStringKey("path");
    if (!path) {
      LOG(ERROR) << "Fail to get path for dev";
      return false;
    }
    device.path = base::FilePath(*path);
    const std::string* type = dev.FindStringKey("type");
    if (!type) {
      LOG(ERROR) << "Fail to get type for " << device.path.value();
      return false;
    }
    device.type = *type;
    base::Optional<bool> dynamic_major = dev.FindBoolKey("dynamicMajor");
    if (dynamic_major.has_value())
      device.dynamicMajor = *dynamic_major;
    if (device.dynamicMajor) {
      if (dev.FindKey("major")) {
        LOG(WARNING)
            << "Ignoring \"major\" since \"dynamicMajor\" is specified for "
            << device.path.value();
      }
    } else {
      if (!ParseIntFromDict(dev, "major", &device.major))
        return false;
    }

    base::Optional<bool> dynamic_minor = dev.FindBoolKey("dynamicMinor");
    if (dynamic_minor.has_value())
      device.dynamicMinor = *dynamic_minor;
    if (device.dynamicMinor) {
      if (dev.FindKey("minor")) {
        LOG(WARNING)
            << "Ignoring \"minor\" since \"dynamicMinor\" is specified for "
            << device.path.value();
      }
    } else {
      if (!ParseIntFromDict(dev, "minor", &device.minor))
        return false;
    }
    if (!ParseIntFromDict(dev, "fileMode", &device.fileMode))
      return false;
    if (!ParseIntFromDict(dev, "uid", &device.uid))
      return false;
    if (!ParseIntFromDict(dev, "gid", &device.gid))
      return false;

    config_out->linux_config.devices.push_back(device);
  }

  return true;
}

// Parses the list of ID mappings and fills |mappings_out| with them.
bool ParseLinuxIdMappings(const base::Value* id_map_list,
                          std::vector<OciLinuxNamespaceMapping>* mappings_out) {
  for (size_t i = 0; i < id_map_list->GetList().size(); ++i) {
    const base::Value& map = id_map_list->GetList()[i];
    if (!map.is_dict()) {
      LOG(ERROR) << "Fail to get id map " << i;
      return false;
    }
    OciLinuxNamespaceMapping new_map;
    if (!ParseIntFromDict(map, "hostID", &new_map.hostID))
      return false;
    if (!ParseIntFromDict(map, "containerID", &new_map.containerID))
      return false;
    if (!ParseIntFromDict(map, "size", &new_map.size))
      return false;
    mappings_out->push_back(new_map);
  }
  return true;
}

// Parses seccomp syscall args.
bool ParseSeccompArgs(const base::Value& syscall_dict,
                      OciSeccompSyscall* syscall_out) {
  const base::Value* args = syscall_dict.FindListKey("args");
  if (args) {
    for (const auto& args_dict : args->GetList()) {
      if (!args_dict.is_dict()) {
        LOG(ERROR) << "Failed to pars args dict for " << syscall_out->name;
        return false;
      }
      OciSeccompArg this_arg;
      if (!ParseIntFromDict(args_dict, "index", &this_arg.index))
        return false;
      if (!ParseIntFromDict(args_dict, "value", &this_arg.value))
        return false;
      if (!ParseIntFromDict(args_dict, "value2", &this_arg.value2))
        return false;
      const std::string* op = args_dict.FindStringKey("op");
      if (!op) {
        LOG(ERROR) << "Failed to parse op for arg " << this_arg.index << " of "
                   << syscall_out->name;
        return false;
      }
      this_arg.op = *op;
      syscall_out->args.push_back(this_arg);
    }
  }
  return true;
}

// Parses the seccomp node if it is present.
bool ParseSeccompInfo(const base::Value& seccomp_dict,
                      OciSeccomp* seccomp_out) {
  const std::string* default_action =
      seccomp_dict.FindStringKey("defaultAction");
  if (!default_action)
    return false;
  seccomp_out->defaultAction = *default_action;
  // Gets the list of architectures.
  const base::Value* architectures = seccomp_dict.FindListKey("architectures");
  if (!architectures) {
    LOG(ERROR) << "Fail to read seccomp architectures";
    return false;
  }
  for (const auto& this_arch : architectures->GetList()) {
    if (!this_arch.is_string()) {
      LOG(ERROR) << "Fail to parse seccomp architecture list";
      return false;
    }
    seccomp_out->architectures.push_back(this_arch.GetString());
  }

  // Gets the list of syscalls.
  const base::Value* syscalls = seccomp_dict.FindListKey("syscalls");
  if (!syscalls) {
    LOG(ERROR) << "Fail to read seccomp syscalls";
    return false;
  }
  for (size_t i = 0; i < syscalls->GetList().size(); ++i) {
    const base::Value& syscall_dict = syscalls->GetList()[i];
    if (!syscall_dict.is_dict()) {
      LOG(ERROR) << "Fail to parse seccomp syscalls list";
      return false;
    }
    OciSeccompSyscall this_syscall;
    const std::string* name = syscall_dict.FindStringKey("name");
    if (!name) {
      LOG(ERROR) << "Fail to parse syscall name " << i;
      return false;
    }
    this_syscall.name = *name;
    const std::string* action = syscall_dict.FindStringKey("action");
    if (!action) {
      LOG(ERROR) << "Fail to parse syscall action for " << this_syscall.name;
      return false;
    }
    this_syscall.action = *action;
    if (!ParseSeccompArgs(syscall_dict, &this_syscall))
      return false;
    seccomp_out->syscalls.push_back(this_syscall);
  }

  return true;
}

constexpr std::pair<const char*, int> kMountPropagationMapping[] = {
    {"rprivate", MS_PRIVATE | MS_REC}, {"private", MS_PRIVATE},
    {"rslave", MS_SLAVE | MS_REC},     {"slave", MS_SLAVE},
    {"rshared", MS_SHARED | MS_REC},   {"shared", MS_SHARED},
    {"", MS_SLAVE | MS_REC},  // Default value.
};

bool ParseMountPropagationFlags(const std::string& propagation,
                                int* propagation_flags_out) {
  for (const auto& entry : kMountPropagationMapping) {
    if (propagation == entry.first) {
      *propagation_flags_out = entry.second;
      return true;
    }
  }
  LOG(ERROR) << "Unrecognized mount propagation flags: " << propagation;
  return false;
}

constexpr std::pair<const char*, uint64_t> kSecurebitsMapping[] = {
#define SECUREBIT_MAP_ENTRY(secbit) \
  { #secbit, SECBIT_##secbit }
    SECUREBIT_MAP_ENTRY(NOROOT),
    SECUREBIT_MAP_ENTRY(NOROOT_LOCKED),
    SECUREBIT_MAP_ENTRY(NO_SETUID_FIXUP),
    SECUREBIT_MAP_ENTRY(NO_SETUID_FIXUP_LOCKED),
    SECUREBIT_MAP_ENTRY(KEEP_CAPS),
    SECUREBIT_MAP_ENTRY(KEEP_CAPS_LOCKED),
#if defined(SECBIT_NO_CAP_AMBIENT_RAISE)
    // Kernels < v4.4 do not have this.
    SECUREBIT_MAP_ENTRY(NO_CAP_AMBIENT_RAISE),
    SECUREBIT_MAP_ENTRY(NO_CAP_AMBIENT_RAISE_LOCKED),
#endif  // SECBIT_NO_CAP_AMBIENT_RAISE
#undef SECUREBIT_MAP_ENTRY
};

bool ParseSecurebit(const std::string& securebit_name, uint64_t* mask_out) {
  for (const auto& entry : kSecurebitsMapping) {
    if (securebit_name == entry.first) {
      *mask_out = entry.second;
      return true;
    }
  }
  LOG(ERROR) << "Unrecognized securebit name: " << securebit_name;
  return false;
}

bool ParseSkipSecurebitsMask(const base::Value& skip_securebits_list,
                             uint64_t* securebits_mask_out) {
  size_t num_securebits = skip_securebits_list.GetList().size();
  for (size_t i = 0; i < num_securebits; ++i) {
    const base::Value& securebit_name = skip_securebits_list.GetList()[i];
    if (!securebit_name.is_string()) {
      LOG(ERROR) << "Fail to get securebit name " << i;
      return false;
    }
    uint64_t mask = 0;
    if (!ParseSecurebit(securebit_name.GetString(), &mask))
      return false;
    *securebits_mask_out |= mask;
  }
  return true;
}

// Parses the cpu node if it is present.
bool ParseCpuInfo(const base::Value& cpu_dict, OciCpu* cpu_out) {
  ParseIntFromDict(cpu_dict, "shares", &cpu_out->shares);
  ParseIntFromDict(cpu_dict, "quota", &cpu_out->quota);
  ParseIntFromDict(cpu_dict, "period", &cpu_out->period);
  ParseIntFromDict(cpu_dict, "realtimeRuntime", &cpu_out->realtimeRuntime);
  ParseIntFromDict(cpu_dict, "realtimePeriod", &cpu_out->realtimePeriod);
  return true;
}

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

  // |uid_map_list| is owned by |linux_dict|
  const base::Value* uid_map_list = linux_dict->FindListKey("uidMappings");
  if (uid_map_list)
    ParseLinuxIdMappings(uid_map_list, &config_out->linux_config.uidMappings);

  // |gid_map_list| is owned by |linux_dict|
  const base::Value* gid_map_list = linux_dict->FindListKey("gidMappings");
  if (gid_map_list)
    ParseLinuxIdMappings(gid_map_list, &config_out->linux_config.gidMappings);

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

  const base::Value* resources_dict = linux_dict->FindDictKey("resources");
  if (resources_dict) {
    if (!ParseResources(*resources_dict, &config_out->linux_config.resources))
      return false;
  }

  const base::Value* namespaces_list = linux_dict->FindListKey("namespaces");
  if (namespaces_list) {
    if (!ParseNamespaces(namespaces_list, &config_out->linux_config.namespaces))
      return false;
  }

  const base::Value* seccomp_dict = linux_dict->FindDictKey("seccomp");
  if (seccomp_dict) {
    if (!ParseSeccompInfo(*seccomp_dict, &config_out->linux_config.seccomp))
      return false;
  }

  const std::string* rootfs_propagation_string =
      linux_dict->FindStringKey("rootfsPropagation");
  if (!ParseMountPropagationFlags(
          rootfs_propagation_string ? *rootfs_propagation_string
                                    : base::EmptyString(),  // Optional
          &config_out->linux_config.rootfsPropagation)) {
    return false;
  }

  const std::string* cgroups_path_string =
      linux_dict->FindStringKey("cgroupsPath");
  if (cgroups_path_string)
    config_out->linux_config.cgroupsPath = base::FilePath(*cgroups_path_string);

  const std::string* alt_syscall = linux_dict->FindStringKey("altSyscall");
  config_out->linux_config.altSyscall =
      alt_syscall ? *alt_syscall : base::EmptyString();  // Optional

  base::Optional<bool> core_sched = linux_dict->FindBoolKey("coreSched");
  config_out->linux_config.coreSched = core_sched.value_or(false);  // Optional

  const base::Value* skip_securebits_list =
      linux_dict->FindListKey("skipSecurebits");
  if (skip_securebits_list) {
    if (!ParseSkipSecurebitsMask(*skip_securebits_list,
                                 &config_out->linux_config.skipSecurebits)) {
      return false;
    }
  } else {
    config_out->linux_config.skipSecurebits = 0;  // Optional
  }

  const base::Value* cpu_dict = linux_dict->FindDictKey("cpu");
  if (cpu_dict) {
    if (!ParseCpuInfo(*cpu_dict, &config_out->linux_config.cpu))
      return false;
  }

  return true;
}

bool HostnameValid(const std::string& hostname) {
  if (hostname.length() > 255)
    return false;

  const std::regex name("^[0-9a-zA-Z]([0-9a-zA-Z-]*[0-9a-zA-Z])?$");
  if (!std::regex_match(hostname, name))
    return false;

  const std::regex double_dash("--");
  if (std::regex_match(hostname, double_dash))
    return false;

  return true;
}

bool ParseHooksList(const base::Value& hooks_list,
                    std::vector<OciHook>* hooks_out,
                    const std::string& hook_type) {
  size_t num_hooks = hooks_list.GetList().size();
  for (size_t i = 0; i < num_hooks; ++i) {
    OciHook hook;
    const base::Value& hook_dict = hooks_list.GetList()[i];
    if (!hook_dict.is_dict()) {
      LOG(ERROR) << "Fail to get " << hook_type << " hook item " << i;
      return false;
    }

    const std::string* path = hook_dict.FindStringPath("path");
    if (!path) {
      LOG(ERROR) << "Fail to get path of " << hook_type << " hook " << i;
      return false;
    }
    hook.path = base::FilePath(*path);

    const base::Value* hook_args = hook_dict.FindListKey("args");
    // args are optional.
    if (hook_args) {
      size_t num_args = hook_args->GetList().size();
      for (size_t j = 0; j < num_args; ++j) {
        const base::Value& arg = hook_args->GetList()[j];
        if (!arg.is_string()) {
          LOG(ERROR) << "Fail to get arg " << j << " of " << hook_type
                     << " hook " << i;
          return false;
        }
        hook.args.push_back(arg.GetString());
      }
    }

    const base::Value* hook_envs = hook_dict.FindListKey("env");
    // envs are optional.
    if (hook_envs) {
      size_t num_env = hook_envs->GetList().size();
      for (size_t j = 0; j < num_env; ++j) {
        const base::Value& env = hook_envs->GetList()[j];
        if (!env.is_string()) {
          LOG(ERROR) << "Fail to get env " << j << " of " << hook_type
                     << " hook " << i;
          return false;
        }
        std::vector<std::string> kvp = base::SplitString(
            env.GetString(), "=", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
        if (kvp.size() != 2) {
          LOG(ERROR) << "Fail to parse env \"" << env.GetString()
                     << "\". Must be in name=value format.";
          return false;
        }
        hook.env.insert(std::make_pair(kvp[0], kvp[1]));
      }
    }

    base::Optional<int> timeout_seconds = hook_dict.FindIntKey("timeout");
    // timeout is optional.
    hook.timeout = timeout_seconds.has_value()
                       ? base::TimeDelta::FromSeconds(*timeout_seconds)
                       : base::TimeDelta::Max();

    hooks_out->emplace_back(std::move(hook));
  }
  return true;
}

bool ParseHooks(const base::Value& config_root_dict,
                OciConfigPtr const& config_out) {
  const base::Value* hooks_config_dict = config_root_dict.FindDictKey("hooks");
  if (!hooks_config_dict) {
    // Hooks are optional.
    return true;
  }

  const base::Value* hooks_list = hooks_config_dict->FindListKey("precreate");
  if (hooks_list) {
    if (!ParseHooksList(*hooks_list, &config_out->pre_create_hooks,
                        "precreate")) {
      return false;
    }
  }
  hooks_list = hooks_config_dict->FindListKey("prechroot");
  if (hooks_list) {
    if (!ParseHooksList(*hooks_list, &config_out->pre_chroot_hooks,
                        "prechroot")) {
      return false;
    }
  }
  hooks_list = hooks_config_dict->FindListKey("prestart");
  if (hooks_list) {
    if (!ParseHooksList(*hooks_list, &config_out->pre_start_hooks, "prestart"))
      return false;
  }
  hooks_list = hooks_config_dict->FindListKey("poststart");
  if (hooks_list) {
    if (!ParseHooksList(*hooks_list, &config_out->post_start_hooks,
                        "poststart"))
      return false;
  }
  hooks_list = hooks_config_dict->FindListKey("poststop");
  if (hooks_list) {
    if (!ParseHooksList(*hooks_list, &config_out->post_stop_hooks, "poststop"))
      return false;
  }
  return true;
}

// Parses the configuration file for the container.  The config file specifies
// basic filesystem info and details about the process to be run.  namespace,
// cgroup, and syscall configurations are also specified
bool ParseConfigDict(const base::Value& config_root_dict,
                     OciConfigPtr const& config_out) {
  const std::string* oci_version = config_root_dict.FindStringKey("ociVersion");
  if (!oci_version) {
    LOG(ERROR) << "Failed to parse ociVersion";
    return false;
  }
  config_out->ociVersion = *oci_version;
  const std::string* host_name = config_root_dict.FindStringKey("hostname");
  if (!host_name) {
    LOG(ERROR) << "Failed to parse hostname";
    return false;
  }
  config_out->hostname = *host_name;
  if (!HostnameValid(config_out->hostname)) {
    LOG(ERROR) << "Invalid hostname " << config_out->hostname;
    return false;
  }

  // Platform info
  if (!ParsePlatformConfig(config_root_dict, config_out)) {
    return false;
  }

  // Root fs info
  if (!ParseRootFileSystemConfig(config_root_dict, config_out)) {
    return false;
  }

  // Process info
  if (!ParseProcessConfig(config_root_dict, config_out)) {
    return false;
  }

  // Get a list of mount points and mounts.
  if (!ParseMounts(config_root_dict, config_out)) {
    LOG(ERROR) << "Failed to parse mounts";
    return false;
  }

  // Hooks info
  if (!ParseHooks(config_root_dict, config_out)) {
    return false;
  }

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

  return true;
}

}  // anonymous namespace

bool ParseContainerConfig(const std::string& config_json_data,
                          OciConfigPtr const& config_out) {
  auto result = base::JSONReader::ReadAndReturnValueWithError(
      config_json_data, base::JSON_PARSE_RFC);
  if (!result.value) {
    LOG(ERROR) << "Fail to parse config.json: " << result.error_message;
    return false;
  }
  if (!result.value->is_dict()) {
    LOG(ERROR) << "Fail to parse root dictionary from config.json";
    return false;
  }
  if (!ParseConfigDict(*result.value, config_out)) {
    return false;
  }

  return true;
}

}  // namespace run_oci
