// Copyright 2019 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 "cryptohome/storage/mount_helper.h"

#include <sys/stat.h>

#include <memory>
#include <vector>

#include <base/bind.h>
#include <base/callback_helpers.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/strings/stringprintf.h>
#include <brillo/cryptohome.h>
#include <brillo/secure_blob.h>

#include "cryptohome/cryptohome_common.h"
#include "cryptohome/filesystem_layout.h"
#include "cryptohome/storage/homedirs.h"
#include "cryptohome/storage/mount_constants.h"

using base::FilePath;
using base::StringPrintf;
using brillo::cryptohome::home::GetRootPath;
using brillo::cryptohome::home::GetUserPath;
using brillo::cryptohome::home::SanitizeUserName;
using brillo::cryptohome::home::SanitizeUserNameWithSalt;

namespace cryptohome {
const char kEphemeralCryptohomeRootContext[] =
    "u:object_r:cros_home_shadow_uid:s0";
}

namespace {
constexpr uid_t kMountOwnerUid = 0;
constexpr gid_t kMountOwnerGid = 0;
constexpr gid_t kDaemonStoreGid = 400;

const int kDefaultEcryptfsKeySize = CRYPTOHOME_AES_KEY_BYTES;

FilePath GetUserEphemeralMountDirectory(
    const std::string& obfuscated_username) {
  return FilePath(cryptohome::kEphemeralCryptohomeDir)
      .Append(cryptohome::kEphemeralMountDir)
      .Append(obfuscated_username);
}

FilePath GetMountedEphemeralRootHomePath(
    const std::string& obfuscated_username) {
  return GetUserEphemeralMountDirectory(obfuscated_username)
      .Append(cryptohome::kRootHomeSuffix);
}

FilePath GetMountedEphemeralUserHomePath(
    const std::string& obfuscated_username) {
  return GetUserEphemeralMountDirectory(obfuscated_username)
      .Append(cryptohome::kUserHomeSuffix);
}

FilePath VaultPathToUserPath(const FilePath& vault) {
  return vault.Append(cryptohome::kUserHomeSuffix);
}

FilePath VaultPathToRootPath(const FilePath& vault) {
  return vault.Append(cryptohome::kRootHomeSuffix);
}

// Sets up the SELinux context for a freshly mounted ephemeral cryptohome.
bool SetUpSELinuxContextForEphemeralCryptohome(cryptohome::Platform* platform,
                                               const FilePath& source_path) {
  // Note that this is needed because the newly mounted ephemeral cryptohome is
  // a new file system, and thus the SELinux context that applies to the
  // mountpoint will not apply to the new root directory in the filesystem.
  return platform->SetSELinuxContext(
      source_path, cryptohome::kEphemeralCryptohomeRootContext);
}

constexpr mode_t kSkeletonSubDirMode = S_IRWXU | S_IRGRP | S_IXGRP;
constexpr mode_t kUserMountPointMode = S_IRWXU | S_IRGRP | S_IXGRP;
constexpr mode_t kRootMountPointMode = S_IRWXU;
constexpr mode_t kAccessMode = S_IRWXU | S_IRGRP | S_IXGRP;
constexpr mode_t kRootDirMode = S_IRWXU | S_IRWXG | S_ISVTX;

constexpr mode_t kTrackedDirMode = S_IRWXU;
constexpr mode_t kPathComponentDirMode = S_IRWXU;
constexpr mode_t kGroupExecAccess = S_IXGRP;
constexpr mode_t kGroupWriteAccess = S_IWGRP;

}  // namespace

