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
This commit is contained in:
Tianjie Xu 2017-08-17 16:42:57 -07:00
parent b4bc57ed39
commit 69b9649e9b
2 changed files with 73 additions and 18 deletions

View file

@ -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") {

View file

@ -19,6 +19,7 @@
#include <sys/types.h>
#include <unistd.h>
#include <algorithm>
#include <string>
#include <vector>
@ -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<std::string>{
"ota-type=AB", "pre-device=" + device, "post-timestamp=" + timestamp,
},
"\n");
std::vector<std::string> 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<std::string> 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