// Copyright 2020 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 <sys/socket.h>
#include <sys/types.h>

#include <string>

#include <base/check.h>
#include <base/files/file_util.h>
#include <base/guid.h>
#include <base/logging.h>

#include "vm_tools/concierge/plugin_vm.h"
#include "vm_tools/concierge/plugin_vm_helper.h"
#include "vm_tools/concierge/service.h"
#include "vm_tools/concierge/shared_data.h"
#include "vm_tools/concierge/vmplugin_dispatcher_interface.h"

namespace vm_tools {
namespace concierge {

namespace {

bool GetPluginStatefulDirectory(const std::string& vm_id,
                                const std::string& cryptohome_id,
                                bool create,
                                base::FilePath* path_out) {
  return GetPluginDirectory(base::FilePath(kCryptohomeRoot)
                                .Append(kPluginVmDir)
                                .Append(cryptohome_id),
                            "pvm", vm_id, create, path_out);
}

bool GetPluginRuntimeDirectory(const std::string& vm_id,
                               base::ScopedTempDir* runtime_dir_out) {
  base::FilePath path;
  if (GetPluginDirectory(base::FilePath("/run/pvm"), "", vm_id,
                         true /*create */, &path)) {
    // Take ownership of directory
    CHECK(runtime_dir_out->Set(path));
    return true;
  }

  return false;
}

bool GetPluginRootDirectory(const std::string& vm_id,
                            base::ScopedTempDir* root_dir_out) {
  base::FilePath path;
  if (!base::CreateTemporaryDirInDir(base::FilePath(kRuntimeDir), "vm.",
                                     &path)) {
    PLOG(ERROR) << "Unable to create root directory for VM";
    return false;
  }

  // Take ownership of directory
  CHECK(root_dir_out->Set(path));
  return true;
}

bool CreatePluginRootHierarchy(const base::FilePath& root_path) {
  base::FilePath etc_dir(root_path.Append("etc"));
  base::File::Error dir_error;
  if (!CreateDirectoryAndGetError(etc_dir, &dir_error)) {
    LOG(ERROR) << "Unable to create /etc in root directory for VM "
               << base::File::ErrorToString(dir_error);
    return false;
  }

  // Note that this will be dangling (or rather point to concierge's timezone
  // instance) until crosvm bind mounts /var/lib/timezone and
  // /usr/share/zoneinfo into plugin jail.
  if (!base::CreateSymbolicLink(base::FilePath("/var/lib/timezone/localtime"),
                                etc_dir.Append("localtime"))) {
    PLOG(ERROR) << "Unable to create /etc/localtime symlink";
    return false;
  }

  return true;
}

bool GetPlugin9PSocketPath(const std::string& vm_id, base::FilePath* path_out) {
  base::FilePath runtime_dir;
  if (!GetPluginDirectory(base::FilePath("/run/pvm"), "", vm_id,
                          true /* create */, &runtime_dir)) {
    LOG(ERROR) << "Unable to get runtime directory for 9P socket";
    return false;
  }

  *path_out = runtime_dir.Append("9p.sock");
  return true;
}

}  // namespace

std::unique_ptr<dbus::Response> Service::StartPluginVm(
    dbus::MethodCall* method_call) {
  LOG(INFO) << "Received StartPluginVm request";

  std::unique_ptr<dbus::Response> dbus_response(
      dbus::Response::FromMethodCall(method_call));
  dbus::MessageReader reader(method_call);
  dbus::MessageWriter writer(dbus_response.get());
  StartPluginVmRequest request;
  StartVmResponse response;
  auto helper_result = StartVmHelper<StartPluginVmRequest>(
      method_call, &reader, &writer, true /* allow_zero_cpus */);
  if (!helper_result) {
    return dbus_response;
  }
  std::tie(request, response) = *helper_result;
  VmInfo* vm_info = response.mutable_vm_info();
  vm_info->set_vm_type(VmInfo::PLUGIN_VM);

  // Get the stateful directory.
  base::FilePath stateful_dir;
  if (!GetPluginStatefulDirectory(request.name(), request.owner_id(),
                                  true /* create */, &stateful_dir)) {
    LOG(ERROR) << "Unable to create stateful directory for VM";

    response.set_failure_reason("Unable to create stateful directory");
    writer.AppendProtoAsArrayOfBytes(response);
    return dbus_response;
  }

  // Get the directory for ISO images.
  base::FilePath iso_dir;
  if (!GetPluginIsoDirectory(request.name(), request.owner_id(),
                             true /* create */, &iso_dir)) {
    LOG(ERROR) << "Unable to create directory holding ISOs for VM";

    response.set_failure_reason("Unable to create ISO directory");
    writer.AppendProtoAsArrayOfBytes(response);
    return dbus_response;
  }

  // Create the runtime directory.
  base::ScopedTempDir runtime_dir;
  if (!GetPluginRuntimeDirectory(request.name(), &runtime_dir)) {
    LOG(ERROR) << "Unable to create runtime directory for VM";

    response.set_failure_reason("Unable to create runtime directory");
    writer.AppendProtoAsArrayOfBytes(response);
    return dbus_response;
  }

  // Create the root directory.
  base::ScopedTempDir root_dir;
  if (!GetPluginRootDirectory(request.name(), &root_dir)) {
    LOG(ERROR) << "Unable to create runtime directory for VM";

    response.set_failure_reason("Unable to create runtime directory");
    writer.AppendProtoAsArrayOfBytes(response);
    return dbus_response;
  }

  if (!CreatePluginRootHierarchy(root_dir.GetPath())) {
    response.set_failure_reason("Unable to create plugin root hierarchy");
    writer.AppendProtoAsArrayOfBytes(response);
    return dbus_response;
  }

  if (!PluginVm::WriteResolvConf(root_dir.GetPath().Append("etc"), nameservers_,
                                 search_domains_)) {
    LOG(ERROR) << "Unable to seed resolv.conf for the Plugin VM";

    response.set_failure_reason("Unable to seed resolv.conf");
    writer.AppendProtoAsArrayOfBytes(response);
    return dbus_response;
  }

  // Generate the token used by cicerone to identify the VM and write it to
  // a VM specific directory that gets mounted into the VM.
  std::string vm_token = base::GenerateGUID();
  if (base::WriteFile(runtime_dir.GetPath().Append("cicerone.token"),
                      vm_token.c_str(),
                      vm_token.length()) != vm_token.length()) {
    PLOG(ERROR) << "Failure writing out cicerone token to file";

    response.set_failure_reason("Unable to set cicerone token");
    writer.AppendProtoAsArrayOfBytes(response);
    return dbus_response;
  }

  base::FilePath p9_socket_path;
  if (!GetPlugin9PSocketPath(request.name(), &p9_socket_path)) {
    response.set_failure_reason("Internal error: unable to get 9P directory");
    writer.AppendProtoAsArrayOfBytes(response);
    return dbus_response;
  }

  base::ScopedFD p9_socket =
      PluginVm::CreateUnixSocket(p9_socket_path, SOCK_STREAM);
  if (!p9_socket.is_valid()) {
    LOG(ERROR) << "Failed creating 9P socket for file sharing";

    response.set_failure_reason("Internal error: unable to create 9P socket");
    writer.AppendProtoAsArrayOfBytes(response);
    return dbus_response;
  }

  std::unique_ptr<patchpanel::Client> network_client =
      patchpanel::Client::New(bus_);
  if (!network_client) {
    LOG(ERROR) << "Unable to open networking service client";

    response.set_failure_reason("Unable to open network service client");
    writer.AppendProtoAsArrayOfBytes(response);
    return dbus_response;
  }

  std::unique_ptr<SeneschalServerProxy> seneschal_server_proxy =
      SeneschalServerProxy::CreateFdProxy(bus_, seneschal_service_proxy_,
                                          p9_socket);
  if (!seneschal_server_proxy) {
    LOG(ERROR) << "Unable to start shared directory server";

    response.set_failure_reason("Unable to start shared directory server");
    writer.AppendProtoAsArrayOfBytes(response);
    return dbus_response;
  }

  // Build the plugin params.
  std::vector<std::string> params(
      std::make_move_iterator(request.mutable_params()->begin()),
      std::make_move_iterator(request.mutable_params()->end()));

  // Now start the VM.
  VmId vm_id(request.owner_id(), request.name());
  SendVmStartingUpSignal(vm_id, *vm_info);

  VmBuilder vm_builder;
  vm_builder.SetCpus(request.cpus());
  for (auto& param : params) {
    // Because additional parameters may start with a '--', we should use
    // --params=<Param> instead of --params <Param> to make explicit <Param>
    // is a parameter for the plugin rather than just another parameter to
    // the crosvm process.
    vm_builder.AppendCustomParam(std::string("--params=") + param, "");
  }

  auto vm = PluginVm::Create(
      vm_id, std::move(stateful_dir), std::move(iso_dir), root_dir.Take(),
      runtime_dir.Take(), std::move(network_client), request.subnet_index(),
      request.net_options().enable_vnet_hdr(), bus_,
      std::move(seneschal_server_proxy), vm_permission_service_proxy_,
      vmplugin_service_proxy_, std::move(vm_builder));
  if (!vm) {
    LOG(ERROR) << "Unable to start VM";
    response.set_failure_reason("Unable to start VM");
    writer.AppendProtoAsArrayOfBytes(response);
    return dbus_response;
  }

  VmInterface::Info info = vm->GetInfo();

  vm_info->set_ipv4_address(info.ipv4_address);
  vm_info->set_pid(info.pid);
  vm_info->set_cid(info.cid);
  vm_info->set_seneschal_server_handle(info.seneschal_server_handle);
  vm_info->set_permission_token(info.permission_token);
  switch (info.status) {
    case VmInterface::Status::STARTING: {
      response.set_status(VM_STATUS_STARTING);
      break;
    }
    case VmInterface::Status::RUNNING: {
      response.set_status(VM_STATUS_RUNNING);
      break;
    }
    default: {
      response.set_status(VM_STATUS_UNKNOWN);
      break;
    }
  }
  response.set_success(true);
  writer.AppendProtoAsArrayOfBytes(response);

  NotifyCiceroneOfVmStarted(vm_id, 0 /* cid */, info.pid, std::move(vm_token));
  SendVmStartedSignal(vm_id, *vm_info, response.status());

  vms_[vm_id] = std::move(vm);
  return dbus_response;
}

bool Service::RenamePluginVm(const std::string& owner_id,
                             const std::string& old_name,
                             const std::string& new_name,
                             std::string* failure_reason) {
  base::FilePath old_dir;
  if (!GetPluginStatefulDirectory(old_name, owner_id, false /* create */,
                                  &old_dir)) {
    *failure_reason = "unable to determine current VM directory";
    return false;
  }

  base::FilePath old_iso_dir;
  if (!GetPluginIsoDirectory(old_name, owner_id, false /* create */,
                             &old_iso_dir)) {
    *failure_reason = "unable to determine current VM ISO directory";
    return false;
  }

  base::FilePath new_dir;
  if (!GetPluginStatefulDirectory(new_name, owner_id, false /* create */,
                                  &new_dir)) {
    *failure_reason = "unable to determine new VM directory";
    return false;
  }

  base::FilePath new_iso_dir;
  if (!GetPluginIsoDirectory(new_name, owner_id, false /* create */,
                             &new_iso_dir)) {
    *failure_reason = "unable to determine new VM ISO directory";
    return false;
  }

  VmId old_id(owner_id, old_name);
  bool registered;
  if (!pvm::dispatcher::IsVmRegistered(bus_, vmplugin_service_proxy_, old_id,
                                       &registered)) {
    *failure_reason = "failed to check Plugin VM registration status";
    return false;
  }

  // This is unexpected: the VM is not registered. Better leave it alone.
  if (!registered) {
    *failure_reason = "the VM is not registered";
    return false;
  }

  bool is_shut_down;
  if (!pvm::dispatcher::IsVmShutDown(bus_, vmplugin_service_proxy_, old_id,
                                     &is_shut_down)) {
    *failure_reason = "failed to check Plugin VM state";
    return false;
  }

  if (!is_shut_down) {
    *failure_reason = "VM is not shut down";
    return false;
  }

  base::File::Error move_error;
  if (base::PathExists(old_iso_dir) &&
      !base::ReplaceFile(old_iso_dir, new_iso_dir, &move_error)) {
    *failure_reason = std::string("failed to rename VM ISO directory: ") +
                      base::File::ErrorToString(move_error);
    return false;
  }

  if (!pvm::dispatcher::UnregisterVm(bus_, vmplugin_service_proxy_, old_id)) {
    *failure_reason = "failed to temporarily unregister VM";
    return false;
  }

  if (!base::ReplaceFile(old_dir, new_dir, &move_error)) {
    *failure_reason = std::string("failed to rename VM directory: ") +
                      base::File::ErrorToString(move_error);
    return false;
  }

  if (!pvm::dispatcher::RegisterVm(bus_, vmplugin_service_proxy_,
                                   VmId(owner_id, new_name), new_dir)) {
    *failure_reason = "Failed to re-register renamed VM";
    return false;
  }

  return true;
}

}  // namespace concierge
}  // namespace vm_tools
