// Copyright 2018 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 "vm_tools/concierge/plugin_vm.h"

#include <signal.h>
#include <sys/socket.h>
#include <sys/un.h>

#include <algorithm>
#include <sstream>
#include <utility>
#include <vector>

#include <base/bind_helpers.h>
#include <base/files/file.h>
#include <base/files/file_util.h>
#include <base/files/scoped_file.h>
#include <base/logging.h>
#include <base/memory/ptr_util.h>
#include <base/strings/stringprintf.h>
#include <base/time/time.h>

#include "vm_tools/concierge/plugin_vm_helper.h"
#include "vm_tools/concierge/tap_device_builder.h"
#include "vm_tools/concierge/vm_builder.h"
#include "vm_tools/concierge/vm_permission_interface.h"
#include "vm_tools/concierge/vm_util.h"
#include "vm_tools/concierge/vmplugin_dispatcher_interface.h"

using std::string;

namespace vm_tools {
namespace concierge {
namespace {

// Path to the plugin binaries and other assets.
constexpr char kPluginDir[] = "/opt/pita";
constexpr char kPluginDlcDir[] = "/run/imageloader/pita/package/root/opt/pita";

// Name of the plugin VM binary.
constexpr char kPluginBin[] = "pvm";
// Name of the sub-directory containing plugin's seccomp policy.
constexpr char kPluginPolicyDir[] = "policy";

// Name of the runtime directory inside the jail.
constexpr char kRuntimeDir[] = "/run/pvm";

// Name of the stateful directory inside the jail.
constexpr char kStatefulDir[] = "/pvm";

// Name of the directory holding ISOs inside the jail.
constexpr char kIsoDir[] = "/iso";

// How long we give VM to suspend.
constexpr base::TimeDelta kVmSuspendTimeout = base::TimeDelta::FromSeconds(25);

// How long to wait before timing out on child process exits.
constexpr base::TimeDelta kChildExitTimeout = base::TimeDelta::FromSeconds(10);

// The CPU cgroup where all the PluginVm crosvm processes should belong to.
constexpr char kPluginVmCpuCgroup[] = "/sys/fs/cgroup/cpu/vms/plugin";

// Offset in a subnet of the client/guest.
constexpr size_t kGuestAddressOffset = 1;

std::unique_ptr<patchpanel::Subnet> MakeSubnet(
    const patchpanel::IPv4Subnet& subnet) {
  return std::make_unique<patchpanel::Subnet>(
      subnet.base_addr(), subnet.prefix_len(), base::DoNothing());
}

void TrySuspendVm(dbus::ObjectProxy* vmplugin_service_proxy, const VmId& id) {
  bool dispatcher_shutting_down = false;
  base::TimeTicks suspend_start_time(base::TimeTicks::Now());
  do {
    pvm::dispatcher::VmOpResult result =
        pvm::dispatcher::SuspendVm(vmplugin_service_proxy, id);

    switch (result) {
      case pvm::dispatcher::VmOpResult::SUCCESS:
        return;

      case pvm::dispatcher::VmOpResult::DISPATCHER_SHUTTING_DOWN:
        // The dispatcher is in process of shutting down, and is supposed
        // to suspend all running VMs. Wait a second, and try again, until we
        // get "dispatcher not available" response.
        if (!dispatcher_shutting_down) {
          LOG(INFO) << "Dispatcher is shutting down, will retry suspend";
          dispatcher_shutting_down = true;
        }
        base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
        break;

      case pvm::dispatcher::VmOpResult::DISPATCHER_NOT_AVAILABLE:
        if (!dispatcher_shutting_down)
          LOG(ERROR) << "Failed to suspend VM: dispatcher is not available";
        return;

      default:
        // TODO(dtor): handle cases when suspend fails because VM is already
        // transitioning into some state, such as suspending or shutting down,
        // in which case dispatcher will reject our request.
        LOG(ERROR) << "Failed to suspend VM: " << static_cast<int>(result);
        return;
    }
  } while (base::TimeTicks::Now() - suspend_start_time < kVmSuspendTimeout);
}

}  // namespace

// static
std::unique_ptr<PluginVm> PluginVm::Create(
    VmId id,
    base::FilePath stateful_dir,
    base::FilePath iso_dir,
    base::FilePath root_dir,
    base::FilePath runtime_dir,
    std::unique_ptr<patchpanel::Client> network_client,
    int subnet_index,
    bool enable_vnet_hdr,
    std::unique_ptr<SeneschalServerProxy> seneschal_server_proxy,
    dbus::ObjectProxy* vm_permission_service_proxy,
    dbus::ObjectProxy* vmplugin_service_proxy,
    VmBuilder vm_builder) {
  auto vm = std::unique_ptr<PluginVm>(new PluginVm(
      std::move(id), std::move(network_client),
      std::move(seneschal_server_proxy), vm_permission_service_proxy,
      vmplugin_service_proxy, std::move(iso_dir), std::move(root_dir),
      std::move(runtime_dir)));

  if (!vm->CreateUsbListeningSocket() ||
      !vm->Start(std::move(stateful_dir), subnet_index, enable_vnet_hdr,
                 std::move(vm_builder))) {
    vm.reset();
  }

  return vm;
}

PluginVm::~PluginVm() {
  StopVm();
}

bool PluginVm::StopVm() {
  // Notify arc-patchpanel that the VM is down.
  // This should run before the process existence check below since we still
  // want to release the network resources on crash.
  // Note the client will only be null during testing.
  if (network_client_ && !network_client_->NotifyPluginVmShutdown(id_hash_)) {
    LOG(WARNING) << "Unable to notify networking services";
  }

  // Notify permission service of VM destruction.
  if (!permission_token_.empty()) {
    vm_permission::UnregisterVm(vm_permission_service_proxy_, id_);
  }

  // Do a sanity check here to make sure the process is still around.
  if (!CheckProcessExists(process_.pid())) {
    // The process is already gone.
    process_.Release();
    return true;
  }

  TrySuspendVm(vmplugin_service_proxy_, id_);
  if (!CheckProcessExists(process_.pid())) {
    process_.Release();
    return true;
  }

  // Kill the process with SIGTERM. For Plugin VMs this will cause plugin to
  // try to suspend the VM.
  if (process_.Kill(SIGTERM, kChildExitTimeout.InSeconds())) {
    return true;
  }

  LOG(WARNING) << "Failed to kill plugin VM with SIGTERM";

  // Kill it with fire.
  if (process_.Kill(SIGKILL, kChildExitTimeout.InSeconds())) {
    return true;
  }

  LOG(ERROR) << "Failed to kill plugin VM with SIGKILL";
  return false;
}

bool PluginVm::Shutdown() {
  // Notify arc-patchpanel that the VM is down.
  // This should run before the process existence check below since we still
  // want to release the network resources on crash.
  // Note the client will only be null during testing.
  if (network_client_ && !network_client_->NotifyPluginVmShutdown(id_hash_)) {
    LOG(WARNING) << "Unable to notify networking services";
  }

  return !CheckProcessExists(process_.pid()) ||
         pvm::dispatcher::ShutdownVm(vmplugin_service_proxy_, id_) ==
             pvm::dispatcher::VmOpResult::SUCCESS;
}

VmInterface::Info PluginVm::GetInfo() {
  VmInterface::Info info = {
      .ipv4_address = subnet_->AddressAtOffset(kGuestAddressOffset),
      .pid = process_.pid(),
      .cid = 0,
      .seneschal_server_handle = seneschal_server_handle(),
      .permission_token = permission_token_,
      .status = VmInterface::Status::RUNNING,
      .type = VmInfo::PLUGIN_VM,
  };

  return info;
}

bool PluginVm::GetVmEnterpriseReportingInfo(
    GetVmEnterpriseReportingInfoResponse* response) {
  response->set_success(false);
  response->set_failure_reason("Not implemented");
  return false;
}

vm_tools::concierge::DiskImageStatus PluginVm::ResizeDisk(
    uint64_t new_size, std::string* failure_reason) {
  *failure_reason = "Not implemented";
  return DiskImageStatus::DISK_STATUS_FAILED;
}

vm_tools::concierge::DiskImageStatus PluginVm::GetDiskResizeStatus(
    std::string* failure_reason) {
  *failure_reason = "Not implemented";
  return DiskImageStatus::DISK_STATUS_FAILED;
}

// static
base::ScopedFD PluginVm::CreateUnixSocket(const base::FilePath& path,
                                          int type) {
  base::ScopedFD fd(socket(AF_UNIX, type, 0));
  if (!fd.is_valid()) {
    PLOG(ERROR) << "Failed to create AF_UNIX socket";
    return base::ScopedFD();
  }

  struct sockaddr_un sa;

  if (path.value().length() >= sizeof(sa.sun_path)) {
    LOG(ERROR) << "Path is too long for a UNIX socket: " << path.value();
    return base::ScopedFD();
  }

  memset(&sa, 0, sizeof(sa));
  sa.sun_family = AF_UNIX;
  // The memset above took care of NUL terminating, and we already verified
  // the length before that.
  memcpy(sa.sun_path, path.value().data(), path.value().length());

  // Delete any old socket instances.
  if (PathExists(path) && !DeleteFile(path, false)) {
    PLOG(ERROR) << "failed to delete " << path.value();
    return base::ScopedFD();
  }

  // Bind the socket.
  if (bind(fd.get(), reinterpret_cast<const sockaddr*>(&sa), sizeof(sa)) < 0) {
    PLOG(ERROR) << "failed to bind " << path.value();
    return base::ScopedFD();
  }

  return fd;
}

// static
bool PluginVm::SetVmCpuRestriction(CpuRestrictionState cpu_restriction_state) {
  return VmBaseImpl::SetVmCpuRestriction(cpu_restriction_state,
                                         kPluginVmCpuCgroup);
}

bool PluginVm::CreateUsbListeningSocket() {
  usb_listen_fd_ = CreateUnixSocket(runtime_dir_.GetPath().Append("usb.sock"),
                                    SOCK_SEQPACKET);
  if (!usb_listen_fd_.is_valid()) {
    return false;
  }

  // Start listening for connections. We only expect one client at a time.
  if (listen(usb_listen_fd_.get(), 1) < 0) {
    PLOG(ERROR) << "Unable to listen for connections on USB socket";
    return false;
  }

  usb_listen_watcher_ = base::FileDescriptorWatcher::WatchReadable(
      usb_listen_fd_.get(),
      base::BindRepeating(&PluginVm::OnListenFileCanReadWithoutBlocking,
                          base::Unretained(this)));
  if (!usb_listen_watcher_) {
    LOG(ERROR) << "Failed to watch USB listening socket";
    return false;
  }

  return true;
}

bool PluginVm::AttachUsbDevice(uint8_t bus,
                               uint8_t addr,
                               uint16_t vid,
                               uint16_t pid,
                               int fd,
                               UsbControlResponse* response) {
  base::ScopedFD dup_fd(dup(fd));
  if (!dup_fd.is_valid()) {
    PLOG(ERROR) << "Unable to duplicate incoming file descriptor";
    return false;
  }

  if (usb_vm_fd_.is_valid() && usb_req_waiting_xmit_.empty()) {
    usb_listen_watcher_.reset();
    usb_vm_read_watcher_ = base::FileDescriptorWatcher::WatchReadable(
        usb_vm_fd_.get(),
        base::BindRepeating(&PluginVm::OnVmFileCanReadWithoutBlocking,
                            base::Unretained(this)));
    usb_vm_write_watcher_ = base::FileDescriptorWatcher::WatchWritable(
        usb_vm_fd_.get(),
        base::BindRepeating(&PluginVm::OnVmFileCanWriteWithoutBlocking,
                            base::Unretained(this)));
    if (!usb_vm_read_watcher_ || !usb_vm_write_watcher_) {
      LOG(ERROR) << "Failed to start watching USB VM socket";
      usb_vm_read_watcher_.reset();
      usb_vm_write_watcher_.reset();
      return false;
    }
  }

  UsbCtrlRequest req{};
  req.type = ATTACH_DEVICE;
  req.handle = ++usb_last_handle_;
  req.DevInfo.bus = bus;
  req.DevInfo.addr = addr;
  req.DevInfo.vid = vid;
  req.DevInfo.pid = pid;
  usb_req_waiting_xmit_.emplace_back(std::move(req), std::move(dup_fd));

  // TODO(dtor): report status only when plugin responds; requires changes to
  // the VM interface API.
  response->type = UsbControlResponseType::OK;
  response->port = usb_last_handle_;
  return true;
}

bool PluginVm::DetachUsbDevice(uint8_t port, UsbControlResponse* response) {
  auto iter = std::find_if(
      usb_devices_.begin(), usb_devices_.end(),
      [port](const auto& info) { return std::get<2>(info) == port; });
  if (iter == usb_devices_.end()) {
    response->type = UsbControlResponseType::NO_SUCH_PORT;
    return true;
  }

  if (usb_vm_fd_.is_valid() && usb_req_waiting_xmit_.empty()) {
    usb_listen_watcher_.reset();
    usb_vm_read_watcher_ = base::FileDescriptorWatcher::WatchReadable(
        usb_vm_fd_.get(),
        base::BindRepeating(&PluginVm::OnVmFileCanReadWithoutBlocking,
                            base::Unretained(this)));
    usb_vm_write_watcher_ = base::FileDescriptorWatcher::WatchWritable(
        usb_vm_fd_.get(),
        base::BindRepeating(&PluginVm::OnVmFileCanWriteWithoutBlocking,
                            base::Unretained(this)));
    if (!usb_vm_read_watcher_ || !usb_vm_write_watcher_) {
      LOG(ERROR) << "Failed to start watching USB VM socket";
      usb_vm_read_watcher_.reset();
      usb_vm_write_watcher_.reset();
      return false;
    }
  }

  UsbCtrlRequest req{};
  req.type = DETACH_DEVICE;
  req.handle = port;
  usb_req_waiting_xmit_.emplace_back(req, base::ScopedFD());

  // TODO(dtor): report status only when plugin responds; requires changes to
  // the VM interface API.
  response->type = UsbControlResponseType::OK;
  response->port = port;
  return true;
}

bool PluginVm::ListUsbDevice(std::vector<UsbDevice>* device) {
  device->resize(usb_devices_.size());
  std::transform(usb_devices_.begin(), usb_devices_.end(), device->begin(),
                 [](const auto& info) {
                   UsbDevice d{};
                   std::tie(d.vid, d.pid, d.port) = info;
                   return d;
                 });
  return true;
}

void PluginVm::HandleUsbControlResponse() {
  UsbCtrlResponse resp;
  int ret = HANDLE_EINTR(read(usb_vm_fd_.get(), &resp, sizeof(resp)));
  if (ret <= 0) {
    // If we get 0 bytes from read() that means that the other side closed
    // the connection. Disconnect the socket and wait for new connection.
    // Do the same if we get any error besides EAGAIN.
    if (ret == 0 || errno != EAGAIN) {
      usb_vm_read_watcher_.reset();
      usb_vm_write_watcher_.reset();
      usb_vm_fd_.reset();

      usb_listen_watcher_ = base::FileDescriptorWatcher::WatchReadable(
          usb_listen_fd_.get(),
          base::BindRepeating(&PluginVm::OnListenFileCanReadWithoutBlocking,
                              base::Unretained(this)));
      if (!usb_listen_watcher_) {
        LOG(ERROR) << "Failed to restart watching USB listening socket";
      }
    }
  } else if (ret != sizeof(resp)) {
    LOG(ERROR) << "Partial read of " << ret
               << " from USB VM socket, discarding";
  } else {
    auto req_iter = std::find_if(
        usb_req_waiting_response_.begin(), usb_req_waiting_response_.end(),
        [&resp](const auto& req) {
          return resp.type == req.type && resp.handle == req.handle;
        });
    if (req_iter == usb_req_waiting_response_.end()) {
      LOG(ERROR) << "Unexpected response (type " << resp.type << ", handle "
                 << resp.handle << ")";
      return;
    }

    if (resp.status != UsbCtrlResponse::Status::OK) {
      LOG(ERROR) << "Request (type " << resp.type << ", handle " << resp.handle
                 << ") failed: " << resp.status;
    }

    switch (req_iter->type) {
      case ATTACH_DEVICE:
        if (resp.status == UsbCtrlResponse::Status::OK) {
          usb_devices_.emplace_back(req_iter->DevInfo.vid,
                                    req_iter->DevInfo.pid, req_iter->handle);
        }
        break;
      case DETACH_DEVICE: {
        // We will attempt to clean up even if plugin signalled error as there
        // is no way the device will continue be operational.
        auto dev_iter = std::find_if(usb_devices_.begin(), usb_devices_.end(),
                                     [&resp](const auto& info) {
                                       return std::get<2>(info) == resp.handle;
                                     });
        if (dev_iter == usb_devices_.end()) {
          LOG(ERROR) << "Received detach response for unknown handle "
                     << resp.handle;
        }
      } break;
      default:
        NOTREACHED();
    }

    usb_req_waiting_response_.erase(req_iter);
  }
}

void PluginVm::OnListenFileCanReadWithoutBlocking() {
  int ret = HANDLE_EINTR(accept4(usb_listen_fd_.get(), nullptr, nullptr,
                                 SOCK_CLOEXEC | SOCK_NONBLOCK));
  if (ret < 0) {
    PLOG(ERROR) << "Unable to accept connection on USB listening socket";
    return;
  }

  // Start managing socket connected to the VM.
  usb_vm_fd_.reset(ret);

  // Switch watcher from listener FD to connected socket FD.
  // We monitor both writes and reads to detect disconnects.
  usb_listen_watcher_.reset();
  usb_vm_read_watcher_ = base::FileDescriptorWatcher::WatchReadable(
      usb_vm_fd_.get(),
      base::BindRepeating(&PluginVm::OnVmFileCanReadWithoutBlocking,
                          base::Unretained(this)));
  if (!usb_req_waiting_xmit_.empty()) {
    usb_vm_write_watcher_ = base::FileDescriptorWatcher::WatchWritable(
        usb_vm_fd_.get(),
        base::BindRepeating(&PluginVm::OnVmFileCanWriteWithoutBlocking,
                            base::Unretained(this)));
  }
  if (!usb_vm_read_watcher_ ||
      (!usb_req_waiting_xmit_.empty() && !usb_vm_write_watcher_)) {
    LOG(ERROR) << "Failed to start watching USB VM socket";
    usb_vm_write_watcher_.reset();
    usb_vm_read_watcher_.reset();
    usb_vm_fd_.reset();
    return;
  }
}

void PluginVm::OnVmFileCanReadWithoutBlocking() {
  PluginVm::HandleUsbControlResponse();
}

void PluginVm::OnVmFileCanWriteWithoutBlocking() {
  DCHECK(usb_vm_fd_.is_valid());

  if (!usb_req_waiting_xmit_.empty()) {
    UsbCtrlRequest req = usb_req_waiting_xmit_.front().first;
    struct iovec io {};
    io.iov_base = &req;
    io.iov_len = sizeof(req);

    struct msghdr msg {};
    msg.msg_iov = &io;
    msg.msg_iovlen = 1;

    char buf[CMSG_SPACE(sizeof(int))];
    base::ScopedFD fd(std::move(usb_req_waiting_xmit_.front().second));
    if (fd.is_valid()) {
      msg.msg_control = buf;
      msg.msg_controllen = CMSG_LEN(sizeof(int));

      struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
      cmsg->cmsg_len = CMSG_LEN(sizeof(int));
      cmsg->cmsg_level = SOL_SOCKET;
      cmsg->cmsg_type = SCM_RIGHTS;

      *(reinterpret_cast<int*> CMSG_DATA(cmsg)) = fd.get();
    }

    int ret = HANDLE_EINTR(sendmsg(usb_vm_fd_.get(), &msg, MSG_EOR));
    if (ret == sizeof(req)) {
      usb_req_waiting_response_.emplace_back(req);
      usb_req_waiting_xmit_.pop_front();
    } else if (ret >= 0) {
      PLOG(ERROR) << "Partial write of " << ret
                  << " while sending USB request; will retry";
    } else if (errno != EINTR) {
      PLOG(ERROR) << "Failed to send USB request";
    }
  } else {
    usb_listen_watcher_.reset();
    usb_vm_write_watcher_.reset();

    usb_vm_read_watcher_ = base::FileDescriptorWatcher::WatchReadable(
        usb_vm_fd_.get(),
        base::BindRepeating(&PluginVm::OnVmFileCanReadWithoutBlocking,
                            base::Unretained(this)));
    if (!usb_vm_read_watcher_) {
      LOG(ERROR) << "Failed to switch to watching USB VM socket for reads";
    }
  }
}

// static
bool PluginVm::WriteResolvConf(const base::FilePath& parent_dir,
                               const std::vector<string>& nameservers,
                               const std::vector<string>& search_domains) {
  // Create temporary directory on the same file system so that we
  // can atomically replace old resolv.conf with new one.
  base::ScopedTempDir temp_dir;
  if (!temp_dir.CreateUniqueTempDirUnderPath(parent_dir)) {
    LOG(ERROR) << "Failed to create temporary directory under "
               << parent_dir.value();
    return false;
  }

  base::FilePath path = temp_dir.GetPath().Append("resolv.conf");
  base::File file(path, base::File::FLAG_CREATE | base::File::FLAG_WRITE);
  if (!file.IsValid()) {
    LOG(ERROR) << "Failed to create temporary file " << path.value();
    return false;
  }

  for (auto& ns : nameservers) {
    string nameserver_line = base::StringPrintf("nameserver %s\n", ns.c_str());
    if (!file.WriteAtCurrentPos(nameserver_line.c_str(),
                                nameserver_line.length())) {
      LOG(ERROR) << "Failed to write nameserver to temporary file";
      return false;
    }
  }

  if (!search_domains.empty()) {
    string search_domains_line = base::StringPrintf(
        "search %s\n", base::JoinString(search_domains, " ").c_str());
    if (!file.WriteAtCurrentPos(search_domains_line.c_str(),
                                search_domains_line.length())) {
      LOG(ERROR) << "Failed to write search domains to temporary file";
      return false;
    }
  }

  constexpr char kResolvConfOptions[] =
      "options single-request timeout:1 attempts:5\n";
  if (!file.WriteAtCurrentPos(kResolvConfOptions, strlen(kResolvConfOptions))) {
    LOG(ERROR) << "Failed to write search resolver options to temporary file";
    return false;
  }

  // This should flush the buffers.
  file.Close();

  base::File::Error err;
  if (!ReplaceFile(path, parent_dir.Append("resolv.conf"), &err)) {
    LOG(ERROR) << "Failed to replace resolv.conf with new instance: "
               << base::File::ErrorToString(err);
    return false;
  }

  return true;
}

bool PluginVm::SetResolvConfig(const std::vector<string>& nameservers,
                               const std::vector<string>& search_domains) {
  return WriteResolvConf(root_dir_.GetPath().Append("etc"), nameservers,
                         search_domains);
}

void PluginVm::VmToolsStateChanged(bool running) {
  LOG(INFO) << "Tools are " << (running ? "" : "not ")
            << "running in plugin VM";

  if (running)
    pvm::helper::CleanUpAfterInstall(id_, iso_dir_);
}

PluginVm::PluginVm(VmId id,
                   std::unique_ptr<patchpanel::Client> network_client,
                   std::unique_ptr<SeneschalServerProxy> seneschal_server_proxy,
                   dbus::ObjectProxy* vm_permission_service_proxy,
                   dbus::ObjectProxy* vmplugin_service_proxy,
                   base::FilePath iso_dir,
                   base::FilePath root_dir,
                   base::FilePath runtime_dir)
    : VmBaseImpl(std::move(network_client),
                 std::move(seneschal_server_proxy),
                 std::move(runtime_dir)),
      id_(std::move(id)),
      iso_dir_(std::move(iso_dir)),
      vm_permission_service_proxy_(vm_permission_service_proxy),
      vmplugin_service_proxy_(vmplugin_service_proxy),
      usb_last_handle_(0) {
  CHECK(vm_permission_service_proxy_);
  CHECK(vmplugin_service_proxy_);
  CHECK(base::DirectoryExists(iso_dir_));
  CHECK(base::DirectoryExists(root_dir));

  // Take ownership of the root and runtime directories.
  CHECK(root_dir_.Set(root_dir));

  std::ostringstream oss;
  oss << id_;
  id_hash_ = std::hash<std::string>{}(oss.str());
}

bool PluginVm::Start(base::FilePath stateful_dir,
                     int subnet_index,
                     bool enable_vnet_hdr,
                     VmBuilder vm_builder) {
  if (!pvm::helper::IsDlcVm()) {
    LOG(ERROR) << "PluginVM DLC is not installed.";
    return false;
  }

  // Register the VM with permission service and obtain permission
  // token.
  if (!vm_permission::RegisterVm(vm_permission_service_proxy_, id_,
                                 vm_permission::VmType::PLUGIN_VM,
                                 &permission_token_)) {
    LOG(ERROR) << "Failed to register with permission service";
    return false;
  }

  // Get the network interface.
  patchpanel::NetworkDevice network_device;
  if (!network_client_->NotifyPluginVmStartup(id_hash_, subnet_index,
                                              &network_device)) {
    LOG(ERROR) << "No network devices available";
    return false;
  }
  subnet_ = MakeSubnet(network_device.ipv4_subnet());

  // Open the tap device.
  base::ScopedFD tap_fd = OpenTapDevice(
      network_device.ifname(), enable_vnet_hdr, nullptr /*ifname_out*/);
  if (!tap_fd.is_valid()) {
    LOG(ERROR) << "Unable to open and configure TAP device "
               << network_device.ifname();
    return false;
  }

  auto plugin_bin_path = base::FilePath(kPluginDlcDir).Append(kPluginBin);
  auto plugin_policy_dir =
      base::FilePath(kPluginDlcDir).Append(kPluginPolicyDir);
  vm_builder.AppendTapFd(std::move(tap_fd))
      .AppendCustomParam("--plugin", plugin_bin_path.value())
      .AppendCustomParam("--seccomp-policy-dir", plugin_policy_dir.value())
      .AppendCustomParam("--plugin-gid-map-file",
                         plugin_bin_path.AddExtension("gid_maps").value());

  // These are bind mounts with parts may change (i.e. they are either VM
  // or config specific).
  std::vector<string> bind_mounts = {
      base::StringPrintf("%s:%s:false", kPluginDlcDir, kPluginDir),
      // This is directory where the VM image resides.
      base::StringPrintf("%s:%s:true", stateful_dir.value().c_str(),
                         kStatefulDir),
      // This is directory where ISO images for the VM reside.
      base::StringPrintf("%s:%s:false", iso_dir_.value().c_str(), kIsoDir),
      // This is directory where control socket, 9p socket, and other axillary
      // runtime data lives.
      base::StringPrintf("%s:%s:true", runtime_dir_.GetPath().value().c_str(),
                         kRuntimeDir),
      // Plugin '/etc' directory.
      base::StringPrintf("%s:%s:true",
                         root_dir_.GetPath().Append("etc").value().c_str(),
                         "/etc"),
  };

  if (vm_permission::IsCameraEnabled(vm_permission_service_proxy_,
                                     permission_token_)) {
    LOG(INFO) << "VM " << id_ << ": camera access enabled";
    bind_mounts.push_back("/run/camera:/run/camera:true");
  } else {
    LOG(INFO) << "VM " << id_ << ": camera access disabled";
  }

  if (vm_permission::IsMicrophoneEnabled(vm_permission_service_proxy_,
                                         permission_token_)) {
    LOG(INFO) << "VM " << id_ << ": microphone access enabled";
    bind_mounts.push_back(
        "/run/cras/.cras_unified:/run/cras/.cras_socket:true");
  } else {
    LOG(INFO) << "VM " << id_ << ": microphone access disabled";
    bind_mounts.push_back("/run/cras/.cras_socket::true");
  }

  // TODO(kimjae): This is a temporary hack to have relative files to be found
  // even when started from DLC paths. Clean this up once a cleaner solution
  // can be leveraged.
  bind_mounts.push_back(
      base::StringPrintf("%s:%s:false", kPluginDlcDir, kPluginDlcDir));
  for (auto& mount : bind_mounts)
    vm_builder.AppendCustomParam("--plugin-mount", std::move(mount));

  // Because some of the static paths are mounted in /run/pvm... in the
  // plugin jail, they have to come after the dynamic paths above.
  vm_builder.AppendCustomParam(
      "--plugin-mount-file",
      plugin_bin_path.AddExtension("bind_mounts").value());

  // Change the process group before exec so that crosvm sending SIGKILL to
  // the whole process group doesn't kill us as well. The function also
  // changes the cpu cgroup for PluginVm crosvm processes.
  process_.SetPreExecCallback(base::Bind(
      &SetUpCrosvmProcess, base::FilePath(kPluginVmCpuCgroup).Append("tasks")));

  if (!StartProcess(vm_builder.BuildVmArgs())) {
    LOG(ERROR) << "Failed to start VM process";
    return false;
  }

  return true;
}

}  // namespace concierge
}  // namespace vm_tools
