// 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"

#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 <memory>
#include <string>
#include <utility>

#include <base/macros.h>
#include <base/bind.h>
#include <base/callback_helpers.h>
#include <base/files/file.h>
#include <base/logging.h>
#include <base/strings/stringprintf.h>
#include <base/strings/string_util.h>
#include <brillo/process_reaper.h>

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

namespace cros_disks {

namespace {

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

const char kFuseDeviceFile[] = "/dev/fuse";
const MountOptions::Flags kRequiredFuseMountFlags =
    MS_NODEV | MS_NOEXEC | MS_NOSUID;

void CleanUpCallback(base::OnceClosure cleanup,
                     const base::FilePath& mount_path,
                     const siginfo_t& info) {
  CHECK_EQ(SIGCHLD, info.si_signo);
  if (info.si_code != CLD_EXITED || info.si_status != 0) {
    LOG(WARNING) << "FUSE daemon for " << quote(mount_path)
                 << " exited with code " << info.si_code << " and status "
                 << info.si_status;
  } else {
    LOG(INFO) << "FUSE daemon for " << quote(mount_path) << " exited normally";
  }
  std::move(cleanup).Run();
}

MountErrorType ConfigureCommonSandbox(SandboxedProcess* sandbox,
                                      const Platform* platform,
                                      bool network_ns,
                                      const base::FilePath& seccomp) {
  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();

  // TODO(crbug.com/707327): Remove this when we get rid of AVFS.
  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();

  if (network_ns) {
    sandbox->NewNetworkNamespace();
  }

  if (!seccomp.empty()) {
    if (!platform->PathExists(seccomp.value())) {
      LOG(ERROR) << "Seccomp policy " << quote(seccomp) << " is missing";
      return MOUNT_ERROR_INTERNAL;
    }
    sandbox->LoadSeccompFilterPolicy(seccomp.value());
  }

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

  // Data dirs if any are mounted inside /run/fuse.
  if (!sandbox->Mount("tmpfs", "/run", "tmpfs", "mode=0755,size=10M")) {
    LOG(ERROR) << "Can't mount /run";
    return MOUNT_ERROR_INTERNAL;
  }
  if (!sandbox->BindMount("/run/fuse", "/run/fuse", false, false)) {
    LOG(ERROR) << "Can't bind /run/fuse";
    return MOUNT_ERROR_INTERNAL;
  }

  if (!network_ns) {
    // Network DNS configs are in /run/shill.
    if (!sandbox->BindMount("/run/shill", "/run/shill", false, false)) {
      LOG(ERROR) << "Can't bind /run/shill";
      return MOUNT_ERROR_INTERNAL;
    }
    // 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) << "Can't bind /etc/hosts.d";
      return MOUNT_ERROR_INTERNAL;
    }
  }
  if (!sandbox->EnterPivotRoot()) {
    LOG(ERROR) << "Can't pivot root";
    return MOUNT_ERROR_INTERNAL;
  }

  return MOUNT_ERROR_NONE;
}

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;
}

MountErrorType MountFuseDevice(const Platform* platform,
                               const std::string& source,
                               const std::string& filesystem_type,
                               const base::FilePath& target,
                               const base::File& fuse_file,
                               uid_t mount_user_id,
                               gid_t mount_group_id,
                               const MountOptions& options) {
  // 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(), mount_user_id, mount_group_id, S_IFDIR);

  // "nosymfollow" is a special mount option that's passed to the Chromium LSM
  // and not forwarded to the FUSE driver. If it's set, add it as a mount
  // option.
  if (options.HasOption(MountOptions::kOptionNoSymFollow)) {
    fuse_mount_options.append(",");
    fuse_mount_options.append(MountOptions::kOptionNoSymFollow);
  }

  std::string fuse_type = "fuse";
  struct stat statbuf = {0};
  if (stat(source.c_str(), &statbuf) == 0 && 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";
  }
  if (!filesystem_type.empty()) {
    fuse_type += ".";
    fuse_type += filesystem_type;
  }

  auto flags = options.ToMountFlagsAndData().first;

  return platform->Mount(source.empty() ? filesystem_type : source,
                         target.value(), fuse_type,
                         flags | kRequiredFuseMountFlags, fuse_mount_options);
}

}  // namespace

FUSEMounter::FUSEMounter(const std::string& source_path,
                         const std::string& target_path,
                         const std::string& filesystem_type,
                         const MountOptions& mount_options,
                         const Platform* platform,
                         brillo::ProcessReaper* process_reaper,
                         const std::string& mount_program_path,
                         const std::string& mount_user,
                         const std::string& seccomp_policy,
                         const std::vector<BindPath>& accessible_paths,
                         bool permit_network_access,
                         const std::string& mount_group)
    : MounterCompat(filesystem_type,
                    source_path,
                    base::FilePath(target_path),
                    mount_options),
      platform_(platform),
      process_reaper_(process_reaper),
      mount_program_path_(mount_program_path),
      mount_user_(mount_user),
      mount_group_(mount_group),
      seccomp_policy_(seccomp_policy),
      accessible_paths_(accessible_paths),
      permit_network_access_(permit_network_access) {}

