blob: 0fc22ccc1777333ded4008557ae0cc129b24a455 [file]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "init/startup/test_mode_mount_helper.h"
#include <sys/stat.h>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include <base/files/file_enumerator.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/values.h>
#include <brillo/files/file_util.h>
#include <brillo/process/process.h>
#include <libstorage/platform/platform.h>
#include "init/startup/flags.h"
#include "init/startup/mount_helper.h"
#include "init/startup/mount_var_home_interface.h"
#include "init/startup/security_manager.h"
#include "init/startup/startup_dep_impl.h"
namespace {
constexpr char kNoEarlyKeyFile[] = ".no_early_system_key";
constexpr char kSysKeyBackupFile[] = "unencrypted/preserve/system.key";
} // namespace
namespace startup {
// Constructor for TestModeMountHelper when the device is
// not in dev mode.
TestModeMountHelper::TestModeMountHelper(
libstorage::Platform* platform,
StartupDep* startup_dep,
const Flags* flags,
const base::FilePath& root,
const base::FilePath& backup,
std::unique_ptr<MountVarAndHomeChronosInterface> impl,
libstorage::StorageContainerFactory* storage_container_factory)
: MountHelper(platform,
startup_dep,
flags,
root,
std::move(impl),
storage_container_factory),
backup_(backup) {}
base::FilePath TestModeMountHelper::GetKeyBackupFile() const {
// If this a TPM 2.0 device that supports encrypted stateful, creates and
// persists a system key into NVRAM and backs the key up if it doesn't exist.
// If the call create_system_key is successful, mount_var_and_home_chronos
// will skip the normal system key generation procedure; otherwise, it will
// generate and persist a key via its normal workflow.
base::FilePath no_early = backup_.Append(kNoEarlyKeyFile);
if (flags_->sys_key_util && !platform_->FileExists(no_early)) {
LOG(INFO) << "Creating System Key";
return backup_.Append(kSysKeyBackupFile);
}
return base::FilePath();
}
bool TestModeMountHelper::DoMountVarAndHomeChronos(
std::optional<encryption::EncryptionKey> key) {
bool ret = MountVarAndHomeChronos(key);
if (!ret) {
// Try to re-construct encrypted folders, otherwise such a failure will lead
// to wiping whole stateful partition (including all helpful programs in
// /usr/local/bin and sshd).
std::string msg("Failed mounting var and home/chronos; re-created.");
startup_dep_->ClobberLog(msg);
std::vector<std::string> crash_args{"--mount_failure",
"--mount_device='encstateful'"};
startup_dep_->AddClobberCrashReport(crash_args);
base::FilePath backup = backup_.Append("corrupted_encryption");
brillo::DeletePathRecursively(backup);
platform_->CreateDirectory(backup);
if (!platform_->SetPermissions(backup, 0755)) {
PLOG(WARNING) << "chmod failed for " << backup.value();
}
std::unique_ptr<libstorage::FileEnumerator> enumerator(
platform_->GetFileEnumerator(backup_, false /* recursive */,
base::FileEnumerator::FILES,
"encrypted.*"));
for (base::FilePath path = enumerator->Next(); !path.empty();
path = enumerator->Next()) {
base::FilePath to_path = backup.Append(path.BaseName());
platform_->Rename(path, to_path, true /* cros_fs */);
}
ret = MountVarAndHomeChronos(key);
}
return ret;
}
} // namespace startup