Merge "libsnapshot: Add boot_complete metrics."
diff --git a/fs_mgr/libsnapshot/cow_api_test.cpp b/fs_mgr/libsnapshot/cow_api_test.cpp
index a96352a..5d63220 100644
--- a/fs_mgr/libsnapshot/cow_api_test.cpp
+++ b/fs_mgr/libsnapshot/cow_api_test.cpp
@@ -757,6 +757,30 @@
ASSERT_TRUE(iter->Done());
}
+TEST_F(CowTest, AppendAfterFinalize) {
+ CowOptions options;
+ options.cluster_ops = 0;
+ auto writer = std::make_unique<CowWriter>(options);
+ ASSERT_TRUE(writer->Initialize(cow_->fd));
+
+ std::string data = "This is some data, believe it";
+ data.resize(options.block_size, '\0');
+ ASSERT_TRUE(writer->AddRawBlocks(50, data.data(), data.size()));
+ ASSERT_TRUE(writer->AddLabel(3));
+ ASSERT_TRUE(writer->Finalize());
+
+ std::string data2 = "More data!";
+ data2.resize(options.block_size, '\0');
+ ASSERT_TRUE(writer->AddRawBlocks(51, data2.data(), data2.size()));
+ ASSERT_TRUE(writer->Finalize());
+
+ ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);
+
+ // COW should be valid.
+ CowReader reader;
+ ASSERT_TRUE(reader.Parse(cow_->fd));
+}
+
} // namespace snapshot
} // namespace android
diff --git a/fs_mgr/libsnapshot/cow_reader.cpp b/fs_mgr/libsnapshot/cow_reader.cpp
index 163e457..44a423c 100644
--- a/fs_mgr/libsnapshot/cow_reader.cpp
+++ b/fs_mgr/libsnapshot/cow_reader.cpp
@@ -229,7 +229,8 @@
if (footer_) {
if (ops_buffer->size() != footer_->op.num_ops) {
- LOG(ERROR) << "num ops does not match";
+ LOG(ERROR) << "num ops does not match, expected " << footer_->op.num_ops << ", found "
+ << ops_buffer->size();
return false;
}
if (ops_buffer->size() * sizeof(CowOperation) != footer_->op.ops_size) {
diff --git a/fs_mgr/libsnapshot/cow_writer.cpp b/fs_mgr/libsnapshot/cow_writer.cpp
index 81edc79..59f6d6f 100644
--- a/fs_mgr/libsnapshot/cow_writer.cpp
+++ b/fs_mgr/libsnapshot/cow_writer.cpp
@@ -376,6 +376,7 @@
auto continue_data_pos = next_data_pos_;
auto continue_op_pos = next_op_pos_;
auto continue_size = ops_.size();
+ auto continue_num_ops = footer_.op.num_ops;
bool extra_cluster = false;
// Footer should be at the end of a file, so if there is data after the current block, end it
@@ -408,9 +409,9 @@
current_data_size_ = continue_data_size;
next_data_pos_ = continue_data_pos;
next_op_pos_ = continue_op_pos;
+ footer_.op.num_ops = continue_num_ops;
ops_.resize(continue_size);
}
-
return Sync();
}
diff --git a/init/init.cpp b/init/init.cpp
index 70d6809..7264b22 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -518,11 +518,9 @@
if (!android::base::GetBoolProperty("ro.oem_unlock_supported", false)) {
return;
}
- ImportKernelCmdline([](const std::string& key, const std::string& value) {
- if (key == "androidboot.verifiedbootstate") {
- SetProperty("ro.boot.flash.locked", value == "orange" ? "0" : "1");
- }
- });
+ SetProperty(
+ "ro.boot.flash.locked",
+ android::base::GetProperty("ro.boot.verifiedbootstate", "") == "orange" ? "0" : "1");
}
static Result<void> property_enable_triggers_action(const BuiltinArguments& args) {
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 404a99c..382f430 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -44,6 +44,7 @@
#include <mutex>
#include <optional>
#include <queue>
+#include <string_view>
#include <thread>
#include <vector>
@@ -1162,28 +1163,25 @@
}
}
+constexpr auto ANDROIDBOOT_PREFIX = "androidboot."sv;
+
static void ProcessKernelCmdline() {
- bool for_emulator = false;
ImportKernelCmdline([&](const std::string& key, const std::string& value) {
- if (key == "qemu") {
- for_emulator = true;
- } else if (StartsWith(key, "androidboot.")) {
- InitPropertySet("ro.boot." + key.substr(12), value);
+ if (StartsWith(key, ANDROIDBOOT_PREFIX)) {
+ InitPropertySet("ro.boot." + key.substr(ANDROIDBOOT_PREFIX.size()), value);
+ } else if (StartsWith(key, "qemu."sv)) {
+ InitPropertySet("ro.kernel." + key, value);
+ } else if (key == "qemu") {
+ InitPropertySet("ro.kernel." + key, value); // emulator specific, deprecated
+ InitPropertySet("ro.boot." + key, value);
}
});
-
- if (for_emulator) {
- ImportKernelCmdline([&](const std::string& key, const std::string& value) {
- // In the emulator, export any kernel option with the "ro.kernel." prefix.
- InitPropertySet("ro.kernel." + key, value);
- });
- }
}
static void ProcessBootconfig() {
ImportBootconfig([&](const std::string& key, const std::string& value) {
- if (StartsWith(key, "androidboot.")) {
- InitPropertySet("ro.boot." + key.substr(12), value);
+ if (StartsWith(key, ANDROIDBOOT_PREFIX)) {
+ InitPropertySet("ro.boot." + key.substr(ANDROIDBOOT_PREFIX.size()), value);
} else if (key == "hardware") {
// "hardware" in bootconfig replaces "androidboot.hardware" kernel
// cmdline parameter
diff --git a/init/selinux.cpp b/init/selinux.cpp
index 47686b8..62c4586 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -63,6 +63,7 @@
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/parseint.h>
+#include <android-base/result.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <fs_avb/fs_avb.h>
@@ -222,8 +223,8 @@
return true;
}
-bool FindPrecompiledSplitPolicy(std::string* file) {
- file->clear();
+Result<std::string> FindPrecompiledSplitPolicy() {
+ std::string precompiled_sepolicy;
// If there is an odm partition, precompiled_sepolicy will be in
// odm/etc/selinux. Otherwise it will be in vendor/etc/selinux.
static constexpr const char vendor_precompiled_sepolicy[] =
@@ -231,62 +232,49 @@
static constexpr const char odm_precompiled_sepolicy[] =
"/odm/etc/selinux/precompiled_sepolicy";
if (access(odm_precompiled_sepolicy, R_OK) == 0) {
- *file = odm_precompiled_sepolicy;
+ precompiled_sepolicy = odm_precompiled_sepolicy;
} else if (access(vendor_precompiled_sepolicy, R_OK) == 0) {
- *file = vendor_precompiled_sepolicy;
+ precompiled_sepolicy = vendor_precompiled_sepolicy;
} else {
- PLOG(INFO) << "No precompiled sepolicy";
- return false;
- }
- std::string actual_plat_id;
- if (!ReadFirstLine("/system/etc/selinux/plat_sepolicy_and_mapping.sha256", &actual_plat_id)) {
- PLOG(INFO) << "Failed to read "
- "/system/etc/selinux/plat_sepolicy_and_mapping.sha256";
- return false;
- }
- std::string actual_system_ext_id;
- if (!ReadFirstLine("/system_ext/etc/selinux/system_ext_sepolicy_and_mapping.sha256",
- &actual_system_ext_id)) {
- PLOG(INFO) << "Failed to read "
- "/system_ext/etc/selinux/system_ext_sepolicy_and_mapping.sha256";
- return false;
- }
- std::string actual_product_id;
- if (!ReadFirstLine("/product/etc/selinux/product_sepolicy_and_mapping.sha256",
- &actual_product_id)) {
- PLOG(INFO) << "Failed to read "
- "/product/etc/selinux/product_sepolicy_and_mapping.sha256";
- return false;
+ return ErrnoError() << "No precompiled sepolicy at " << vendor_precompiled_sepolicy;
}
- std::string precompiled_plat_id;
- std::string precompiled_plat_sha256 = *file + ".plat_sepolicy_and_mapping.sha256";
- if (!ReadFirstLine(precompiled_plat_sha256.c_str(), &precompiled_plat_id)) {
- PLOG(INFO) << "Failed to read " << precompiled_plat_sha256;
- file->clear();
- return false;
+ // Use precompiled sepolicy only when all corresponding hashes are equal.
+ // plat_sepolicy is always checked, while system_ext and product are checked only when they
+ // exist.
+ std::vector<std::pair<std::string, std::string>> sepolicy_hashes{
+ {"/system/etc/selinux/plat_sepolicy_and_mapping.sha256",
+ precompiled_sepolicy + ".plat_sepolicy_and_mapping.sha256"},
+ };
+
+ if (access("/system_ext/etc/selinux/system_ext_sepolicy.cil", F_OK) == 0) {
+ sepolicy_hashes.emplace_back(
+ "/system_ext/etc/selinux/system_ext_sepolicy_and_mapping.sha256",
+ precompiled_sepolicy + ".system_ext_sepolicy_and_mapping.sha256");
}
- std::string precompiled_system_ext_id;
- std::string precompiled_system_ext_sha256 = *file + ".system_ext_sepolicy_and_mapping.sha256";
- if (!ReadFirstLine(precompiled_system_ext_sha256.c_str(), &precompiled_system_ext_id)) {
- PLOG(INFO) << "Failed to read " << precompiled_system_ext_sha256;
- file->clear();
- return false;
+
+ if (access("/product/etc/selinux/product_sepolicy.cil", F_OK) == 0) {
+ sepolicy_hashes.emplace_back("/product/etc/selinux/product_sepolicy_and_mapping.sha256",
+ precompiled_sepolicy + ".product_sepolicy_and_mapping.sha256");
}
- std::string precompiled_product_id;
- std::string precompiled_product_sha256 = *file + ".product_sepolicy_and_mapping.sha256";
- if (!ReadFirstLine(precompiled_product_sha256.c_str(), &precompiled_product_id)) {
- PLOG(INFO) << "Failed to read " << precompiled_product_sha256;
- file->clear();
- return false;
+
+ for (const auto& [actual_id_path, precompiled_id_path] : sepolicy_hashes) {
+ std::string actual_id;
+ if (!ReadFirstLine(actual_id_path.c_str(), &actual_id)) {
+ return ErrnoError() << "Failed to read " << actual_id_path;
+ }
+
+ std::string precompiled_id;
+ if (!ReadFirstLine(precompiled_id_path.c_str(), &precompiled_id)) {
+ return ErrnoError() << "Failed to read " << precompiled_id_path;
+ }
+
+ if (actual_id.empty() || actual_id != precompiled_id) {
+ return Error() << actual_id_path << " and " << precompiled_id_path << " differ";
+ }
}
- if (actual_plat_id.empty() || actual_plat_id != precompiled_plat_id ||
- actual_system_ext_id.empty() || actual_system_ext_id != precompiled_system_ext_id ||
- actual_product_id.empty() || actual_product_id != precompiled_product_id) {
- file->clear();
- return false;
- }
- return true;
+
+ return precompiled_sepolicy;
}
bool GetVendorMappingVersion(std::string* plat_vers) {
@@ -333,15 +321,18 @@
// Load precompiled policy from vendor image, if a matching policy is found there. The policy
// must match the platform policy on the system image.
- std::string precompiled_sepolicy_file;
// use_userdebug_policy requires compiling sepolicy with userdebug_plat_sepolicy.cil.
// Thus it cannot use the precompiled policy from vendor image.
- if (!use_userdebug_policy && FindPrecompiledSplitPolicy(&precompiled_sepolicy_file)) {
- unique_fd fd(open(precompiled_sepolicy_file.c_str(), O_RDONLY | O_CLOEXEC | O_BINARY));
- if (fd != -1) {
- policy_file->fd = std::move(fd);
- policy_file->path = std::move(precompiled_sepolicy_file);
- return true;
+ if (!use_userdebug_policy) {
+ if (auto res = FindPrecompiledSplitPolicy(); res.ok()) {
+ unique_fd fd(open(res->c_str(), O_RDONLY | O_CLOEXEC | O_BINARY));
+ if (fd != -1) {
+ policy_file->fd = std::move(fd);
+ policy_file->path = std::move(*res);
+ return true;
+ }
+ } else {
+ LOG(INFO) << res.error();
}
}
// No suitable precompiled policy could be loaded
diff --git a/rootdir/etc/linker.config.json b/rootdir/etc/linker.config.json
index 2faf608..83cb6ff 100644
--- a/rootdir/etc/linker.config.json
+++ b/rootdir/etc/linker.config.json
@@ -6,6 +6,7 @@
"libnativebridge.so",
"libnativehelper.so",
"libnativeloader.so",
+ "libsigchain.so",
"libandroidicu.so",
"libicu.so",
// TODO(b/122876336): Remove libpac.so once it's migrated to Webview
@@ -26,4 +27,4 @@
"libadb_pairing_connection.so",
"libadb_pairing_server.so"
]
-}
\ No newline at end of file
+}