// Copyright (c) 2013 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 "cros-disks/fuse_mounter.h"

// Has to come before linux/fs.h due to conflicting definitions of MS_*
// constants.
#include <sys/mount.h>

#include <fcntl.h>
#include <linux/capability.h>
#include <linux/fs.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

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

#include <base/bind.h>
#include <base/callback_helpers.h>
#include <base/files/file.h>
#include <base/logging.h>
#include <base/memory/weak_ptr.h>
#include <base/stl_util.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <brillo/process/process_reaper.h>

#include "cros-disks/error_logger.h"
#include "cros-disks/mount_point.h"
#include "cros-disks/platform.h"
#include "cros-disks/quote.h"
#include "cros-disks/sandboxed_process.h"
#include "cros-disks/uri.h"

namespace cros_disks {

namespace {

const mode_t kSourcePathPermissions = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;

const char kFuseDeviceFile[] = "/dev/fuse";

template <typename T>
base::Optional<T> UnsetIfEmpty(T value) {
  if (value.empty())
    return base::Optional<T>();
  return base::Optional<T>(std::move(value));
}

// TODO(dats): Remove when it's done beforehead by the caller.
OwnerUser ResolveUserOrDie(const Platform* platform, const std::string& user) {
  OwnerUser result;
  PCHECK(platform->GetUserAndGroupId(user, &result.uid, &result.gid));
  result.gid = kChronosAccessGID;
  return result;
}

class FUSEMountPoint : public MountPoint {
 public:
  FUSEMountPoint(const base::FilePath& path, const Platform* platform)
      : MountPoint(path), platform_(platform) {}

  FUSEMountPoint(const FUSEMountPoint&) = delete;
  FUSEMountPoint& operator=(const FUSEMountPoint&) = delete;

  ~FUSEMountPoint() override { DestructorUnmount(); }

  base::WeakPtr<FUSEMountPoint> GetWeakPtr() {
    return weak_factory_.GetWeakPtr();
  }

  static void CleanUpCallback(const base::FilePath& mount_path,
                              base::WeakPtr<FUSEMountPoint> ptr,
                              const siginfo_t& info) {
    CHECK_EQ(SIGCHLD, info.si_signo);
    if (info.si_code != CLD_EXITED) {
      LOG(WARNING) << "FUSE daemon for " << quote(mount_path)
                   << " crashed with code " << info.si_code << " and status "
                   << info.si_status;
    } else if (info.si_status != 0) {
      LOG(WARNING) << "FUSE daemon for " << quote(mount_path)
                   << " exited with status " << info.si_status;
    } else {
      LOG(INFO) << "FUSE daemon for " << quote(mount_path)
                << " exited normally";
    }
    if (!ptr) {
      // If the MountPoint instance has been deleted, it was
      // already unmounted and cleaned up due to a
      // request from the browser (or logout). In this
      // case, there's nothing to do.
      // TODO(dats): Consolidate this logic into centralized place (likely
      //  MountPoint base class).
      return;
    }
    ptr->CleanUp();
  }

 private:
  // MountPoint overrides:
  MountErrorType UnmountImpl() override {
    // We take a 2-step approach to unmounting FUSE filesystems. First, try a
    // normal unmount. This lets the VFS flush any pending data and lets the
    // filesystem shut down cleanly. If the filesystem is busy, force unmount
    // the filesystem. This is done because there is no good recovery path the
    // user can take, and these filesystem are sometimes unmounted implicitly on
    // login/logout/suspend. This action is similar to native filesystems (i.e.
    // FAT32, ext2/3/4, etc) which are lazy unmounted if a regular unmount fails
    // because the filesystem is busy.

    MountErrorType error = platform_->Unmount(path().value(), 0 /* flags */);
    if (error != MOUNT_ERROR_PATH_ALREADY_MOUNTED) {
      // MOUNT_ERROR_PATH_ALREADY_MOUNTED is returned on EBUSY.
      return error;
    }

    // For FUSE filesystems, MNT_FORCE will cause the kernel driver to
    // immediately close the channel to the user-space driver program and cancel
    // all outstanding requests. However, if any program is still accessing the
    // filesystem, the umount2() will fail with EBUSY and the mountpoint will
    // still be attached. Since the mountpoint is no longer valid, use
    // MNT_DETACH to also force the mountpoint to be disconnected.
    LOG(WARNING) << "Mount point " << quote(path())
                 << " is busy, using force unmount";
    return platform_->Unmount(path().value(), MNT_FORCE | MNT_DETACH);
  }