MountErrorType FUSEMounter::MountImpl() const {
  auto mount_process = CreateSandboxedProcess();
  MountErrorType error = ConfigureCommonSandbox(
      mount_process.get(), platform_, !permit_network_access_,
      base::FilePath(seccomp_policy_));
  if (error != MOUNT_ERROR_NONE) {
    return error;
  }

  uid_t mount_user_id;
  gid_t mount_group_id;
  if (!platform_->GetUserAndGroupId(mount_user_, &mount_user_id,
                                    &mount_group_id)) {
    LOG(ERROR) << "Cannot resolve user " << quote(mount_user_);
    return MOUNT_ERROR_INTERNAL;
  }
  if (!mount_group_.empty() &&
      !platform_->GetGroupId(mount_group_, &mount_group_id)) {
    return MOUNT_ERROR_INTERNAL;
  }

  mount_process->SetUserId(mount_user_id);
  mount_process->SetGroupId(mount_group_id);

  if (!platform_->PathExists(mount_program_path_)) {
    LOG(ERROR) << "Cannot find mount program " << quote(mount_program_path_);
    return MOUNT_ERROR_MOUNT_PROGRAM_NOT_FOUND;
  }
  mount_process->AddArgument(mount_program_path_);

  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());
    return MOUNT_ERROR_INTERNAL;
  }

  error = MountFuseDevice(platform_, source(), filesystem_type(),
                          base::FilePath(target_path()), fuse_file,
                          mount_user_id, mount_group_id, mount_options());
  if (error != MOUNT_ERROR_NONE) {
    LOG(ERROR) << "Can't perform unprivileged FUSE mount: " << error;
    return error;
  }

  // The |fuse_failure_unmounter| closure runner is used to unmount the FUSE
  // filesystem if any part of starting the FUSE helper process fails.
  // TODO(crbug.com/993857): Use base::BindOnce().
  base::ScopedClosureRunner fuse_cleanup_runner(base::Bind(
      [](const Platform* platform, const std::string& target_path) {
        if (!platform->DirectoryExists(target_path)) {
          // If the mount directory doesn't exist, don't try to unmount and
          // remove it. This will happen when the browser requests to unmount
          // the filesystem. In this case, both the following operations are
          // unnecessary and will fail, resulting in log spam.
          return;
        }

        MountErrorType unmount_error = platform->Unmount(target_path, 0);
        LOG_IF(ERROR, unmount_error != MOUNT_ERROR_NONE)
            << "Cannot unmount FUSE mount point " << quote(target_path) << ": "
            << unmount_error;

        if (!platform->RemoveEmptyDirectory(target_path)) {
          PLOG(ERROR) << "Cannot remove FUSE mount point "
                      << quote(target_path);
        }
      },
      platform_, target_path().value()));

  // Source might be an URI. Only try to re-own source if it looks like
  // an existing path.
  if (!source().empty() && platform_->PathExists(source())) {
    if (!platform_->SetOwnership(source(), getuid(), mount_group_id) ||
        !platform_->SetPermissions(source(), kSourcePathPermissions)) {
      LOG(ERROR) << "Can't set up permissions on the source";
      return MOUNT_ERROR_INSUFFICIENT_PERMISSIONS;
    }
  }

  // If a block device is being mounted, bind mount it into the sandbox.
  if (base::StartsWith(source(), "/dev/", base::CompareCase::SENSITIVE)) {
    if (!mount_process->BindMount(source(), source(), true, false)) {
      LOG(ERROR) << "Cannot bind mount device " << quote(source());
      return MOUNT_ERROR_INVALID_ARGUMENT;
    }
  }

  // TODO(crbug.com/933018): Remove when DriveFS helper is refactored.
  if (!mount_process->Mount("tmpfs", "/home", "tmpfs", "mode=0755,size=10M")) {
    LOG(ERROR) << "Can't mount /home";
    return MOUNT_ERROR_INTERNAL;
  }

  // This is for additional data dirs.
  for (const auto& path : accessible_paths_) {
    if (!mount_process->BindMount(path.path, path.path, path.writable,
                                  path.recursive)) {
      LOG(ERROR) << "Can't bind " << path.path;
      return MOUNT_ERROR_INVALID_ARGUMENT;
    }
  }

  std::string options_string = mount_options().ToString();
  if (!options_string.empty()) {
    mount_process->AddArgument("-o");
    mount_process->AddArgument(options_string);
  }
  if (!source().empty()) {
    mount_process->AddArgument(source());
  }
  mount_process->AddArgument(
      base::StringPrintf("/dev/fd/%d", fuse_file.GetPlatformFile()));

  std::vector<std::string> output;
  int return_code = mount_process->Run(&output);
  if (return_code != 0) {
    LOG(ERROR) << "FUSE mount program failed with return code " << return_code;
    if (!output.empty()) {
      LOG(ERROR) << "FUSE mount program outputted " << output.size()
                 << " lines:";
      for (const std::string& line : output) {
        LOG(ERROR) << line;
      }
    }
    return MOUNT_ERROR_MOUNT_PROGRAM_FAILED;
  }

  // At this point, the FUSE daemon has successfully started, so repurpose
  // the FUSE cleanup closure runner to run on daemon quitting.
  // 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, mount_process->pid(),
      base::BindOnce(CleanUpCallback, fuse_cleanup_runner.Release(),
                     target_path()));

  return MOUNT_ERROR_NONE;
}

std::unique_ptr<SandboxedProcess> FUSEMounter::CreateSandboxedProcess() const {
  return std::make_unique<SandboxedProcess>();
}

}  // namespace cros_disks
