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

#include <algorithm>
#include <memory>
#include <utility>

#include </usr/include/linux/magic.h>
#include <fcntl.h>
#include <libdevmapper.h>
#include <linux/loop.h>
#include <mntent.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/vfs.h>

#include <base/command_line.h>
#include <base/containers/adapters.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/files/scoped_file.h>
#include <base/logging.h>
#include <base/process/launch.h>
#include <base/rand_util.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <base/time/time.h>

#include "component.h"
#include "verity_mounter_impl.h"

namespace imageloader {

namespace {
// Path to devices created by device mapper.
constexpr char kDeviceMapperPath[] = "/dev/mapper";

using dm_task_ptr = std::unique_ptr<dm_task, void(*)(dm_task *)>;

enum class MountStatus { FAIL, RETRY, SUCCESS };

constexpr int GET_LOOP_DEVICE_MAX_RETRY = 5;
constexpr int DMSETUP_TIMEOUT_SECONDS = 3;

// Fetches the device mapper table entry with the specified name and writes the
// type and parameters into the provided pointers.
// Returns true on success.
bool MapperGetEntry(const std::string& name, std::string* type,
                    std::string* parameters) {
  auto task = dm_task_ptr(dm_task_create(DM_DEVICE_TABLE), &dm_task_destroy);
  struct dm_info info;

  if (!task) {
    LOG(ERROR) << "dm_task_create failed!";
    return false;
  }

  if (!dm_task_set_name(task.get(), name.c_str())) {
    LOG(ERROR) << "dm_task_set_name failed!";
    return false;
  }

  if (!dm_task_run(task.get())) {
    LOG(ERROR) << "dm_task_run failed!";
    return false;
  }

  if (!dm_task_get_info(task.get(), &info)) {
    LOG(ERROR) << "dm_task_get_info failed!";
    return false;
  }

  void* next = nullptr;
  uint64_t start;
  uint64_t length;
  char* type_cstr;
  char* parameters_cstr;
  next = dm_get_next_target(task.get(), next, &start, &length, &type_cstr,
                            &parameters_cstr);
  if (type != nullptr) {
    *type = std::string(type_cstr);
  }
  if (parameters != nullptr) {
    *parameters = std::string(parameters_cstr);
  }
  return true;
}

// Fetches the length of the device mapper table entries for the specified name.
bool MapperTableLength(const std::string& name, uint64_t* length) {
  auto task = dm_task_ptr(dm_task_create(DM_DEVICE_TABLE), &dm_task_destroy);
  struct dm_info info;

  if (!task) {
    LOG(ERROR) << "dm_task_create failed!";
    return false;
  }

  if (!dm_task_set_name(task.get(), name.c_str())) {
    LOG(ERROR) << "dm_task_set_name failed!";
    return false;
  }

  if (!dm_task_run(task.get())) {
    LOG(ERROR) << "dm_task_run failed!";
    return false;
  }

  if (!dm_task_get_info(task.get(), &info)) {
    LOG(ERROR) << "dm_task_get_info failed!";
    return false;
  }

  *length = 0;
  void* next = nullptr;
  uint64_t start;
  uint64_t length_part;
  char* type;
  char* parameters;
  do {
    next =
        dm_get_next_target(task.get(), next, &start, &length_part, &type,
                           &parameters);
    *length += length_part;
  } while (next);
  return true;
}

// Executes the equivalent of: dmsetup wipe_table <name>
// Returns true on success.
bool MapperWipeTable(const std::string& name) {
  uint64_t length;
  if (!MapperTableLength(name, &length)) {
    return false;
  }

  auto task = dm_task_ptr(dm_task_create(DM_DEVICE_RELOAD), &dm_task_destroy);

  if (!task) {
    LOG(ERROR) << "dm_task_create failed!";
    return false;
  }

  if (!dm_task_set_name(task.get(), name.c_str())) {
    LOG(ERROR) << "dm_task_set_name failed!";
    return false;
  }

  if (!dm_task_add_target(task.get(), 0, length, "error", "")) {
    LOG(ERROR) << "dm_task_add_target failed!";
    return false;
  }

  if (!dm_task_run(task.get())) {
    LOG(ERROR) << "dm_task_run failed!";
    return false;
  }
  return true;
}

// Executes the equivalent of: dmsetup remove <name>
// Returns true on success.
bool MapperRemove(const std::string& name) {
  auto task = dm_task_ptr(dm_task_create(DM_DEVICE_REMOVE), &dm_task_destroy);

  if (!task) {
    LOG(ERROR) << "dm_task_create failed!";
    return false;
  }

  if (!dm_task_set_name(task.get(), name.c_str())) {
    LOG(ERROR) << "dm_task_set_name failed!";
    return false;
  }

  if (!dm_task_run(task.get())) {
    LOG(ERROR) << "dm_task_run failed!";
    return false;
  }
  return true;
}

// |argv| should include all the commands and table to dmsetup, but not
// include the path to the binary.
bool RunDMSetup(const std::vector<std::string>& argv) {
  base::LaunchOptions options;
  options.clear_environ = true;

  std::vector<std::string> full_argv(argv);
  full_argv.insert(full_argv.begin(), "/sbin/dmsetup");

  base::Process process = base::LaunchProcess(full_argv, options);

  if (!process.IsValid()) {
    LOG(ERROR) << "Failed to launch dmsetup process";
    return false;
  }

  int exit_code;
  if (!process.WaitForExitWithTimeout(
          base::TimeDelta::FromSeconds(DMSETUP_TIMEOUT_SECONDS), &exit_code)) {
    LOG(ERROR) << "Failed to wait for dmsetup process.";
    return false;
  }

  return exit_code == 0;
}

bool LaunchDMCreate(const std::string& name, const std::string& table) {
  const std::vector<std::string> argv = {"create", name, "--table",
                                         table.c_str(), "--readonly"};
  return RunDMSetup(argv);
}

// Clear the /dev/mapper/<foo> verity device.
void ClearVerityDevice(const std::string& name) {
  // Per the man page, wipe_table:
  // Wait for any I/O in-flight through the device to complete, then replace the
  // table with a new table that fails any new I/O sent to the device.  If
  // successful, this should release any devices held open by the device's
  // table(s).
  MapperWipeTable(name);
  // Now remove the actual device.
  MapperRemove(name);
}

// Clear the file descriptor behind a loop device.
void ClearLoopDevice(const std::string& device_path) {
  base::ScopedFD loop_device_fd(
      open(device_path.c_str(), O_RDONLY | O_CLOEXEC));
  if (loop_device_fd.is_valid()) ioctl(loop_device_fd.get(), LOOP_CLR_FD, 0);
}

bool SetupDeviceMapper(const std::string& device_path, const std::string& table,
                       std::string* dev_name) {
  // Now setup the dmsetup table.
  std::string final_table = table;
  if (!VerityMounter::SetupTable(&final_table, device_path)) return false;

  // Generate a name with a random string of 32 characters: we consider this to
  // have sufficiently low chance of collision to assume the name isn't taken.
  std::vector<uint8_t> rand_bytes(32);
  base::RandBytes(rand_bytes.data(), rand_bytes.size());
  std::string name = base::HexEncode(rand_bytes.data(), rand_bytes.size());

  if (!LaunchDMCreate(name, final_table)) {
    LOG(ERROR) << "Failed to run dmsetup.";
    return false;
  }

  const base::FilePath dev_mapper(kDeviceMapperPath);
  dev_name->assign(dev_mapper.Append(name).value().c_str());
  return true;
}

bool CreateDirectoryWithMode(const base::FilePath& full_path, int mode) {
  std::vector<base::FilePath> subpaths;

  // Collect a list of all parent directories.
  base::FilePath last_path = full_path;
  subpaths.push_back(full_path);
  for (base::FilePath path = full_path.DirName();
       path.value() != last_path.value(); path = path.DirName()) {
    subpaths.push_back(path);
    last_path = path;
  }

  // Iterate through the parents and create the missing ones.
  for (const auto& subpath : base::Reversed(subpaths)) {
    if (base::DirectoryExists(subpath)) continue;
    if (mkdir(subpath.value().c_str(), mode) == 0) continue;
    // Mkdir failed, but it might have failed with EEXIST, or some other error
    // due to the directory appearing out of thin air. This can occur if two
    // processes are trying to create the same file system tree at the same
    // time. Check to see if it exists and make sure it is a directory.
    if (!base::DirectoryExists(subpath)) {
      PLOG(ERROR) << "Failed to create directory: " << subpath.value();
      return false;
    }
  }
  return true;
}

bool CreateMountPointIfNeeded(const base::FilePath& mount_point,
                              bool* already_mounted) {
  *already_mounted = false;
  // Is this mount point somehow already taken?
  struct stat st;
  if (lstat(mount_point.value().c_str(), &st) == 0) {
    if (!S_ISDIR(st.st_mode)) {
      LOG(ERROR) << "Mount point exists but is not a directory.";
      return false;
    }

    base::FilePath mount_parent = mount_point.DirName();
    struct stat st2;
    if (stat(mount_parent.value().c_str(), &st2) != 0) {
      PLOG(ERROR) << "Could not stat the mount point parent";
      return false;
    }
    if (st.st_dev != st2.st_dev) {
      struct statfs st_fs;
      if (statfs(mount_point.value().c_str(), &st_fs) != 0) {
        PLOG(ERROR) << "statfs";
        return false;
      }
      if (st_fs.f_type != SQUASHFS_MAGIC || !(st_fs.f_flags & ST_NODEV) ||
          !(st_fs.f_flags & ST_NOSUID) || !(st_fs.f_flags & ST_RDONLY)) {
        LOG(ERROR) << "File system is not the expected type.";
        return false;
      }
      *already_mounted = true;
      return true;
    }
  } else if (!CreateDirectoryWithMode(mount_point, kComponentDirPerms)) {
    LOG(ERROR) << "Failed to create mount point: " << mount_point.value();
    return false;
  }
  return true;
}

// Reserves a loop device and associates it with |image_fd|. The path to the
// loop device is returned in |device_path_out|. When the loop device is no
// longer being used, free the resource with ClearLoopDevice().
MountStatus GetLoopDevice(const base::ScopedFD& image_fd,
                          std::string* device_path_out) {
  base::ScopedFD loopctl_fd(open("/dev/loop-control", O_RDONLY | O_CLOEXEC));
  if (!loopctl_fd.is_valid()) {
    PLOG(ERROR) << "loopctl_fd";
    return MountStatus::FAIL;
  }
  int device_free_number = ioctl(loopctl_fd.get(), LOOP_CTL_GET_FREE);
  if (device_free_number < 0) {
    PLOG(ERROR) << "ioctl : LOOP_CTL_GET_FREE";
    return MountStatus::FAIL;
  }

  std::string device_path =
      base::StringPrintf("/dev/loop%d", device_free_number);
  base::ScopedFD loop_device_fd(
      open(device_path.c_str(), O_RDONLY | O_CLOEXEC));
  if (!loop_device_fd.is_valid()) {
    PLOG(ERROR) << "Failed to open loop device: " << device_path;
    return MountStatus::FAIL;
  }

  if (ioctl(loop_device_fd.get(), LOOP_SET_FD, image_fd.get()) == -1) {
    if (errno != EBUSY) {
      PLOG(ERROR) << "ioctl: LOOP_SET_FD";
      ioctl(loop_device_fd.get(), LOOP_CLR_FD, 0);
      return MountStatus::FAIL;
    }
    return MountStatus::RETRY;
  }

  device_path_out->assign(device_path);
  return MountStatus::SUCCESS;
}

}  // namespace

// static
bool VerityMounter::SetupTable(std::string* table,
                               const std::string& device_path) {
  // Make sure there is only one entry in the device mapper table.
  if (std::count(table->begin(), table->end(), '\n') > 1) return false;

  // Remove all newlines from the table. This is to workaround the server
  // incorrectly inserting a newline when writing out the table.
  table->erase(std::remove(table->begin(), table->end(), '\n'), table->end());
  // Replace in the actual loop device name.
  base::ReplaceSubstringsAfterOffset(table, 0, "ROOT_DEV", device_path);
  base::ReplaceSubstringsAfterOffset(table, 0, "HASH_DEV", device_path);
  // If the table does not specify an error condition, use the default (eio).
  // This is critical because the default behavior is to panic the device and
  // force a system recovery. Do not do this for component corruption.
  if (table->find("error_behavior") == std::string::npos)
    table->append(" error_behavior=eio");

  return true;
}

bool VerityMounter::Mount(const base::ScopedFD& image_fd,
                          const base::FilePath& mount_point,
                          const std::string& fs_type,
                          const std::string& table) {
  // First check if the component is already mounted and avoid unnecessary work.
  bool already_mounted = false;
  if (!CreateMountPointIfNeeded(mount_point, &already_mounted)) return false;
  if (already_mounted) return true;

  std::string loop_device_path;
  // We need to retry because another program could grap the loop device,
  // resulting in an EBUSY error. If that happens, run again and grab a new
  // device.
  int retries = GET_LOOP_DEVICE_MAX_RETRY;
  while (true) {
    MountStatus status = GetLoopDevice(image_fd, &loop_device_path);
    if (status == MountStatus::FAIL ||
        (status == MountStatus::RETRY && retries == 0)) {
      LOG(ERROR) << "GetLoopDevice failed, mount_point: "
                 << mount_point.value();
      return false;
    } else if (status == MountStatus::SUCCESS) {
      break;
    }
    --retries;
  }

  std::string dev_name;
  if (!SetupDeviceMapper(loop_device_path, table, &dev_name)) {
    LOG(ERROR) << "mount_point: " << mount_point.value();
    ClearLoopDevice(loop_device_path);
    return false;
  }

  if (mount(dev_name.c_str(), mount_point.value().c_str(), fs_type.c_str(),
            MS_RDONLY | MS_NOSUID | MS_NODEV, "") < 0) {
    PLOG(ERROR) << "mount, mount_point " << mount_point.value();
    ClearVerityDevice(dev_name);
    ClearLoopDevice(loop_device_path);
    return false;
  }

  return true;
}

// Takes a device mapper name and determines the loop device number.
bool MapperNameToLoop(const std::string& name, int32_t* loop) {
  std::string type;
  std::string parameters;
  if (!MapperGetEntry(name, &type, &parameters)) {
    return false;
  }

  if (type != "verity") {
    LOG(ERROR) << "Encountered unexpected mapping \"" << type
               << "\" instead of \"verity\".";
    return false;
  }

  return MapperParametersToLoop(parameters, loop);
}

bool Unmount(const base::FilePath& mount_point) {
  return umount(mount_point.value().c_str()) == 0;
}

// Returns (mount point, source path) pairs visible to this process. The order
// can be reversed to help with unmounting.
std::vector<std::pair<std::string, std::string>>
    GetAllMountPaths(bool reverse) {
  std::vector<std::pair<std::string, std::string>> mount_paths;
  base::ScopedFILE mountinfo(fopen("/proc/self/mounts", "re"));
  if (!mountinfo) {
    PLOG(ERROR) << "Failed to open \"/proc/self/mounts\".";
    return mount_paths;
  }

  // MNT_LINE_MAX from sys/mnttab.h is 1024, extra bytes are for null
  // termination of strings.
  static char buffer[1024 + 4];
  struct mntent mount_entry;
  while (getmntent_r(mountinfo.get(), &mount_entry, buffer, sizeof(buffer))) {
    mount_paths.emplace(reverse ? mount_paths.end() : mount_paths.begin(),
                        mount_entry.mnt_dir, mount_entry.mnt_fsname);
  }
  return mount_paths;
}

// Performs the a cleanup of a given mount point which should be tied to the
// given source path. This entails unmounting the mount point, removing the
// device mapper table entry, deleting the mount point folder, and freeing the
// loop device.
// Returns true on success.
bool CleanupImpl(const base::FilePath& mount_point,
                 const base::FilePath source_path) {
  const base::FilePath dev_mapper(kDeviceMapperPath);
  if (!IsAncestor(dev_mapper, source_path)) {
    LOG(ERROR) << source_path.value() << " is not device mapped!";
    return false;
  }

  // Lookup loop info.
  int32_t loop = -1;
  if (!MapperNameToLoop(source_path.BaseName().value(), &loop) ||
      loop < 0) {
    LOG(ERROR) << "Unable to determine loop device for " << source_path.value();
    return false;
  }

  // Unmount the image.
  if (!Unmount(mount_point)) {
    PLOG(ERROR) << "Unmount failed";
    return false;
  }
  // Delete mount target folder
  base::DeleteFile(mount_point, true);

  // Clear Verity device.
  if (!MapperWipeTable(source_path.value())) {
    PLOG(ERROR) << "Device mapper wipe table failed";
    return false;
  }
  if (!MapperRemove(source_path.value())) {
    PLOG(ERROR) << "Device mapper remove failed";
    return false;
  }

  // Clear loop device.
  ClearLoopDevice(base::StringPrintf("/dev/loop%d", loop));
  return true;
}

// Unmounts the given path, cleans up the device mapper entry, and frees the
// loop device for the specified mount point.
// Returns true on success.
bool VerityMounter::Cleanup(const base::FilePath& mount_point) {
  bool ret = true;
  for (const auto& mount_path : GetAllMountPaths(true)) {
    if (mount_point.value() == mount_path.first) {
      if (!CleanupImpl(mount_point, base::FilePath(mount_path.second))) {
        ret = false;
      }
    }
  }
  return ret;
}

// Performs a cleanup for all mount points under parent_dir.
// All successfully cleaned up mount points will be appended to "paths".
// Returns false if cleanup fails for any mount point.
bool VerityMounter::CleanupAll(bool dry_run,
                               const base::FilePath& parent_dir,
                               std::vector<base::FilePath>* paths) {
  bool ret = true;
  for (const auto& mount_path : GetAllMountPaths(true)) {
    base::FilePath fp_mount_path(mount_path.first);
    // It is not enough to check if fp_mount_path is a direct child because
    // some mount points, such as printer drivers, are mounted under a sub
    // folder.
    if (IsAncestor(parent_dir, fp_mount_path)) {
      if (dry_run) {
        if (paths) {
          paths->push_back(fp_mount_path);
        }
      } else if (CleanupImpl(fp_mount_path,
                             base::FilePath(mount_path.second))) {
        if (paths) {
          paths->push_back(fp_mount_path);
        }
      } else {
        LOG(ERROR) << "Failed to cleanup \"" << mount_path.first << "\"";
        ret = false;
      }
    }
  }
  return ret;
}

}  // namespace imageloader