  void CleanUp() {
    MountErrorType unmount_error = Unmount();
    LOG_IF(ERROR, unmount_error != MOUNT_ERROR_NONE)
        << "Cannot unmount FUSE mount point " << quote(path())
        << " after process exit: " << unmount_error;

    if (!platform_->RemoveEmptyDirectory(path().value())) {
      PLOG(ERROR) << "Cannot remove FUSE mount point " << quote(path().value())
                  << " after process exit";
    }
  }

  const Platform* platform_;

  base::WeakPtrFactory<FUSEMountPoint> weak_factory_{this};
};

bool GetPhysicalBlockSize(const std::string& source, int* size) {
  base::ScopedFD fd(open(source.c_str(), O_RDONLY | O_CLOEXEC));

  *size = 0;
  if (!fd.is_valid()) {
    PLOG(WARNING) << "Couldn't open " << source;
    return false;
  }

  if (ioctl(fd.get(), BLKPBSZGET, size) < 0) {
    PLOG(WARNING) << "Failed to get block size for" << source;
    return false;
  }

  return true;
}

}  // namespace

FUSESandboxedProcessFactory::FUSESandboxedProcessFactory(
    const Platform* platform,
    SandboxedExecutable executable,
    OwnerUser run_as,
    bool has_network_access,
    std::vector<gid_t> supplementary_groups,
    base::Optional<base::FilePath> mount_namespace)
    : platform_(platform),
      executable_(std::move(executable.executable)),
      seccomp_policy_(std::move(executable.seccomp_policy)),
      run_as_(std::move(run_as)),
      has_network_access_(has_network_access),
      supplementary_groups_(std::move(supplementary_groups)),
      mount_namespace_(std::move(mount_namespace)) {
  CHECK(executable_.IsAbsolute());
  if (seccomp_policy_) {
    CHECK(seccomp_policy_.value().IsAbsolute());
  }
  if (mount_namespace_) {
    CHECK(mount_namespace_.value().IsAbsolute());
  }
}

FUSESandboxedProcessFactory::~FUSESandboxedProcessFactory() = default;

std::unique_ptr<SandboxedProcess>
FUSESandboxedProcessFactory::CreateSandboxedProcess() const {
  auto sandbox = std::make_unique<SandboxedProcess>();
  if (!ConfigureSandbox(sandbox.get()))
    return nullptr;
  return sandbox;
}

bool FUSESandboxedProcessFactory::ConfigureSandbox(
    SandboxedProcess* sandbox) const {
  sandbox->SetCapabilities(0);
  sandbox->SetNoNewPrivileges();

  // The FUSE mount program is put under a new mount namespace, so mounts
  // inside that namespace don't normally propagate.
  sandbox->NewMountNamespace();
  sandbox->SkipRemountPrivate();

  // TODO(benchan): Re-enable cgroup namespace when either Chrome OS
  // kernel 3.8 supports it or no more supported devices use kernel
  // 3.8.
  // mount_process.NewCgroupNamespace();

  sandbox->NewIpcNamespace();

  sandbox->NewPidNamespace();

  // Prepare mounts for pivot_root.
  if (!sandbox->SetUpMinimalMounts()) {
    LOG(ERROR) << "Cannot set up minijail mounts";
    return false;
  }

  // /run is the place where mutable system configs are being kept.
  // We don't expose them by default, but to be able to bind them when
  // needed /run needs to be writeable.
  if (!sandbox->Mount("tmpfs", "/run", "tmpfs", "mode=0755,size=1M")) {
    LOG(ERROR) << "Cannot mount /run";
    return false;
  }

  if (!has_network_access_) {
    sandbox->NewNetworkNamespace();
  } else {
    // Network DNS configs are in /run/shill.
    if (!sandbox->BindMount("/run/shill", "/run/shill", false, false)) {
      LOG(ERROR) << "Cannot bind /run/shill";
      return false;
    }
    // Hardcoded hosts are mounted into /etc/hosts.d when Crostini is enabled.
    if (platform_->PathExists("/etc/hosts.d") &&
        !sandbox->BindMount("/etc/hosts.d", "/etc/hosts.d", false, false)) {
      LOG(ERROR) << "Cannot bind /etc/hosts.d";
      return false;
    }
  }

  if (!sandbox->EnterPivotRoot()) {
    LOG(ERROR) << "Cannot pivot root";
    return false;
  }

  if (seccomp_policy_) {
    if (!platform_->PathExists(seccomp_policy_.value().value())) {
      LOG(ERROR) << "Seccomp policy " << quote(seccomp_policy_.value())
                 << " is missing";
      return false;
    }
    sandbox->LoadSeccompFilterPolicy(seccomp_policy_.value().value());
  }

  sandbox->SetUserId(run_as_.uid);
  sandbox->SetGroupId(run_as_.gid);
  if (!supplementary_groups_.empty()) {
    sandbox->SetSupplementaryGroupIds(supplementary_groups_);
  }

  // Enter mount namespace in the sandbox if necessary.
  if (mount_namespace_) {
    sandbox->EnterExistingMountNamespace(mount_namespace_.value().value());
  }

  if (!platform_->PathExists(executable_.value())) {
    LOG(ERROR) << "Cannot find mount program " << quote(executable_);
    return false;
  }
  sandbox->AddArgument(executable_.value());

  return true;
}

FUSEMounter::FUSEMounter(const Platform* platform,
                         brillo::ProcessReaper* process_reaper,
                         std::string filesystem_type,
                         bool nosymfollow)
    : platform_(platform),
      process_reaper_(process_reaper),
      filesystem_type_(std::move(filesystem_type)),
      nosymfollow_(nosymfollow) {}

FUSEMounter::~FUSEMounter() = default;

std::unique_ptr<MountPoint> FUSEMounter::Mount(
    const std::string& source,
    const base::FilePath& target_path,
    std::vector<std::string> params,
    MountErrorType* error) const {
  // Read-only is the only parameter that has any effect at this layer.
  const bool read_only = IsReadOnlyMount(params);

  const base::File fuse_file = base::File(
      base::FilePath(kFuseDeviceFile),
      base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE);
  if (!fuse_file.IsValid()) {
    LOG(ERROR) << "Unable to open FUSE device file. Error: "
               << fuse_file.error_details() << " "
               << base::File::ErrorToString(fuse_file.error_details());
    *error = MOUNT_ERROR_INTERNAL;
    return nullptr;
  }

  // Mount options for FUSE:
  // fd - File descriptor for /dev/fuse.
  // user_id/group_id - user/group for file access control. Essentially
  //     bypassed due to allow_other, but still required to be set.
  // allow_other - Allows users other than user_id/group_id to access files
  //     on the file system. By default, FUSE prevents any process other than
  //     ones running under user_id/group_id to access files, regardless of
  //     the file's permissions.
  // default_permissions - Enforce permission checking.
  // rootmode - Mode bits for the root inode.
  std::string fuse_mount_options = base::StringPrintf(
      "fd=%d,user_id=%u,group_id=%u,allow_other,default_permissions,"
      "rootmode=%o",
      fuse_file.GetPlatformFile(), kChronosUID, kChronosAccessGID, S_IFDIR);

  std::string fuse_type = "fuse";
  std::string source_descr = source;
  base::stat_wrapper_t statbuf = {0};
  if (platform_->Lstat(source, &statbuf) && S_ISBLK(statbuf.st_mode)) {
    int blksize = 0;

    // TODO(crbug.com/931500): It's possible that specifying a block size equal
    // to the file system cluster size (which might be larger than the physical
    // block size) might be more efficient. Data would be needed to see what
    // kind of performance benefit, if any, could be gained. At the very least,
    // specify the block size of the underlying device. Without this, UFS cards
    // with 4k sector size will fail to mount.
    if (GetPhysicalBlockSize(source, &blksize) && blksize > 0)
      fuse_mount_options.append(base::StringPrintf(",blksize=%d", blksize));

    LOG(INFO) << "Source file " << quote(source)
              << " is a block device with block size " << blksize;

    fuse_type = "fuseblk";
  } else {
    source_descr = "fuse:" + source;
  }

  if (!filesystem_type_.empty()) {
    fuse_type += ".";
    fuse_type += filesystem_type_;
  }
  *error = platform_->Mount(source_descr, target_path.value(), fuse_type,
                            MountOptions::kMountFlags | MS_DIRSYNC |
                                (read_only ? MS_RDONLY : 0) |
                                (nosymfollow_ ? MS_NOSYMFOLLOW : 0),
                            fuse_mount_options);

  if (*error != MOUNT_ERROR_NONE) {
    LOG(ERROR) << "Cannot perform unprivileged FUSE mount: " << *error;
    return nullptr;
  }

  pid_t pid =
      StartDaemon(fuse_file, source, target_path, std::move(params), error);
  if (*error != MOUNT_ERROR_NONE || pid == Process::kInvalidProcessId) {
    LOG(ERROR) << "FUSE daemon start failure: " << *error;
    LOG(INFO) << "FUSE cleanup on start failure for " << quote(target_path);
    MountErrorType unmount_error =
        platform_->Unmount(target_path.value(), MNT_FORCE | MNT_DETACH);
    LOG_IF(ERROR, unmount_error != MOUNT_ERROR_NONE)
        << "Cannot unmount FUSE mount point " << quote(target_path)
        << " after launch failure: " << unmount_error;
    return nullptr;
  }

  // At this point, the FUSE daemon has successfully started.
  std::unique_ptr<FUSEMountPoint> mount_point =
      std::make_unique<FUSEMountPoint>(target_path, platform_);

  // Add a watcher that cleans up the FUSE mount when the process exits.
  // This is defined as in-jail "init" process, denoted by pid(),
  // terminates, which happens only when the last process in the jailed PID
  // namespace terminates.
  process_reaper_->WatchForChild(
      FROM_HERE, pid,
      base::BindOnce(&FUSEMountPoint::CleanUpCallback, target_path,
                     mount_point->GetWeakPtr()));

  *error = MOUNT_ERROR_NONE;
  return std::move(mount_point);
}

pid_t FUSEMounter::StartDaemon(const base::File& fuse_file,
                               const std::string& source,
                               const base::FilePath& target_path,
                               std::vector<std::string> params,
                               MountErrorType* error) const {
  auto mount_process =
      PrepareSandbox(source, target_path, std::move(params), error);
  if (*error != MOUNT_ERROR_NONE) {
    return Process::kInvalidProcessId;
  }

  mount_process->AddArgument(
      base::StringPrintf("/dev/fd/%d", fuse_file.GetPlatformFile()));

  std::vector<std::string> output;
  const int return_code = mount_process->Run(&output);
  *error = InterpretReturnCode(return_code);

  if (*error != MOUNT_ERROR_NONE) {
    const auto& executable = mount_process->arguments()[0];
    if (!output.empty()) {
      LOG(ERROR) << "FUSE mount program " << quote(executable) << " outputted "
                 << output.size() << " lines:";
      for (const std::string& line : output) {
        LOG(ERROR) << line;
      }
    }
    LOG(ERROR) << "FUSE mount program " << quote(executable)
               << " returned error code " << return_code;
    return Process::kInvalidProcessId;
  }

  return mount_process->pid();
}

MountErrorType FUSEMounter::InterpretReturnCode(int return_code) const {
  if (return_code != 0)
    return MOUNT_ERROR_MOUNT_PROGRAM_FAILED;
  return MOUNT_ERROR_NONE;
}

FUSEMounterHelper::FUSEMounterHelper(
    const Platform* platform,
    brillo::ProcessReaper* process_reaper,
    std::string filesystem_type,
    bool nosymfollow,
    const SandboxedProcessFactory* sandbox_factory)
    : FUSEMounter(
          platform, process_reaper, std::move(filesystem_type), nosymfollow),
      sandbox_factory_(sandbox_factory) {}

FUSEMounterHelper::~FUSEMounterHelper() = default;

std::unique_ptr<SandboxedProcess> FUSEMounterHelper::PrepareSandbox(
    const std::string& source,
    const base::FilePath& target_path,
    std::vector<std::string> params,
    MountErrorType* error) const {
  auto sandbox = sandbox_factory_->CreateSandboxedProcess();
  *error =
      ConfigureSandbox(source, target_path, std::move(params), sandbox.get());
  if (*error != MOUNT_ERROR_NONE) {
    return nullptr;
  }
  return sandbox;
}

FUSEMounterLegacy::FUSEMounterLegacy(Params params)
    : FUSEMounter(params.platform,
                  params.process_reaper,
                  std::move(params.filesystem_type),
                  params.nosymfollow),
      metrics_(params.metrics),
      metrics_name_(std::move(params.metrics_name)),
      seccomp_policy_(),
      bind_paths_(std::move(params.bind_paths)),
      password_needed_codes_(std::move(params.password_needed_codes)),
      mount_options_(std::move(params.mount_options)),
      sandbox_factory_(
          platform(),
          {base::FilePath(std::move(params.mount_program)),
           UnsetIfEmpty(base::FilePath(std::move(params.seccomp_policy)))},
          ResolveUserOrDie(platform(), params.mount_user),
          params.network_access,
          std::move(params.supplementary_groups),
          UnsetIfEmpty(base::FilePath(std::move(params.mount_namespace)))) {}

void FUSEMounterLegacy::CopyPassword(const std::vector<std::string>& options,
                                     Process* const process) const {
  DCHECK(process);

  // Is the process "password-aware"?
  if (password_needed_codes_.empty())
    return;

  // Is there a password available in options?
  const base::StringPiece prefix = "password=";
  const auto it = std::find_if(options.cbegin(), options.cend(),
                               [prefix](const base::StringPiece s) {
                                 return base::StartsWith(s, prefix);
                               });
  if (it == options.cend())
    return;

  // Pass the password via stdin.
  process->SetStdIn(it->substr(prefix.size()));
}

std::unique_ptr<SandboxedProcess> FUSEMounterLegacy::PrepareSandbox(
    const std::string& source,
    const base::FilePath& target_path,
    std::vector<std::string> params,
    MountErrorType* error) const {
  std::unique_ptr<SandboxedProcess> mount_process = CreateSandboxedProcess();

  // TODO(crbug.com/1053778) Only create the necessary tmpfs filesystems.
  for (const char* const dir : {"/home", "/media"}) {
    if (!mount_process->Mount("tmpfs", dir, "tmpfs", "mode=0755,size=10M")) {
      LOG(ERROR) << "Cannot mount " << quote(dir);
      *error = MOUNT_ERROR_INTERNAL;
      return nullptr;
    }
  }

  // Data dirs if any are mounted inside /run/fuse.
  if (!mount_process->BindMount("/run/fuse", "/run/fuse", false, false)) {
    LOG(ERROR) << "Can't bind /run/fuse";
    return nullptr;
  }

  // If a block device is being mounted, bind mount it into the sandbox.
  if (base::StartsWith(source, "/dev/", base::CompareCase::SENSITIVE)) {
    // Re-own source.
    if (!platform()->SetOwnership(source, getuid(),
                                  sandbox_factory_.run_as().gid) ||
        !platform()->SetPermissions(source, kSourcePathPermissions)) {
      LOG(ERROR) << "Can't set up permissions on " << quote(source);
      *error = MOUNT_ERROR_INSUFFICIENT_PERMISSIONS;
      return nullptr;
    }

    if (!mount_process->BindMount(source, source, true, false)) {
      LOG(ERROR) << "Cannot bind mount device " << quote(source);
      *error = MOUNT_ERROR_INVALID_ARGUMENT;
      return nullptr;
    }
  }

  // This is for additional data dirs.
  for (const BindPath& bind_path : bind_paths_) {
    if (!mount_process->BindMount(bind_path.path, bind_path.path,
                                  bind_path.writable, bind_path.recursive)) {
      LOG(ERROR) << "Cannot bind-mount " << quote(bind_path.path);
      *error = MOUNT_ERROR_INVALID_ARGUMENT;
      return nullptr;
    }
  }

  {
    // TODO(dats): This it leaking legacy options implementation. Remove it.
    std::string options_string = mount_options_.ToFuseMounterOptions();
    DCHECK(!options_string.empty());
    mount_process->AddArgument("-o");
    mount_process->AddArgument(std::move(options_string));
  }

  if (!source.empty()) {
    mount_process->AddArgument(source);
  }

  CopyPassword(params, mount_process.get());

  return mount_process;
}

MountErrorType FUSEMounterLegacy::InterpretReturnCode(int return_code) const {
  if (metrics_ && !metrics_name_.empty())
    metrics_->RecordFuseMounterErrorCode(metrics_name_, return_code);

  if (base::Contains(password_needed_codes_, return_code))
    return MOUNT_ERROR_NEED_PASSWORD;

  return FUSEMounter::InterpretReturnCode(return_code);
}

bool FUSEMounterLegacy::CanMount(const std::string& source,
                                 const std::vector<std::string>& params,
                                 base::FilePath* suggested_name) const {
  NOTREACHED();
  return true;
}

std::unique_ptr<SandboxedProcess> FUSEMounterLegacy::CreateSandboxedProcess()
    const {
  return sandbox_factory_.CreateSandboxedProcess();
}

}  // namespace cros_disks
