blob: 5aaef05f9087deca6287e5dddabe0b50f8382d15 [file] [log] [blame]
// Copyright 2018 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <inttypes.h>
#include <sys/stat.h>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <base/files/file_path.h>
#include <brillo/brillo_export.h>
#include <brillo/secure_blob.h>
#include <libstorage/platform/platform.h>
#include <libstorage/storage_container/filesystem_key.h>
#include <libstorage/storage_container/storage_container.h>
#include <libstorage/storage_container/storage_container_factory.h>
namespace mount_encrypted {
// Teardown stage: for granular teardowns
enum class TeardownStage {
// BindMount represents a bind mount to be setup from
// source directories within the encrypted mount.
// EncryptedFs is responsible for setting up the bind mount
// once it sets up the encrypted mount.
struct BindMount {
base::FilePath src; // Location of bind source.
base::FilePath dst; // Destination of bind.
uid_t owner;
gid_t group;
mode_t mode;
bool submount; // Submount is bound already.
// EncryptedFs sets up, tears down and cleans up encrypted
// stateful mounts. Given a root directory, the class
// sets up an encrypted mount at <root_dir>/ENCRYPTED_MOUNT.
class BRILLO_EXPORT EncryptedFs {
// Set up the encrypted filesystem..
EncryptedFs(const base::FilePath& rootdir,
const base::FilePath& statefulmnt,
uint64_t fs_size,
const std::string& dmcrypt_name,
std::unique_ptr<libstorage::StorageContainer> container,
libstorage::Platform* platform);
~EncryptedFs() = default;
static std::unique_ptr<EncryptedFs> Generate(
const base::FilePath& rootdir,
const base::FilePath& statefulmnt,
libstorage::Platform* platform,
libstorage::StorageContainerFactory* storage_container_factory);
// Setup mounts the encrypted mount by:
// 1. Create a sparse file at <rootdir>/STATEFUL_MNT/encrypted.block
// 2. Mounting a loop device on top of the sparse file.
// 3. Mounting a dmcrypt device with the loop device as the backing
// device and the provided encryption key.
// 4. Formatting the dmcrypt device as ext4 and mounting it at the
// mount_point.
// If a sparse file already exists, Setup assumes that the stateful
// mount has already been setup and attempts to mount the
// | ext4 | dmcrypt | loopback | tower on top of the sparse file.
// Parameters
// encryption_key - dmcrypt encryption key.
// rebuild - cleanup and recreate the encrypted mount.
bool Setup(const libstorage::FileSystemKey& encryption_key, bool rebuild);
// Purge - obliterate the sparse file. This should be called only
// when the encrypted fs is not mounted.
bool Purge();
// Teardown - stepwise unmounts the | ext4 | dmcrypt | loopback | tower
// on top of the sparse file.
bool Teardown();
// CheckStates - Checks validity for the stateful mount before mounting.
bool CheckStates();
// ReportInfo - Reports the paths and bind mounts.
bool ReportInfo() const;
friend class EncryptedFsTest;
FRIEND_TEST(EncryptedFsTest, RebuildStateful);
FRIEND_TEST(EncryptedFsTest, OldStateful);
FRIEND_TEST(EncryptedFsTest, LoopdevTeardown);
FRIEND_TEST(EncryptedFsTest, DevmapperTeardown);
// TeardownByStage allows higher granularity over teardown
// processes.
bool TeardownByStage(TeardownStage stage, bool ignore_errors);
// Root directory to use for the encrypted stateful filesystem.
const base::FilePath rootdir_;
// Size of the filesystem.
const uint64_t fs_size_;
// Dm-crypt device name: used for key finalization.
const std::string dmcrypt_name_;
// File paths used by encrypted stateful.
const base::FilePath stateful_mount_;
const base::FilePath dmcrypt_dev_;
const base::FilePath encrypted_mount_;
// Use a raw Platform pointer to avoid convoluted EXPECT_CALL semantics
// for mock Platform objects.
libstorage::Platform* platform_;
// Encrypted container that will be mounted as the encrypted filesystem.
std::unique_ptr<libstorage::StorageContainer> container_;
std::vector<BindMount> bind_mounts_;
} // namespace mount_encrypted