diff options
Diffstat (limited to '')
-rw-r--r-- | Android.mk | 29 | ||||
-rw-r--r-- | error_code.h | 3 | ||||
-rw-r--r-- | install.cpp | 72 | ||||
-rw-r--r-- | install.h | 4 | ||||
-rw-r--r-- | mounts.cpp | 17 | ||||
-rw-r--r-- | mounts.h | 4 | ||||
-rw-r--r-- | tests/Android.mk | 3 | ||||
-rw-r--r-- | tests/component/install_test.cpp | 57 |
8 files changed, 163 insertions, 26 deletions
diff --git a/Android.mk b/Android.mk index d70101395..9e374de8f 100644 --- a/Android.mk +++ b/Android.mk @@ -14,6 +14,10 @@ LOCAL_PATH := $(call my-dir) +# Needed by build/make/core/Makefile. +RECOVERY_API_VERSION := 3 +RECOVERY_FSTAB_VERSION := 2 + # libfusesideload (static library) # =============================== include $(CLEAR_VARS) @@ -36,6 +40,27 @@ LOCAL_MODULE := libmounts LOCAL_STATIC_LIBRARIES := libbase include $(BUILD_STATIC_LIBRARY) +# librecovery (static library) +# =============================== +include $(CLEAR_VARS) +LOCAL_SRC_FILES := \ + install.cpp +LOCAL_CFLAGS := -Wno-unused-parameter -Werror +LOCAL_CFLAGS += -DRECOVERY_API_VERSION=$(RECOVERY_API_VERSION) + +ifeq ($(AB_OTA_UPDATER),true) + LOCAL_CFLAGS += -DAB_OTA_UPDATER=1 +endif + +LOCAL_MODULE := librecovery +LOCAL_STATIC_LIBRARIES := \ + libminui \ + libcrypto_utils \ + libcrypto \ + libbase + +include $(BUILD_STATIC_LIBRARY) + # recovery (static executable) # =============================== include $(CLEAR_VARS) @@ -45,7 +70,6 @@ LOCAL_SRC_FILES := \ asn1_decoder.cpp \ device.cpp \ fuse_sdcard_provider.cpp \ - install.cpp \ recovery.cpp \ roots.cpp \ rotate_logs.cpp \ @@ -65,8 +89,6 @@ LOCAL_REQUIRED_MODULES := mkfs.f2fs endif endif -RECOVERY_API_VERSION := 3 -RECOVERY_FSTAB_VERSION := 2 LOCAL_CFLAGS += -DRECOVERY_API_VERSION=$(RECOVERY_API_VERSION) LOCAL_CFLAGS += -Wno-unused-parameter -Werror LOCAL_CLANG := true @@ -76,6 +98,7 @@ LOCAL_C_INCLUDES += \ system/core/adb \ LOCAL_STATIC_LIBRARIES := \ + librecovery \ libbatterymonitor \ libbootloader_message \ libext4_utils \ diff --git a/error_code.h b/error_code.h index 5dad6b263..cde4ee6de 100644 --- a/error_code.h +++ b/error_code.h @@ -22,7 +22,8 @@ enum ErrorCode { kLowBattery = 20, kZipVerificationFailure, kZipOpenFailure, - kBootreasonInBlacklist + kBootreasonInBlacklist, + kPackageCompatibilityFailure, }; enum CauseCode { diff --git a/install.cpp b/install.cpp index 0a2fa3ca4..6dcd3565e 100644 --- a/install.cpp +++ b/install.cpp @@ -489,6 +489,69 @@ static int try_update_binary(const char* path, ZipArchiveHandle zip, bool* wipe_ return INSTALL_SUCCESS; } +// Verifes the compatibility info in a Treble-compatible package. Returns true directly if the +// entry doesn't exist. Note that the compatibility info is packed in a zip file inside the OTA +// package. +bool verify_package_compatibility(ZipArchiveHandle package_zip) { + LOG(INFO) << "Verifying package compatibility..."; + + static constexpr const char* COMPATIBILITY_ZIP_ENTRY = "compatibility.zip"; + ZipString compatibility_entry_name(COMPATIBILITY_ZIP_ENTRY); + ZipEntry compatibility_entry; + if (FindEntry(package_zip, compatibility_entry_name, &compatibility_entry) != 0) { + LOG(INFO) << "Package doesn't contain " << COMPATIBILITY_ZIP_ENTRY << " entry"; + return true; + } + + std::string zip_content(compatibility_entry.uncompressed_length, '\0'); + int32_t ret; + if ((ret = ExtractToMemory(package_zip, &compatibility_entry, + reinterpret_cast<uint8_t*>(&zip_content[0]), + compatibility_entry.uncompressed_length)) != 0) { + LOG(ERROR) << "Failed to read " << COMPATIBILITY_ZIP_ENTRY << ": " << ErrorCodeString(ret); + return false; + } + + ZipArchiveHandle zip_handle; + ret = OpenArchiveFromMemory(static_cast<void*>(const_cast<char*>(zip_content.data())), + zip_content.size(), COMPATIBILITY_ZIP_ENTRY, &zip_handle); + if (ret != 0) { + LOG(ERROR) << "Failed to OpenArchiveFromMemory: " << ErrorCodeString(ret); + return false; + } + + // Iterate all the entries inside COMPATIBILITY_ZIP_ENTRY and read the contents. + void* cookie; + ret = StartIteration(zip_handle, &cookie, nullptr, nullptr); + if (ret != 0) { + LOG(ERROR) << "Failed to start iterating zip entries: " << ErrorCodeString(ret); + CloseArchive(zip_handle); + return false; + } + std::unique_ptr<void, decltype(&EndIteration)> guard(cookie, EndIteration); + + std::vector<std::string> compatibility_info; + ZipEntry info_entry; + ZipString info_name; + while (Next(cookie, &info_entry, &info_name) == 0) { + std::string content(info_entry.uncompressed_length, '\0'); + int32_t ret = ExtractToMemory(zip_handle, &info_entry, reinterpret_cast<uint8_t*>(&content[0]), + info_entry.uncompressed_length); + if (ret != 0) { + LOG(ERROR) << "Failed to read " << info_name.name << ": " << ErrorCodeString(ret); + CloseArchive(zip_handle); + return false; + } + compatibility_info.emplace_back(std::move(content)); + } + CloseArchive(zip_handle); + + // TODO(b/36814503): Enable the actual verification when VintfObject::CheckCompatibility() lands. + // VintfObject::CheckCompatibility returns zero on success. + // return (android::vintf::VintfObject::CheckCompatibility(compatibility_info, true) == 0); + return true; +} + static int really_install_package(const char *path, bool* wipe_cache, bool needs_mount, std::vector<std::string>& log_buffer, int retry_count, int* max_temperature) @@ -536,6 +599,15 @@ really_install_package(const char *path, bool* wipe_cache, bool needs_mount, return INSTALL_CORRUPT; } + // Additionally verify the compatibility of the package. + if (!verify_package_compatibility(zip)) { + LOG(ERROR) << "Failed to verify package compatibility"; + log_buffer.push_back(android::base::StringPrintf("error: %d", kPackageCompatibilityFailure)); + sysReleaseMap(&map); + CloseArchive(zip); + return INSTALL_CORRUPT; + } + // Verify and install the contents of the package. ui->Print("Installing update...\n"); if (retry_count > 0) { @@ -37,4 +37,8 @@ bool verify_package(const unsigned char* package_data, size_t package_size); // Return true if succeed, otherwise return false. bool read_metadata_from_package(ZipArchiveHandle zip, std::string* meta_data); +// Verifes the compatibility info in a Treble-compatible package. Returns true directly if the +// entry doesn't exist. +bool verify_package_compatibility(ZipArchiveHandle package_zip); + #endif // RECOVERY_INSTALL_H_ diff --git a/mounts.cpp b/mounts.cpp index fbcbac014..76fa65739 100644 --- a/mounts.cpp +++ b/mounts.cpp @@ -62,13 +62,6 @@ bool scan_mounted_volumes() { return true; } -MountedVolume* find_mounted_volume_by_device(const char* device) { - for (size_t i = 0; i < g_mounts_state.size(); ++i) { - if (g_mounts_state[i]->device == device) return g_mounts_state[i]; - } - return nullptr; -} - MountedVolume* find_mounted_volume_by_mount_point(const char* mount_point) { for (size_t i = 0; i < g_mounts_state.size(); ++i) { if (g_mounts_state[i]->mount_point == mount_point) return g_mounts_state[i]; @@ -87,13 +80,3 @@ int unmount_mounted_volume(MountedVolume* volume) { } return result; } - -int remount_read_only(MountedVolume* volume) { - int result = mount(volume->device.c_str(), volume->mount_point.c_str(), - volume->filesystem.c_str(), - MS_NOATIME | MS_NODEV | MS_NODIRATIME | MS_RDONLY | MS_REMOUNT, 0); - if (result == -1) { - PLOG(WARNING) << "Failed to remount read-only " << volume->mount_point; - } - return result; -} @@ -21,12 +21,8 @@ struct MountedVolume; bool scan_mounted_volumes(); -MountedVolume* find_mounted_volume_by_device(const char* device); - MountedVolume* find_mounted_volume_by_mount_point(const char* mount_point); int unmount_mounted_volume(MountedVolume* volume); -int remount_read_only(MountedVolume* volume); - #endif diff --git a/tests/Android.mk b/tests/Android.mk index 974aa0e2d..a1f0d4892 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -93,6 +93,7 @@ LOCAL_SRC_FILES := \ component/bootloader_message_test.cpp \ component/edify_test.cpp \ component/imgdiff_test.cpp \ + component/install_test.cpp \ component/sideload_test.cpp \ component/uncrypt_test.cpp \ component/updater_test.cpp \ @@ -117,6 +118,7 @@ LOCAL_STATIC_LIBRARIES := \ libbsdiff \ libbspatch \ libotafault \ + librecovery \ libupdater \ libbootloader_message \ libverifier \ @@ -131,7 +133,6 @@ LOCAL_STATIC_LIBRARIES := \ libsparse \ libcrypto_utils \ libcrypto \ - libcutils \ libbz \ libziparchive \ libutils \ diff --git a/tests/component/install_test.cpp b/tests/component/install_test.cpp new file mode 100644 index 000000000..3b6fbc301 --- /dev/null +++ b/tests/component/install_test.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agree to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> + +#include <android-base/test_utils.h> +#include <gtest/gtest.h> +#include <ziparchive/zip_archive.h> +#include <ziparchive/zip_writer.h> + +#include "install.h" + +TEST(InstallTest, verify_package_compatibility_no_entry) { + TemporaryFile temp_file; + FILE* zip_file = fdopen(temp_file.fd, "w"); + ZipWriter writer(zip_file); + // The archive must have something to be opened correctly. + ASSERT_EQ(0, writer.StartEntry("dummy_entry", 0)); + ASSERT_EQ(0, writer.FinishEntry()); + ASSERT_EQ(0, writer.Finish()); + ASSERT_EQ(0, fclose(zip_file)); + + // Doesn't contain compatibility zip entry. + ZipArchiveHandle zip; + ASSERT_EQ(0, OpenArchive(temp_file.path, &zip)); + ASSERT_TRUE(verify_package_compatibility(zip)); + CloseArchive(zip); +} + +TEST(InstallTest, verify_package_compatibility_invalid_entry) { + TemporaryFile temp_file; + FILE* zip_file = fdopen(temp_file.fd, "w"); + ZipWriter writer(zip_file); + ASSERT_EQ(0, writer.StartEntry("compatibility.zip", 0)); + ASSERT_EQ(0, writer.FinishEntry()); + ASSERT_EQ(0, writer.Finish()); + ASSERT_EQ(0, fclose(zip_file)); + + // Empty compatibility zip entry. + ZipArchiveHandle zip; + ASSERT_EQ(0, OpenArchive(temp_file.path, &zip)); + ASSERT_FALSE(verify_package_compatibility(zip)); + CloseArchive(zip); +} |