From 69b9649e9bfafc2ddb5aa4dd609895b1fc097364 Mon Sep 17 00:00:00 2001 From: Tianjie Xu Date: Thu, 17 Aug 2017 16:42:57 -0700 Subject: Allow comparison against multi serial nums for A/B package The metadata file now can have multiple serial numbers in the format: serialno=serialno1|serialno2|serialno3 ... Verifier will pass the check if the device serial number matches any of these numbers. Bug: 64802465 Test: Create a metadata file with 1000 numbers and sideload in sailfish. The checker detects both match and mismatch cases. Change-Id: I3f12b75e15f4179df260778e37f4563d65db0fa8 --- install.cpp | 20 ++++++++--- tests/component/install_test.cpp | 71 ++++++++++++++++++++++++++++++++-------- 2 files changed, 73 insertions(+), 18 deletions(-) diff --git a/install.cpp b/install.cpp index 7fbf5c01f..1220c6ab7 100644 --- a/install.cpp +++ b/install.cpp @@ -148,13 +148,23 @@ static int check_newer_ab_build(ZipArchiveHandle zip) { return INSTALL_ERROR; } - // We allow the package to not have any serialno, but if it has a non-empty - // value it should match. + // We allow the package to not have any serialno; and we also allow it to carry multiple serial + // numbers split by "|"; e.g. serialno=serialno1|serialno2|serialno3 ... We will fail the + // verification if the device's serialno doesn't match any of these carried numbers. value = android::base::GetProperty("ro.serialno", ""); const std::string& pkg_serial_no = metadata["serialno"]; - if (!pkg_serial_no.empty() && pkg_serial_no != value) { - LOG(ERROR) << "Package is for serial " << pkg_serial_no; - return INSTALL_ERROR; + if (!pkg_serial_no.empty()) { + bool match = false; + for (const std::string& number : android::base::Split(pkg_serial_no, "|")) { + if (value == android::base::Trim(number)) { + match = true; + break; + } + } + if (!match) { + LOG(ERROR) << "Package is for serial " << pkg_serial_no; + return INSTALL_ERROR; + } } if (metadata["ota-type"] != "AB") { diff --git a/tests/component/install_test.cpp b/tests/component/install_test.cpp index 968196fc0..7bb496066 100644 --- a/tests/component/install_test.cpp +++ b/tests/component/install_test.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -198,8 +199,8 @@ TEST(InstallTest, verify_package_compatibility_with_libvintf_system_manifest_xml CloseArchive(zip); } -TEST(InstallTest, update_binary_command_smoke) { #ifdef AB_OTA_UPDATER +static void VerifyAbUpdateBinaryCommand(const std::string& serialno, bool success = true) { TemporaryFile temp_file; FILE* zip_file = fdopen(temp_file.fd, "w"); ZipWriter writer(zip_file); @@ -215,11 +216,13 @@ TEST(InstallTest, update_binary_command_smoke) { ASSERT_NE("", device); std::string timestamp = android::base::GetProperty("ro.build.date.utc", ""); ASSERT_NE("", timestamp); - std::string metadata = android::base::Join( - std::vector{ - "ota-type=AB", "pre-device=" + device, "post-timestamp=" + timestamp, - }, - "\n"); + + std::vector meta{ "ota-type=AB", "pre-device=" + device, + "post-timestamp=" + timestamp }; + if (!serialno.empty()) { + meta.push_back("serialno=" + serialno); + } + std::string metadata = android::base::Join(meta, "\n"); ASSERT_EQ(0, writer.WriteBytes(metadata.data(), metadata.size())); ASSERT_EQ(0, writer.FinishEntry()); ASSERT_EQ(0, writer.Finish()); @@ -234,14 +237,25 @@ TEST(InstallTest, update_binary_command_smoke) { std::string package = "/path/to/update.zip"; std::string binary_path = "/sbin/update_engine_sideload"; std::vector cmd; - ASSERT_EQ(0, update_binary_command(package, zip, binary_path, 0, status_fd, &cmd)); - ASSERT_EQ(5U, cmd.size()); - ASSERT_EQ(binary_path, cmd[0]); - ASSERT_EQ("--payload=file://" + package, cmd[1]); - ASSERT_EQ("--offset=" + std::to_string(payload_entry.offset), cmd[2]); - ASSERT_EQ("--headers=" + properties, cmd[3]); - ASSERT_EQ("--status_fd=" + std::to_string(status_fd), cmd[4]); + if (success) { + ASSERT_EQ(0, update_binary_command(package, zip, binary_path, 0, status_fd, &cmd)); + ASSERT_EQ(5U, cmd.size()); + ASSERT_EQ(binary_path, cmd[0]); + ASSERT_EQ("--payload=file://" + package, cmd[1]); + ASSERT_EQ("--offset=" + std::to_string(payload_entry.offset), cmd[2]); + ASSERT_EQ("--headers=" + properties, cmd[3]); + ASSERT_EQ("--status_fd=" + std::to_string(status_fd), cmd[4]); + } else { + ASSERT_EQ(INSTALL_ERROR, update_binary_command(package, zip, binary_path, 0, status_fd, &cmd)); + } CloseArchive(zip); +} +#endif // AB_OTA_UPDATER + +TEST(InstallTest, update_binary_command_smoke) { +#ifdef AB_OTA_UPDATER + // Empty serialno will pass the verification. + VerifyAbUpdateBinaryCommand({}); #else TemporaryFile temp_file; FILE* zip_file = fdopen(temp_file.fd, "w"); @@ -340,3 +354,34 @@ TEST(InstallTest, update_binary_command_invalid) { CloseArchive(zip); #endif // AB_OTA_UPDATER } + +#ifdef AB_OTA_UPDATER +TEST(InstallTest, update_binary_command_multiple_serialno) { + std::string serialno = android::base::GetProperty("ro.serialno", ""); + ASSERT_NE("", serialno); + + // Single matching serialno will pass the verification. + VerifyAbUpdateBinaryCommand(serialno); + + static constexpr char alphabet[] = + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + auto generator = []() { return alphabet[rand() % (sizeof(alphabet) - 1)]; }; + + // Generate 900 random serial numbers. + std::string random_serial; + for (size_t i = 0; i < 900; i++) { + generate_n(back_inserter(random_serial), serialno.size(), generator); + random_serial.append("|"); + } + // Random serialnos should fail the verification. + VerifyAbUpdateBinaryCommand(random_serial, false); + + std::string long_serial = random_serial + serialno + "|"; + for (size_t i = 0; i < 99; i++) { + generate_n(back_inserter(long_serial), serialno.size(), generator); + long_serial.append("|"); + } + // String with the matching serialno should pass the verification. + VerifyAbUpdateBinaryCommand(long_serial); +} +#endif // AB_OTA_UPDATER -- cgit v1.2.3