// 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 char kFuseDeviceFile[] = "/dev/fuse";

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,
                         Config config)
    : platform_(platform),
      process_reaper_(process_reaper),
      filesystem_type_(std::move(filesystem_type)),
      config_(std::move(config)) {}

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 = config_.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) |
                                (config_.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 = 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;
}

}  // namespace cros_disks