namespace cryptohome {

const char kDefaultHomeDir[] = "/home/chronos/user";

std::vector<DirectoryACL> MountHelper::GetCommonSubdirectories(
    uid_t uid, gid_t gid, gid_t access_gid) {
  return std::vector<DirectoryACL>{
      {FilePath(kUserHomeSuffix).Append(kDownloadsDir), kAccessMode, uid,
       access_gid},
      {FilePath(kUserHomeSuffix).Append(kMyFilesDir), kAccessMode, uid,
       access_gid},
      {FilePath(kUserHomeSuffix).Append(kMyFilesDir).Append(kDownloadsDir),
       kAccessMode, uid, access_gid},
  };
}

std::vector<DirectoryACL> MountHelper::GetCacheSubdirectories(
    uid_t uid, gid_t gid, gid_t access_gid) {
  return std::vector<DirectoryACL>{
      {FilePath(kUserHomeSuffix).Append(kGCacheDir), kAccessMode, uid,
       access_gid},
      {FilePath(kUserHomeSuffix).Append(kCacheDir), kTrackedDirMode, uid, gid},
  };
}

std::vector<DirectoryACL> MountHelper::GetGCacheSubdirectories(uid_t uid,
                                                               gid_t gid,
                                                               gid_t access_gid,
                                                               bool v1_dirs) {
  DirectoryACL gcache_v2_subdir = {
      FilePath(kUserHomeSuffix).Append(kGCacheDir).Append(kGCacheVersion2Dir),
      kAccessMode | kGroupWriteAccess, uid, access_gid};

  std::vector<DirectoryACL> gcache_v1_subdirs = {
      {FilePath(kUserHomeSuffix).Append(kGCacheDir).Append(kGCacheVersion1Dir),
       kAccessMode, uid, access_gid},
      {FilePath(kUserHomeSuffix)
           .Append(kGCacheDir)
           .Append(kGCacheVersion1Dir)
           .Append(kGCacheBlobsDir),
       kTrackedDirMode, uid, gid},
      {FilePath(kUserHomeSuffix)
           .Append(kGCacheDir)
           .Append(kGCacheVersion1Dir)
           .Append(kGCacheTmpDir),
       kTrackedDirMode, uid, gid},
  };

  if (v1_dirs) {
    gcache_v1_subdirs.push_back(gcache_v2_subdir);
    return gcache_v1_subdirs;
  }

  return {gcache_v2_subdir};
}

std::vector<DirectoryACL> MountHelper::GetTrackedSubdirectories(
    uid_t uid, gid_t gid, gid_t access_gid) {
  std::vector<DirectoryACL> durable_only_subdirs{
      {FilePath(kRootHomeSuffix), kRootDirMode, kMountOwnerUid,
       kDaemonStoreGid},
      {FilePath(kUserHomeSuffix), kTrackedDirMode | kGroupExecAccess, uid,
       access_gid},
  };

  std::vector<DirectoryACL> common_subdirs =
      GetCommonSubdirectories(uid, gid, access_gid);

  std::vector<DirectoryACL> cache_subdirs =
      GetCacheSubdirectories(uid, gid, access_gid);

  std::vector<DirectoryACL> gcache_subdirs =
      GetGCacheSubdirectories(uid, gid, access_gid, /*v1_dirs=*/true);

  auto result = durable_only_subdirs;
  result.insert(result.end(), common_subdirs.begin(), common_subdirs.end());
  result.insert(result.end(), cache_subdirs.begin(), cache_subdirs.end());
  result.insert(result.end(), gcache_subdirs.begin(), gcache_subdirs.end());
  return result;
}

// static
FilePath MountHelper::GetNewUserPath(const std::string& username) {
  std::string sanitized = SanitizeUserName(username);
  std::string user_dir = StringPrintf("u-%s", sanitized.c_str());
  return FilePath("/home")
      .Append(cryptohome::kDefaultSharedUser)
      .Append(user_dir);
}

// static
FilePath MountHelper::GetEphemeralSparseFile(
    const std::string& obfuscated_username) {
  return FilePath(cryptohome::kEphemeralCryptohomeDir)
      .Append(kSparseFileDir)
      .Append(obfuscated_username);
}

FilePath MountHelper::GetMountedUserHomePath(
    const std::string& obfuscated_username) const {
  return GetUserMountDirectory(obfuscated_username).Append(kUserHomeSuffix);
}

FilePath MountHelper::GetMountedRootHomePath(
    const std::string& obfuscated_username) const {
  return GetUserMountDirectory(obfuscated_username).Append(kRootHomeSuffix);
}

bool MountHelper::EnsurePathComponent(const FilePath& check_path,
                                      uid_t uid,
                                      gid_t gid) const {
  base::stat_wrapper_t st;
  if (!platform_->Stat(check_path, &st)) {
    // Dirent not there, so create and set ownership.
    if (!platform_->SafeCreateDirAndSetOwnershipAndPermissions(
            check_path, kPathComponentDirMode, uid, gid)) {
      PLOG(ERROR) << "Can't create: " << check_path.value();
      return false;
    }
  } else {
    // Dirent there; make sure it's acceptable.
    if (!S_ISDIR(st.st_mode)) {
      LOG(ERROR) << "Non-directory path: " << check_path.value();
      return false;
    }
    if (st.st_uid != uid) {
      LOG(ERROR) << "Owner mismatch: " << check_path.value() << " " << st.st_uid
                 << " != " << uid;
      return false;
    }
    if (st.st_gid != gid) {
      LOG(ERROR) << "Group mismatch: " << check_path.value() << " " << st.st_gid
                 << " != " << gid;
      return false;
    }
    if (st.st_mode & S_IWOTH) {
      LOG(ERROR) << "Permissions too lenient: " << check_path.value() << " has "
                 << std::oct << st.st_mode;
      return false;
    }
  }
  return true;
}

void MountHelper::CreateHomeSubdirectories(const FilePath& vault_path) const {
  FilePath user_path(VaultPathToUserPath(vault_path));
  FilePath root_path(VaultPathToRootPath(vault_path));
  base::stat_wrapper_t st;

  // This check makes the creation idempotent; if we completed creation,
  // root_path will exist and we're done, and if we didn't complete it, we can
  // finish it.
  if (platform_->Stat(root_path, &st) && S_ISDIR(st.st_mode) &&
      st.st_mode & S_ISVTX && st.st_uid == kMountOwnerUid &&
      st.st_gid == kDaemonStoreGid) {
    return;
  }

  // There are three ways to get here:
  // 1) the Stat() call above succeeded, but what we saw was not a root-owned
  //    directory.
  // 2) the Stat() call above failed with -ENOENT
  // 3) the Stat() call above failed for some other reason
  // In any of these cases, it is safe for us to rm root_path, since the only
  // way it could have gotten there is if someone undertook some funny business
  // as root.
  platform_->DeletePathRecursively(root_path);

  if (!platform_->SafeCreateDirAndSetOwnershipAndPermissions(
          user_path, kTrackedDirMode | kGroupExecAccess, default_uid_,
          default_access_gid_)) {
    PLOG(ERROR) << "SafeCreateDirAndSetOwnershipAndPermissions() failed: "
                << user_path.value();
    return;
  }

  // Create root_path at the end as a sentinel for migration.
  if (!platform_->SafeCreateDirAndSetOwnershipAndPermissions(
          root_path, kRootDirMode, kMountOwnerUid, kDaemonStoreGid)) {
    PLOG(ERROR) << "SafeCreateDirAndSetOwnershipAndPermissions() failed: "
                << root_path.value();
    return;
  }
  LOG(INFO) << "Created user directory: " << vault_path.value();
}

bool MountHelper::EnsureMountPointPath(const FilePath& dir) const {
  std::vector<std::string> path_parts;
  dir.GetComponents(&path_parts);
  FilePath check_path(path_parts[0]);
  if (path_parts[0] != "/") {
    return false;
  }
  for (size_t i = 1; i < path_parts.size(); i++) {
    check_path = check_path.Append(path_parts[i]);
    if (!EnsurePathComponent(check_path, kMountOwnerUid, kMountOwnerGid)) {
      return false;
    }
  }
  return true;
}

bool MountHelper::EnsureUserMountPoints(const std::string& username) const {
  FilePath multi_home_user = GetUserPath(username);
  FilePath multi_home_root = GetRootPath(username);
  FilePath new_user_path = GetNewUserPath(username);

  if (platform_->DirectoryExists(multi_home_user) &&
      (platform_->IsDirectoryMounted(multi_home_user) ||
       !platform_->DeleteFile(multi_home_user))) {
    LOG(ERROR) << "Failed to remove mount point: " << multi_home_user.value();
    return false;
  }

  if (platform_->DirectoryExists(multi_home_root) &&
      (platform_->IsDirectoryMounted(multi_home_root) ||
       !platform_->DeleteFile(multi_home_root))) {
    LOG(ERROR) << "Failed to remove mount point: " << multi_home_root.value();
    return false;
  }

  if (platform_->DirectoryExists(new_user_path) &&
      (platform_->IsDirectoryMounted(new_user_path) ||
       !platform_->DeleteFile(new_user_path))) {
    LOG(ERROR) << "Failed to remove mount point: " << new_user_path.value();
    return false;
  }

  if (!EnsureMountPointPath(multi_home_user.DirName()) ||
      !EnsureMountPointPath(multi_home_root.DirName()) ||
      !EnsureMountPointPath(new_user_path.DirName().DirName()) ||
      !EnsurePathComponent(new_user_path.DirName(), default_uid_,
                           default_gid_)) {
    LOG(ERROR) << "The paths to mountpoints are inconsistent";
    return false;
  }

  if (!platform_->SafeCreateDirAndSetOwnershipAndPermissions(
          multi_home_user, kUserMountPointMode, default_uid_,
          default_access_gid_)) {
    PLOG(ERROR) << "Can't create: " << multi_home_user;
    return false;
  }

  if (!platform_->SafeCreateDirAndSetOwnershipAndPermissions(
          new_user_path, kUserMountPointMode, default_uid_,
          default_access_gid_)) {
    PLOG(ERROR) << "Can't create: " << new_user_path;
    return false;
  }

  if (!platform_->SafeCreateDirAndSetOwnershipAndPermissions(
          multi_home_root, kRootMountPointMode, kMountOwnerUid,
          kMountOwnerGid)) {
    PLOG(ERROR) << "Can't create: " << multi_home_root;
    return false;
  }

  return true;
}

void MountHelper::RecursiveCopy(const FilePath& source,
                                const FilePath& destination) const {
  std::unique_ptr<cryptohome::FileEnumerator> file_enumerator(
      platform_->GetFileEnumerator(source, false, base::FileEnumerator::FILES));
  FilePath next_path;
  while (!(next_path = file_enumerator->Next()).empty()) {
    FilePath file_name = next_path.BaseName();
    FilePath destination_file = destination.Append(file_name);
    if (!platform_->Copy(next_path, destination_file) ||
        !platform_->SetOwnership(destination_file, default_uid_, default_gid_,
                                 false)) {
      LOG(ERROR) << "Couldn't change owner (" << default_uid_ << ":"
                 << default_gid_
                 << ") of destination path: " << destination_file.value();
    }
  }
  std::unique_ptr<cryptohome::FileEnumerator> dir_enumerator(
      platform_->GetFileEnumerator(source, false,
                                   base::FileEnumerator::DIRECTORIES));
  while (!(next_path = dir_enumerator->Next()).empty()) {
    FilePath dir_name = FilePath(next_path).BaseName();
    FilePath destination_dir = destination.Append(dir_name);
    VLOG(1) << "RecursiveCopy: " << destination_dir.value();
    if (!platform_->SafeCreateDirAndSetOwnershipAndPermissions(
            destination_dir, kSkeletonSubDirMode, default_uid_, default_gid_)) {
      LOG(ERROR) << "SafeCreateDirAndSetOwnership() failed: "
                 << destination_dir.value();
    }
    RecursiveCopy(FilePath(next_path), destination_dir);
  }
}

void MountHelper::CopySkeleton(const FilePath& destination) const {
  RecursiveCopy(SkelDir(), destination);
}

std::vector<DirectoryACL> MountHelper::GetEphemeralSubdirectories(
    uid_t uid, gid_t gid, gid_t access_gid) {
  std::vector<DirectoryACL> common_subdirs =
      GetCommonSubdirectories(uid, gid, access_gid);

  std::vector<DirectoryACL> cache_subdirs =
      GetCacheSubdirectories(uid, gid, access_gid);

  std::vector<DirectoryACL> gcache_subdirs =
      GetGCacheSubdirectories(uid, gid, access_gid, /*v1_dirs=*/false);

  auto result = common_subdirs;
  result.insert(result.end(), cache_subdirs.begin(), cache_subdirs.end());
  result.insert(result.end(), gcache_subdirs.begin(), gcache_subdirs.end());
  return result;
}

bool MountHelper::SetUpEphemeralCryptohome(const FilePath& source_path) {
  FilePath user_home = source_path.Append(kUserHomeSuffix);
  CopySkeleton(user_home);

  const auto subdirs = GetEphemeralSubdirectories(default_uid_, default_gid_,
                                                  default_access_gid_);
  for (const auto& subdir : subdirs) {
    FilePath path = FilePath(source_path).Append(subdir.path);
    if (platform_->DirectoryExists(path))
      continue;

    if (!platform_->SafeCreateDirAndSetOwnershipAndPermissions(
            path, subdir.mode, subdir.uid, subdir.gid)) {
      LOG(ERROR) << "Couldn't create user path directory: " << path.value();
      return false;
    }
  }

  return true;
}

bool MountHelper::MountLegacyHome(const FilePath& from) {
  VLOG(1) << "MountLegacyHome from " << from.value();
  // Multiple mounts can't live on the legacy mountpoint.
  if (platform_->IsDirectoryMounted(FilePath(kDefaultHomeDir))) {
    LOG(INFO) << "Skipping binding to /home/chronos/user";
    return true;
  }

  if (!BindAndPush(from, FilePath(kDefaultHomeDir), true /*is_shared*/))
    return false;

  return true;
}

bool MountHelper::BindMyFilesDownloads(const base::FilePath& user_home) {
  if (!platform_->DirectoryExists(user_home)) {
    LOG(ERROR) << "Failed to bind MyFiles/Downloads, missing directory: "
               << user_home.value();
    return false;
  }

  const FilePath downloads = user_home.Append(kDownloadsDir);
  if (!platform_->DirectoryExists(downloads)) {
    LOG(ERROR) << "Failed to bind MyFiles/Downloads, missing directory: "
               << downloads.value();
    return false;
  }

  const FilePath downloads_in_myfiles =
      user_home.Append(kMyFilesDir).Append(kDownloadsDir);
  if (!platform_->DirectoryExists(downloads_in_myfiles)) {
    LOG(ERROR) << "Failed to bind MyFiles/Downloads, missing directory: "
               << downloads_in_myfiles.value();
    return false;
  }
  /*
   * User could have saved files in MyFiles/Downloads in case cryptohome
   * crashed and bind mounts were removed by error. See crbug.com/1080730.
   * Move the files back to Download unless a file already exits.
   */
  MigrateDirectory(downloads, downloads_in_myfiles);

  if (!BindAndPush(downloads, downloads_in_myfiles, true /*is_shared*/))
    return false;

  return true;
}

bool MountHelper::MountAndPush(const base::FilePath& src,
                               const base::FilePath& dest,
                               const std::string& type,
                               const std::string& options) {
  if (!platform_->Mount(src, dest, type, kDefaultMountFlags, options)) {
    PLOG(ERROR) << "Mount failed: " << src.value() << " -> " << dest.value();
    return false;
  }

  stack_.Push(src, dest);
  return true;
}

bool MountHelper::BindAndPush(const FilePath& src,
                              const FilePath& dest,
                              bool is_shared) {
  if (!platform_->Bind(src, dest, is_shared, /*nosymfollow=*/true)) {
    PLOG(ERROR) << "Bind mount failed: " << src.value() << " -> "
                << dest.value() << " is_shared: " << std::boolalpha
                << is_shared;
    return false;
  }

  stack_.Push(src, dest);
  return true;
}

bool MountHelper::MountDaemonStoreDirectories(
    const FilePath& root_home, const std::string& obfuscated_username) {
  // Iterate over all directories in /etc/daemon-store. This list is on rootfs,
  // so it's tamper-proof and nobody can sneak in additional directories that we
  // blindly mount. The actual mounts happen on /run/daemon-store, though.
  std::unique_ptr<cryptohome::FileEnumerator> file_enumerator(
      platform_->GetFileEnumerator(FilePath(kEtcDaemonStoreBaseDir),
                                   false /* recursive */,
                                   base::FileEnumerator::DIRECTORIES));

  // /etc/daemon-store/<daemon-name>
  FilePath etc_daemon_store_path;
  while (!(etc_daemon_store_path = file_enumerator->Next()).empty()) {
    const FilePath& daemon_name = etc_daemon_store_path.BaseName();

    // /run/daemon-store/<daemon-name>
    FilePath run_daemon_store_path =
        FilePath(kRunDaemonStoreBaseDir).Append(daemon_name);
    if (!platform_->DirectoryExists(run_daemon_store_path)) {
      // The chromeos_startup script should make sure this exist.
      PLOG(ERROR) << "Daemon store directory does not exist: "
                  << run_daemon_store_path.value();
      return false;
    }

    // /home/.shadow/<user_hash>/mount/root/<daemon-name>
    const FilePath mount_source = root_home.Append(daemon_name);

    // /run/daemon-store/<daemon-name>/<user_hash>
    const FilePath mount_target =
        run_daemon_store_path.Append(obfuscated_username);

    // Copy ownership from |etc_daemon_store_path| to |mount_source|. After the
    // bind operation, this guarantees that ownership for |mount_target| is the
    // same as for |etc_daemon_store_path| (usually
    // <daemon_user>:<daemon_group>), which is what the daemon intended.
    // Otherwise, it would end up being root-owned.
    base::stat_wrapper_t etc_daemon_path_stat =
        file_enumerator->GetInfo().stat();

    // TODO(dlunev): add some reporting when we see ACL mismatch.
    if (!platform_->DirectoryExists(mount_source) &&
        !platform_->SafeCreateDirAndSetOwnershipAndPermissions(
            mount_source, etc_daemon_path_stat.st_mode,
            etc_daemon_path_stat.st_uid, etc_daemon_path_stat.st_gid)) {
      LOG(ERROR) << "Failed to create directory " << mount_source.value();
      return false;
    }

    // The target directory's parent exists in the root mount namespace so the
    // directory itself can be created in the root mount namespace and it will
    // be visible in all namespaces.
    if (!platform_->CreateDirectory(mount_target)) {
      PLOG(ERROR) << "Failed to create directory " << mount_target.value();
      return false;
    }

    // Assuming that |run_daemon_store_path| is a shared mount and the daemon
    // runs in a file system namespace with |run_daemon_store_path| mounted as
    // secondary, this mount event propagates into the daemon.
    if (!BindAndPush(mount_source, mount_target))
      return false;
  }

  return true;
}

void MountHelper::MigrateDirectory(const base::FilePath& dst,
                                   const base::FilePath& src) const {
  VLOG(1) << "Migrating directory " << src << " -> " << dst;
  std::unique_ptr<cryptohome::FileEnumerator> enumerator(
      platform_->GetFileEnumerator(
          src, false /* recursive */,
          base::FileEnumerator::DIRECTORIES | base::FileEnumerator::FILES));
  for (base::FilePath src_obj = enumerator->Next(); !src_obj.empty();
       src_obj = enumerator->Next()) {
    base::FilePath dst_obj = dst.Append(src_obj.BaseName());

    // If the destination file exists, or rename failed for whatever reason,
    // then log a warning and delete the source file.
    if (platform_->FileExists(dst_obj) ||
        !platform_->Rename(src_obj, dst_obj)) {
      LOG(WARNING) << "Failed to migrate " << src_obj << " : deleting";
      platform_->DeletePathRecursively(src_obj);
    }
  }
}

bool MountHelper::MountHomesAndDaemonStores(
    const std::string& username,
    const std::string& obfuscated_username,
    const FilePath& user_home,
    const FilePath& root_home) {
  // Bind mount user directory as a shared bind mount.
  // This allows us to set up user mounts as shared mounts without needing to
  // replicate that across multiple mount points.
  if (!BindAndPush(user_home, user_home, true /*is_shared*/))
    return false;

  // Mount /home/chronos/user.
  if (legacy_mount_ && !MountLegacyHome(user_home))
    return false;

  // Mount /home/chronos/u-<user_hash>
  const FilePath new_user_path = GetNewUserPath(username);
  if (!BindAndPush(user_home, new_user_path))
    return false;

  // Mount /home/user/<user_hash>.
  const FilePath user_multi_home = GetUserPath(username);
  if (!BindAndPush(user_home, user_multi_home))
    return false;

  // Mount /home/root/<user_hash>.
  const FilePath root_multi_home = GetRootPath(username);
  if (!BindAndPush(root_home, root_multi_home))
    return false;

  if (bind_mount_downloads_) {
    // Mount Downloads to MyFiles/Downloads in:
    //  - /home/chronos/u-<user_hash>
    if (!BindMyFilesDownloads(user_multi_home)) {
      return false;
    }
  }

  // Mount directories used by daemons to store per-user data.
  if (!MountDaemonStoreDirectories(root_home, obfuscated_username))
    return false;

  return true;
}

bool MountHelper::CreateTrackedSubdirectories(
    const std::string& obfuscated_username, const MountType& mount_type) const {
  // Add the subdirectories if they do not exist.
  const FilePath dest_dir(mount_type == MountType::ECRYPTFS
                              ? GetEcryptfsUserVaultPath(obfuscated_username)
                              : GetUserMountDirectory(obfuscated_username));
  if (!platform_->DirectoryExists(dest_dir)) {
    LOG(ERROR) << "Can't create tracked subdirectories for a missing user.";
    return false;
  }

  const FilePath mount_dir(GetUserMountDirectory(obfuscated_username));

  // The call is allowed to partially fail if directory creation fails, but we
  // want to have as many of the specified tracked directories created as
  // possible.
  bool result = true;
  for (const auto& tracked_dir : GetTrackedSubdirectories(
           default_uid_, default_gid_, default_access_gid_)) {
    const FilePath tracked_dir_path = dest_dir.Append(tracked_dir.path);
    if (mount_type == MountType::ECRYPTFS) {
      const FilePath userside_dir = mount_dir.Append(tracked_dir.path);
      // If non-pass-through dir with the same name existed - delete it
      // to prevent duplication.
      if (platform_->DirectoryExists(userside_dir) &&
          !platform_->DirectoryExists(tracked_dir_path)) {
        platform_->DeletePathRecursively(userside_dir);
      }
    }

    // Create pass-through directory.
    if (!platform_->DirectoryExists(tracked_dir_path)) {
      // Delete the existing file or symbolic link if any.
      platform_->DeleteFile(tracked_dir_path);
      VLOG(1) << "Creating pass-through directory " << tracked_dir_path.value();
      if (!platform_->SafeCreateDirAndSetOwnershipAndPermissions(
              tracked_dir_path, tracked_dir.mode, tracked_dir.uid,
              tracked_dir.gid)) {
        PLOG(ERROR) << "Couldn't create directory: "
                    << tracked_dir_path.value();
        platform_->DeletePathRecursively(tracked_dir_path);
        result = false;
        continue;
      }
    } else {
      // We make the mode for chronos-access accessible directories more
      // permissive, thus we need to change mode. it is unfortunate we need
      // to do it explicitly, unlike with mountpoints which we could just
      // recreate, but we must preservce user data while doing so.
      if (!platform_->SafeDirChmod(tracked_dir_path, tracked_dir.mode)) {
        PLOG(ERROR) << "Couldn't change directory's mode: "
                    << tracked_dir_path.value();
      }
    }
    if (mount_type == MountType::DIR_CRYPTO) {
      // Set xattr to make this directory trackable.
      std::string name = tracked_dir_path.BaseName().value();
      if (!platform_->SetExtendedFileAttribute(tracked_dir_path,
                                               kTrackedDirectoryNameAttribute,
                                               name.data(), name.length())) {
        PLOG(ERROR) << "Unable to set xattr on " << tracked_dir_path.value();
        result = false;
        continue;
      }
    }
  }

  if (!bind_mount_downloads_) {
    // If we are not doing the downloads bind mount, move the content of the
    // Downloads to MyFiles/Downloads. Doing it file by file in case there is
    // a content in the MyFiles/Downloads already.
    auto downloads = dest_dir.Append(kUserHomeSuffix).Append(kDownloadsDir);
    auto downloads_in_myfiles = dest_dir.Append(kUserHomeSuffix)
                                    .Append(kMyFilesDir)
                                    .Append(kDownloadsDir);
    MigrateDirectory(downloads_in_myfiles, downloads);
  }

  return result;
}

std::vector<DirectoryACL> MountHelper::GetDmcryptSubdirectories(
    uid_t uid, gid_t gid, gid_t access_gid) {
  auto common_subdirs = GetCommonSubdirectories(uid, gid, access_gid);
  auto cache_subdirs = GetCacheSubdirectories(uid, gid, access_gid);
  auto gcache_subdirs =
      GetGCacheSubdirectories(uid, gid, access_gid, /*v1_dirs=*/true);

  // Construct data volume subdirectories.
  std::vector<DirectoryACL> data_volume_subdirs;
  data_volume_subdirs.insert(data_volume_subdirs.end(), common_subdirs.begin(),
                             common_subdirs.end());
  data_volume_subdirs.insert(data_volume_subdirs.end(), cache_subdirs.begin(),
                             cache_subdirs.end());

  for (auto& subdir : data_volume_subdirs) {
    subdir.path = FilePath(kMountDir).Append(subdir.path);
  }

  // Construct cache volume subdirectories.
  auto cache_volume_subdirs = cache_subdirs;
  cache_volume_subdirs.insert(cache_volume_subdirs.end(),
                              gcache_subdirs.begin(), gcache_subdirs.end());
  for (auto& subdir : cache_volume_subdirs) {
    subdir.path = FilePath(kDmcryptCacheDir).Append(subdir.path);
  }

  auto result = cache_volume_subdirs;
  result.insert(result.end(), data_volume_subdirs.begin(),
                data_volume_subdirs.end());
  return result;
}

bool MountHelper::CreateDmcryptSubdirectories(
    const std::string& obfuscated_username) {
  FilePath user_shadow_dir = ShadowRoot().Append(obfuscated_username);
  const std::vector<DirectoryACL> dmcrypt_subdirs =
      GetDmcryptSubdirectories(default_uid_, default_gid_, default_access_gid_);

  // Set up directories.
  for (const auto& subdir : dmcrypt_subdirs) {
    FilePath dir = user_shadow_dir.Append(subdir.path);
    // Ensure that the directory exists.
    if (!platform_->DirectoryExists(dir)) {
      // Delete the existing file or symbolic link if any.
      platform_->DeletePathRecursively(dir);
      VLOG(1) << "Creating directory " << dir.value();
      if (!platform_->SafeCreateDirAndSetOwnershipAndPermissions(
              dir, subdir.mode, subdir.uid, subdir.gid)) {
        PLOG(ERROR) << "SafeCreateDirAndSetOwnershipAndPermissions() failed: "
                    << dir.value();
        platform_->DeletePathRecursively(dir);
        return false;
      }
    }
  }

  return true;
}

bool MountHelper::MountCacheSubdirectories(
    const std::string& obfuscated_username) {
  FilePath cache_directory = GetDmcryptUserCacheDirectory(obfuscated_username);
  FilePath data_directory = GetUserMountDirectory(obfuscated_username);

  const FilePath tracked_subdir_paths[] = {
      FilePath(kUserHomeSuffix).Append(kCacheDir),
      FilePath(kUserHomeSuffix).Append(kGCacheDir)};

  for (const auto& tracked_dir : tracked_subdir_paths) {
    FilePath src_dir = cache_directory.Append(tracked_dir);
    FilePath dst_dir = data_directory.Append(tracked_dir);

    if (!BindAndPush(src_dir, dst_dir, true)) {
      LOG(ERROR) << "Failed to bind mount " << src_dir;
      return false;
    }
  }

  return true;
}

// The eCryptfs mount is mounted from vault/ --> mount/ except in case of
// migration where the mount point is a temporary directory.
bool MountHelper::SetUpEcryptfsMount(const std::string& obfuscated_username,
                                     const std::string& fek_signature,
                                     const std::string& fnek_signature,
                                     bool should_migrate) {
  const FilePath vault_path = GetEcryptfsUserVaultPath(obfuscated_username);
  const FilePath mount_point =
      should_migrate ? GetUserTemporaryMountDirectory(obfuscated_username)
                     : GetUserMountDirectory(obfuscated_username);

  // Specify the ecryptfs options for mounting the user's cryptohome.
  std::string ecryptfs_options = StringPrintf(
      "ecryptfs_cipher=aes"
      ",ecryptfs_key_bytes=%d"
      ",ecryptfs_fnek_sig=%s"
      ",ecryptfs_sig=%s"
      ",ecryptfs_unlink_sigs",
      kDefaultEcryptfsKeySize, fnek_signature.c_str(), fek_signature.c_str());

  // Create <vault_path>/user and <vault_path>/root.
  CreateHomeSubdirectories(vault_path);

  // Move the tracked subdirectories from <mount_point_>/user to <vault_path>
  // as passthrough directories.
  CreateTrackedSubdirectories(obfuscated_username, MountType::ECRYPTFS);

  // b/115997660: Mount eCryptfs after creating the tracked subdirectories.
  if (!MountAndPush(vault_path, mount_point, "ecryptfs", ecryptfs_options))
    return false;

  return true;
}

void MountHelper::SetUpDircryptoMount(const std::string& obfuscated_username) {
  const FilePath mount_point = GetUserMountDirectory(obfuscated_username);

  CreateHomeSubdirectories(mount_point);
  CreateTrackedSubdirectories(obfuscated_username, MountType::DIR_CRYPTO);
}

bool MountHelper::SetUpDmcryptMount(const std::string& obfuscated_username) {
  const FilePath dmcrypt_data_volume =
      GetDmcryptDataVolume(obfuscated_username);
  const FilePath dmcrypt_cache_volume =
      GetDmcryptCacheVolume(obfuscated_username);

  const FilePath data_mount_point = GetUserMountDirectory(obfuscated_username);
  const FilePath cache_mount_point =
      GetDmcryptUserCacheDirectory(obfuscated_username);

  // Mount the data volume at <vault>/mount and the cache volume at
  // <vault>/cache. The directories are set up by the creation code.
  if (!MountAndPush(dmcrypt_data_volume, data_mount_point,
                    kDmcryptContainerMountType,
                    kDmcryptContainerMountOptions)) {
    LOG(ERROR) << "Failed to mount dmcrypt data volume";
    return false;
  }

  if (!MountAndPush(dmcrypt_cache_volume, cache_mount_point,
                    kDmcryptContainerMountType,
                    kDmcryptContainerMountOptions)) {
    LOG(ERROR) << "Failed to mount dmcrypt cache volume";
    return false;
  }

  CreateHomeSubdirectories(data_mount_point);
  CreateDmcryptSubdirectories(obfuscated_username);

  return true;
}

bool MountHelper::PerformMount(const Options& mount_opts,
                               const std::string& username,
                               const std::string& fek_signature,
                               const std::string& fnek_signature,
                               bool is_pristine,
                               MountError* error) {
  const std::string obfuscated_username = SanitizeUserName(username);

  bool should_mount_ecryptfs = mount_opts.type == MountType::ECRYPTFS ||
                               mount_opts.to_migrate_from_ecryptfs;

  if (should_mount_ecryptfs &&
      !SetUpEcryptfsMount(obfuscated_username, fek_signature, fnek_signature,
                          mount_opts.to_migrate_from_ecryptfs)) {
    LOG(ERROR) << "eCryptfs mount failed";
    *error = MOUNT_ERROR_MOUNT_ECRYPTFS_FAILED;
    return false;
  }

  if (mount_opts.type == MountType::DIR_CRYPTO)
    SetUpDircryptoMount(obfuscated_username);

  if (mount_opts.type == MountType::DMCRYPT &&
      !SetUpDmcryptMount(obfuscated_username)) {
    LOG(ERROR) << "Dm-crypt mount failed";
    *error = MOUNT_ERROR_MOUNT_DMCRYPT_FAILED;
    return false;
  }

  const FilePath user_home = GetMountedUserHomePath(obfuscated_username);
  const FilePath root_home = GetMountedRootHomePath(obfuscated_username);

  if (is_pristine)
    CopySkeleton(user_home);

  // When migrating, it's better to avoid exposing the new ext4 crypto dir.
  if (!mount_opts.to_migrate_from_ecryptfs &&
      !MountHomesAndDaemonStores(username, obfuscated_username, user_home,
                                 root_home)) {
    *error = MOUNT_ERROR_MOUNT_HOMES_AND_DAEMON_STORES_FAILED;
    return false;
  }

  // Mount tracked subdirectories from the cache volume.
  if (mount_opts.type == MountType::DMCRYPT &&
      !MountCacheSubdirectories(obfuscated_username)) {
    LOG(ERROR)
        << "Failed to mount tracked subdirectories from the cache volume";
    *error = MOUNT_ERROR_MOUNT_DMCRYPT_FAILED;
    return false;
  }

  return true;
}

bool MountHelper::PrepareEphemeralDevice(
    const std::string& obfuscated_username) {
  // Underlying sparse file will be created in a temporary directory in RAM.
  const FilePath ephemeral_root(kEphemeralCryptohomeDir);

  // Determine ephemeral cryptohome size.
  struct statvfs vfs;
  if (!platform_->StatVFS(ephemeral_root, &vfs)) {
    PLOG(ERROR) << "Can't determine ephemeral cryptohome size";
    return false;
  }
  const int64_t sparse_size = static_cast<int64_t>(vfs.f_blocks * vfs.f_frsize);

  // Create underlying sparse file.
  const FilePath sparse_file = GetEphemeralSparseFile(obfuscated_username);
  if (!platform_->CreateDirectory(sparse_file.DirName())) {
    LOG(ERROR) << "Can't create directory for ephemeral sparse files";
    return false;
  }

  // Remember the file to clean up if an error happens during file creation.
  ephemeral_file_path_ = sparse_file;
  if (!platform_->CreateSparseFile(sparse_file, sparse_size)) {
    LOG(ERROR) << "Can't create ephemeral sparse file";
    return false;
  }

  // Format the sparse file as ext4.
  if (!platform_->FormatExt4(sparse_file, kDefaultExt4FormatOpts, 0)) {
    LOG(ERROR) << "Can't format ephemeral sparse file as ext4";
    return false;
  }

  // Create a loop device based on the sparse file.
  const FilePath loop_device = platform_->AttachLoop(sparse_file);
  if (loop_device.empty()) {
    LOG(ERROR) << "Can't create loop device";
    return false;
  }

  // Remember the loop device to clean up if an error happens.
  ephemeral_loop_device_ = loop_device;
  return true;
}

bool MountHelper::PerformEphemeralMount(const std::string& username) {
  const std::string obfuscated_username =
      SanitizeUserNameWithSalt(username, system_salt_);

  if (!PrepareEphemeralDevice(obfuscated_username)) {
    LOG(ERROR) << "Can't prepare ephemeral device";
    return false;
  }

  const FilePath mount_point =
      GetUserEphemeralMountDirectory(obfuscated_username);
  if (!platform_->CreateDirectory(mount_point)) {
    PLOG(ERROR) << "Directory creation failed for " << mount_point.value();
    return false;
  }
  if (!MountAndPush(ephemeral_loop_device_, mount_point, kEphemeralMountType,
                    kEphemeralMountOptions)) {
    LOG(ERROR) << "Can't mount ephemeral mount point";
    return false;
  }

  // Set SELinux context first, so that the created user & root directory have
  // the correct context.
  if (!::SetUpSELinuxContextForEphemeralCryptohome(platform_, mount_point)) {
    // Logging already done in SetUpSELinuxContextForEphemeralCryptohome.
    return false;
  }

  // Create user & root directories.
  CreateHomeSubdirectories(mount_point);
  if (!EnsureUserMountPoints(username)) {
    return false;
  }

  const FilePath user_home =
      GetMountedEphemeralUserHomePath(obfuscated_username);
  const FilePath root_home =
      GetMountedEphemeralRootHomePath(obfuscated_username);

  if (!SetUpEphemeralCryptohome(mount_point)) {
    return false;
  }

  if (!MountHomesAndDaemonStores(username, obfuscated_username, user_home,
                                 root_home)) {
    return false;
  }

  return true;
}

bool MountHelper::TearDownEphemeralMount() {
  UnmountAll();
  return CleanUpEphemeral();
}

void MountHelper::TearDownNonEphemeralMount() {
  UnmountAll();
}

void MountHelper::UnmountAll() {
  FilePath src, dest;
  const FilePath ephemeral_mount_path =
      FilePath(kEphemeralCryptohomeDir).Append(kEphemeralMountDir);
  while (stack_.Pop(&src, &dest)) {
    ForceUnmount(src, dest);
    // Clean up destination directory for ephemeral loop device mounts.
    if (ephemeral_mount_path == dest.DirName())
      platform_->DeletePathRecursively(dest);
  }
}

bool MountHelper::CleanUpEphemeral() {
  bool success = true;
  if (!ephemeral_loop_device_.empty()) {
    if (!platform_->DetachLoop(ephemeral_loop_device_)) {
      PLOG(ERROR) << "Can't detach loop device '"
                  << ephemeral_loop_device_.value() << "'";
      success = false;
    }
    ephemeral_loop_device_.clear();
  }
  if (!ephemeral_file_path_.empty()) {
    if (!platform_->DeleteFile(ephemeral_file_path_)) {
      PLOG(ERROR) << "Failed to clean up ephemeral sparse file '"
                  << ephemeral_file_path_.value() << "'";
      success = false;
    }
    ephemeral_file_path_.clear();
  }

  return success;
}

void MountHelper::ForceUnmount(const FilePath& src, const FilePath& dest) {
  // Try an immediate unmount.
  bool was_busy;
  if (!platform_->Unmount(dest, false, &was_busy)) {
    LOG(ERROR) << "Couldn't unmount '" << dest.value()
               << "' immediately, was_busy=" << std::boolalpha << was_busy;
    // Failed to unmount immediately, do a lazy unmount.  If |was_busy| we also
    // want to sync before the unmount to help prevent data loss.
    if (was_busy)
      platform_->SyncDirectory(dest);
    platform_->LazyUnmount(dest);
    platform_->SyncDirectory(src);
  }
}

bool MountHelper::CanPerformEphemeralMount() const {
  return ephemeral_file_path_.empty() && ephemeral_loop_device_.empty();
}

bool MountHelper::MountPerformed() const {
  return stack_.size() > 0;
}

bool MountHelper::IsPathMounted(const base::FilePath& path) const {
  return stack_.ContainsDest(path);
}

std::vector<base::FilePath> MountHelper::MountedPaths() const {
  return stack_.MountDestinations();
}

}  // namespace cryptohome
