Loading fs_mgr/libfs_avb/fs_avb.cpp +32 −12 Original line number Original line Diff line number Diff line Loading @@ -266,8 +266,10 @@ AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta( return avb_handle; return avb_handle; } } AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta(const FstabEntry& fstab_entry) { AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta(const FstabEntry& fstab_entry, if (fstab_entry.avb_keys.empty()) { const std::vector<std::string>& preload_avb_key_blobs) { // At least one of the following should be provided for public key matching. if (preload_avb_key_blobs.empty() && fstab_entry.avb_keys.empty()) { LERROR << "avb_keys=/path/to/key(s) is missing for " << fstab_entry.mount_point; LERROR << "avb_keys=/path/to/key(s) is missing for " << fstab_entry.mount_point; return nullptr; return nullptr; } } Loading Loading @@ -309,6 +311,20 @@ AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta(const FstabEntry& fstab_entry) { return nullptr; return nullptr; } } bool public_key_match = false; // Performs key matching for preload_avb_key_blobs first, if it is present. if (!public_key_data.empty() && !preload_avb_key_blobs.empty()) { if (std::find(preload_avb_key_blobs.begin(), preload_avb_key_blobs.end(), public_key_data) != preload_avb_key_blobs.end()) { public_key_match = true; } } // Performs key matching for fstab_entry.avb_keys if necessary. // Note that it is intentional to match both preload_avb_key_blobs and fstab_entry.avb_keys. // Some keys might only be availble before init chroots into /system, e.g., /avb/key1 // in the first-stage ramdisk, while other keys might only be available after the chroot, // e.g., /system/etc/avb/key2. if (!public_key_data.empty() && !public_key_match) { // fstab_entry.avb_keys might be either a directory containing multiple keys, // fstab_entry.avb_keys might be either a directory containing multiple keys, // or a string indicating multiple keys separated by ':'. // or a string indicating multiple keys separated by ':'. std::vector<std::string> allowed_avb_keys; std::vector<std::string> allowed_avb_keys; Loading @@ -319,8 +335,12 @@ AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta(const FstabEntry& fstab_entry) { } else { } else { allowed_avb_keys = Split(fstab_entry.avb_keys, ":"); allowed_avb_keys = Split(fstab_entry.avb_keys, ":"); } } if (ValidatePublicKeyBlob(public_key_data, allowed_avb_keys)) { public_key_match = true; } } if (!ValidatePublicKeyBlob(public_key_data, allowed_avb_keys)) { if (!public_key_match) { avb_handle->status_ = AvbHandleStatus::kVerificationError; avb_handle->status_ = AvbHandleStatus::kVerificationError; LWARNING << "Found unknown public key used to sign " << fstab_entry.mount_point; LWARNING << "Found unknown public key used to sign " << fstab_entry.mount_point; if (!allow_verification_error) { if (!allow_verification_error) { Loading fs_mgr/libfs_avb/include/fs_avb/fs_avb.h +9 −2 Original line number Original line Diff line number Diff line Loading @@ -85,8 +85,15 @@ class AvbHandle { // TODO(bowgotsai): remove Open() and switch to LoadAndVerifyVbmeta(). // TODO(bowgotsai): remove Open() and switch to LoadAndVerifyVbmeta(). static AvbUniquePtr Open(); // loads inline vbmeta, via libavb. static AvbUniquePtr Open(); // loads inline vbmeta, via libavb. static AvbUniquePtr LoadAndVerifyVbmeta(); // loads inline vbmeta. static AvbUniquePtr LoadAndVerifyVbmeta(); // loads inline vbmeta. static AvbUniquePtr LoadAndVerifyVbmeta( const FstabEntry& fstab_entry); // loads offline vbmeta. // The caller can specify optional preload_avb_key_blobs for public key matching. // This is mostly for init to preload AVB keys before chroot into /system. // Both preload_avb_key_blobs and fstab_entry.avb_keys (file paths) will be used // for public key matching. static AvbUniquePtr LoadAndVerifyVbmeta( // loads offline vbmeta. const FstabEntry& fstab_entry, const std::vector<std::string>& preload_avb_key_blobs = {}); static AvbUniquePtr LoadAndVerifyVbmeta( // loads offline vbmeta. static AvbUniquePtr LoadAndVerifyVbmeta( // loads offline vbmeta. const std::string& partition_name, const std::string& ab_suffix, const std::string& partition_name, const std::string& ab_suffix, const std::string& ab_other_suffix, const std::string& expected_public_key, const std::string& ab_other_suffix, const std::string& expected_public_key, Loading init/first_stage_mount.cpp +56 −1 Original line number Original line Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <unistd.h> #include <unistd.h> #include <chrono> #include <chrono> #include <map> #include <memory> #include <memory> #include <set> #include <set> #include <string> #include <string> Loading @@ -29,6 +30,7 @@ #include <android-base/chrono_utils.h> #include <android-base/chrono_utils.h> #include <android-base/file.h> #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/logging.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <android-base/strings.h> #include <fs_avb/fs_avb.h> #include <fs_avb/fs_avb.h> #include <fs_mgr.h> #include <fs_mgr.h> Loading @@ -45,7 +47,9 @@ #include "uevent_listener.h" #include "uevent_listener.h" #include "util.h" #include "util.h" using android::base::ReadFileToString; using android::base::Split; using android::base::Split; using android::base::StringPrintf; using android::base::Timer; using android::base::Timer; using android::fiemap::IImageManager; using android::fiemap::IImageManager; using android::fs_mgr::AvbHandle; using android::fs_mgr::AvbHandle; Loading Loading @@ -95,6 +99,7 @@ class FirstStageMount { void GetDmLinearMetadataDevice(std::set<std::string>* devices); void GetDmLinearMetadataDevice(std::set<std::string>* devices); bool InitDmLinearBackingDevices(const android::fs_mgr::LpMetadata& metadata); bool InitDmLinearBackingDevices(const android::fs_mgr::LpMetadata& metadata); void UseDsuIfPresent(); void UseDsuIfPresent(); void PreloadAvbKeys(); ListenerAction UeventCallback(const Uevent& uevent, std::set<std::string>* required_devices); ListenerAction UeventCallback(const Uevent& uevent, std::set<std::string>* required_devices); Loading @@ -110,6 +115,9 @@ class FirstStageMount { std::string super_partition_name_; std::string super_partition_name_; std::unique_ptr<DeviceHandler> device_handler_; std::unique_ptr<DeviceHandler> device_handler_; UeventListener uevent_listener_; UeventListener uevent_listener_; // Reads all AVB keys before chroot into /system, as they might be used // later when mounting other partitions, e.g., /vendor and /product. std::map<std::string, std::vector<std::string>> preload_avb_key_blobs_; }; }; class FirstStageMountVBootV1 : public FirstStageMount { class FirstStageMountVBootV1 : public FirstStageMount { Loading Loading @@ -508,11 +516,57 @@ bool FirstStageMount::MountPartition(const Fstab::iterator& begin, bool erase_sa return mounted; return mounted; } } void FirstStageMount::PreloadAvbKeys() { for (const auto& entry : fstab_) { // No need to cache the key content if it's empty, or is already cached. if (entry.avb_keys.empty() || preload_avb_key_blobs_.count(entry.avb_keys)) { continue; } // Determines all key paths first. std::vector<std::string> key_paths; if (is_dir(entry.avb_keys.c_str())) { // fstab_keys might be a dir, e.g., /avb. const char* avb_key_dir = entry.avb_keys.c_str(); std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(avb_key_dir), closedir); if (!dir) { LOG(ERROR) << "Failed to opendir: " << dir; continue; } // Gets all key pathes under the dir. struct dirent* de; while ((de = readdir(dir.get()))) { if (de->d_type != DT_REG) continue; std::string full_path = StringPrintf("%s/%s", avb_key_dir, de->d_name); key_paths.emplace_back(std::move(full_path)); } std::sort(key_paths.begin(), key_paths.end()); } else { // avb_keys are key paths separated by ":", if it's not a dir. key_paths = Split(entry.avb_keys, ":"); } // Reads the key content then cache it. std::vector<std::string> key_blobs; for (const auto& path : key_paths) { std::string key_value; if (!ReadFileToString(path, &key_value)) { continue; } key_blobs.emplace_back(std::move(key_value)); } // Maps entry.avb_keys to actual key blobs. preload_avb_key_blobs_[entry.avb_keys] = std::move(key_blobs); } } // If system is in the fstab then we're not a system-as-root device, and in // If system is in the fstab then we're not a system-as-root device, and in // this case, we mount system first then pivot to it. From that point on, // this case, we mount system first then pivot to it. From that point on, // we are effectively identical to a system-as-root device. // we are effectively identical to a system-as-root device. bool FirstStageMount::TrySwitchSystemAsRoot() { bool FirstStageMount::TrySwitchSystemAsRoot() { UseDsuIfPresent(); UseDsuIfPresent(); // Preloading all AVB keys from the ramdisk before switching root to /system. PreloadAvbKeys(); auto system_partition = std::find_if(fstab_.begin(), fstab_.end(), [](const auto& entry) { auto system_partition = std::find_if(fstab_.begin(), fstab_.end(), [](const auto& entry) { return entry.mount_point == "/system"; return entry.mount_point == "/system"; Loading Loading @@ -776,7 +830,8 @@ bool FirstStageMountVBootV2::SetUpDmVerity(FstabEntry* fstab_entry) { << fstab_entry->mount_point; << fstab_entry->mount_point; return true; // Returns true to mount the partition directly. return true; // Returns true to mount the partition directly. } else { } else { auto avb_standalone_handle = AvbHandle::LoadAndVerifyVbmeta(*fstab_entry); auto avb_standalone_handle = AvbHandle::LoadAndVerifyVbmeta( *fstab_entry, preload_avb_key_blobs_[fstab_entry->avb_keys]); if (!avb_standalone_handle) { if (!avb_standalone_handle) { LOG(ERROR) << "Failed to load offline vbmeta for " << fstab_entry->mount_point; LOG(ERROR) << "Failed to load offline vbmeta for " << fstab_entry->mount_point; // Fallbacks to built-in hashtree if fs_mgr_flags.avb is set. // Fallbacks to built-in hashtree if fs_mgr_flags.avb is set. Loading Loading
fs_mgr/libfs_avb/fs_avb.cpp +32 −12 Original line number Original line Diff line number Diff line Loading @@ -266,8 +266,10 @@ AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta( return avb_handle; return avb_handle; } } AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta(const FstabEntry& fstab_entry) { AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta(const FstabEntry& fstab_entry, if (fstab_entry.avb_keys.empty()) { const std::vector<std::string>& preload_avb_key_blobs) { // At least one of the following should be provided for public key matching. if (preload_avb_key_blobs.empty() && fstab_entry.avb_keys.empty()) { LERROR << "avb_keys=/path/to/key(s) is missing for " << fstab_entry.mount_point; LERROR << "avb_keys=/path/to/key(s) is missing for " << fstab_entry.mount_point; return nullptr; return nullptr; } } Loading Loading @@ -309,6 +311,20 @@ AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta(const FstabEntry& fstab_entry) { return nullptr; return nullptr; } } bool public_key_match = false; // Performs key matching for preload_avb_key_blobs first, if it is present. if (!public_key_data.empty() && !preload_avb_key_blobs.empty()) { if (std::find(preload_avb_key_blobs.begin(), preload_avb_key_blobs.end(), public_key_data) != preload_avb_key_blobs.end()) { public_key_match = true; } } // Performs key matching for fstab_entry.avb_keys if necessary. // Note that it is intentional to match both preload_avb_key_blobs and fstab_entry.avb_keys. // Some keys might only be availble before init chroots into /system, e.g., /avb/key1 // in the first-stage ramdisk, while other keys might only be available after the chroot, // e.g., /system/etc/avb/key2. if (!public_key_data.empty() && !public_key_match) { // fstab_entry.avb_keys might be either a directory containing multiple keys, // fstab_entry.avb_keys might be either a directory containing multiple keys, // or a string indicating multiple keys separated by ':'. // or a string indicating multiple keys separated by ':'. std::vector<std::string> allowed_avb_keys; std::vector<std::string> allowed_avb_keys; Loading @@ -319,8 +335,12 @@ AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta(const FstabEntry& fstab_entry) { } else { } else { allowed_avb_keys = Split(fstab_entry.avb_keys, ":"); allowed_avb_keys = Split(fstab_entry.avb_keys, ":"); } } if (ValidatePublicKeyBlob(public_key_data, allowed_avb_keys)) { public_key_match = true; } } if (!ValidatePublicKeyBlob(public_key_data, allowed_avb_keys)) { if (!public_key_match) { avb_handle->status_ = AvbHandleStatus::kVerificationError; avb_handle->status_ = AvbHandleStatus::kVerificationError; LWARNING << "Found unknown public key used to sign " << fstab_entry.mount_point; LWARNING << "Found unknown public key used to sign " << fstab_entry.mount_point; if (!allow_verification_error) { if (!allow_verification_error) { Loading
fs_mgr/libfs_avb/include/fs_avb/fs_avb.h +9 −2 Original line number Original line Diff line number Diff line Loading @@ -85,8 +85,15 @@ class AvbHandle { // TODO(bowgotsai): remove Open() and switch to LoadAndVerifyVbmeta(). // TODO(bowgotsai): remove Open() and switch to LoadAndVerifyVbmeta(). static AvbUniquePtr Open(); // loads inline vbmeta, via libavb. static AvbUniquePtr Open(); // loads inline vbmeta, via libavb. static AvbUniquePtr LoadAndVerifyVbmeta(); // loads inline vbmeta. static AvbUniquePtr LoadAndVerifyVbmeta(); // loads inline vbmeta. static AvbUniquePtr LoadAndVerifyVbmeta( const FstabEntry& fstab_entry); // loads offline vbmeta. // The caller can specify optional preload_avb_key_blobs for public key matching. // This is mostly for init to preload AVB keys before chroot into /system. // Both preload_avb_key_blobs and fstab_entry.avb_keys (file paths) will be used // for public key matching. static AvbUniquePtr LoadAndVerifyVbmeta( // loads offline vbmeta. const FstabEntry& fstab_entry, const std::vector<std::string>& preload_avb_key_blobs = {}); static AvbUniquePtr LoadAndVerifyVbmeta( // loads offline vbmeta. static AvbUniquePtr LoadAndVerifyVbmeta( // loads offline vbmeta. const std::string& partition_name, const std::string& ab_suffix, const std::string& partition_name, const std::string& ab_suffix, const std::string& ab_other_suffix, const std::string& expected_public_key, const std::string& ab_other_suffix, const std::string& expected_public_key, Loading
init/first_stage_mount.cpp +56 −1 Original line number Original line Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <unistd.h> #include <unistd.h> #include <chrono> #include <chrono> #include <map> #include <memory> #include <memory> #include <set> #include <set> #include <string> #include <string> Loading @@ -29,6 +30,7 @@ #include <android-base/chrono_utils.h> #include <android-base/chrono_utils.h> #include <android-base/file.h> #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/logging.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <android-base/strings.h> #include <fs_avb/fs_avb.h> #include <fs_avb/fs_avb.h> #include <fs_mgr.h> #include <fs_mgr.h> Loading @@ -45,7 +47,9 @@ #include "uevent_listener.h" #include "uevent_listener.h" #include "util.h" #include "util.h" using android::base::ReadFileToString; using android::base::Split; using android::base::Split; using android::base::StringPrintf; using android::base::Timer; using android::base::Timer; using android::fiemap::IImageManager; using android::fiemap::IImageManager; using android::fs_mgr::AvbHandle; using android::fs_mgr::AvbHandle; Loading Loading @@ -95,6 +99,7 @@ class FirstStageMount { void GetDmLinearMetadataDevice(std::set<std::string>* devices); void GetDmLinearMetadataDevice(std::set<std::string>* devices); bool InitDmLinearBackingDevices(const android::fs_mgr::LpMetadata& metadata); bool InitDmLinearBackingDevices(const android::fs_mgr::LpMetadata& metadata); void UseDsuIfPresent(); void UseDsuIfPresent(); void PreloadAvbKeys(); ListenerAction UeventCallback(const Uevent& uevent, std::set<std::string>* required_devices); ListenerAction UeventCallback(const Uevent& uevent, std::set<std::string>* required_devices); Loading @@ -110,6 +115,9 @@ class FirstStageMount { std::string super_partition_name_; std::string super_partition_name_; std::unique_ptr<DeviceHandler> device_handler_; std::unique_ptr<DeviceHandler> device_handler_; UeventListener uevent_listener_; UeventListener uevent_listener_; // Reads all AVB keys before chroot into /system, as they might be used // later when mounting other partitions, e.g., /vendor and /product. std::map<std::string, std::vector<std::string>> preload_avb_key_blobs_; }; }; class FirstStageMountVBootV1 : public FirstStageMount { class FirstStageMountVBootV1 : public FirstStageMount { Loading Loading @@ -508,11 +516,57 @@ bool FirstStageMount::MountPartition(const Fstab::iterator& begin, bool erase_sa return mounted; return mounted; } } void FirstStageMount::PreloadAvbKeys() { for (const auto& entry : fstab_) { // No need to cache the key content if it's empty, or is already cached. if (entry.avb_keys.empty() || preload_avb_key_blobs_.count(entry.avb_keys)) { continue; } // Determines all key paths first. std::vector<std::string> key_paths; if (is_dir(entry.avb_keys.c_str())) { // fstab_keys might be a dir, e.g., /avb. const char* avb_key_dir = entry.avb_keys.c_str(); std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(avb_key_dir), closedir); if (!dir) { LOG(ERROR) << "Failed to opendir: " << dir; continue; } // Gets all key pathes under the dir. struct dirent* de; while ((de = readdir(dir.get()))) { if (de->d_type != DT_REG) continue; std::string full_path = StringPrintf("%s/%s", avb_key_dir, de->d_name); key_paths.emplace_back(std::move(full_path)); } std::sort(key_paths.begin(), key_paths.end()); } else { // avb_keys are key paths separated by ":", if it's not a dir. key_paths = Split(entry.avb_keys, ":"); } // Reads the key content then cache it. std::vector<std::string> key_blobs; for (const auto& path : key_paths) { std::string key_value; if (!ReadFileToString(path, &key_value)) { continue; } key_blobs.emplace_back(std::move(key_value)); } // Maps entry.avb_keys to actual key blobs. preload_avb_key_blobs_[entry.avb_keys] = std::move(key_blobs); } } // If system is in the fstab then we're not a system-as-root device, and in // If system is in the fstab then we're not a system-as-root device, and in // this case, we mount system first then pivot to it. From that point on, // this case, we mount system first then pivot to it. From that point on, // we are effectively identical to a system-as-root device. // we are effectively identical to a system-as-root device. bool FirstStageMount::TrySwitchSystemAsRoot() { bool FirstStageMount::TrySwitchSystemAsRoot() { UseDsuIfPresent(); UseDsuIfPresent(); // Preloading all AVB keys from the ramdisk before switching root to /system. PreloadAvbKeys(); auto system_partition = std::find_if(fstab_.begin(), fstab_.end(), [](const auto& entry) { auto system_partition = std::find_if(fstab_.begin(), fstab_.end(), [](const auto& entry) { return entry.mount_point == "/system"; return entry.mount_point == "/system"; Loading Loading @@ -776,7 +830,8 @@ bool FirstStageMountVBootV2::SetUpDmVerity(FstabEntry* fstab_entry) { << fstab_entry->mount_point; << fstab_entry->mount_point; return true; // Returns true to mount the partition directly. return true; // Returns true to mount the partition directly. } else { } else { auto avb_standalone_handle = AvbHandle::LoadAndVerifyVbmeta(*fstab_entry); auto avb_standalone_handle = AvbHandle::LoadAndVerifyVbmeta( *fstab_entry, preload_avb_key_blobs_[fstab_entry->avb_keys]); if (!avb_standalone_handle) { if (!avb_standalone_handle) { LOG(ERROR) << "Failed to load offline vbmeta for " << fstab_entry->mount_point; LOG(ERROR) << "Failed to load offline vbmeta for " << fstab_entry->mount_point; // Fallbacks to built-in hashtree if fs_mgr_flags.avb is set. // Fallbacks to built-in hashtree if fs_mgr_flags.avb is set. Loading