Loading tests/Android.mk +6 −0 Original line number Diff line number Diff line Loading @@ -89,6 +89,10 @@ ifeq ($(AB_OTA_UPDATER),true) LOCAL_CFLAGS += -DAB_OTA_UPDATER=1 endif ifeq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),true) LOCAL_CFLAGS += -DPRODUCT_SUPPORTS_VERITY=1 endif LOCAL_MODULE := recovery_component_test LOCAL_COMPATIBILITY_SUITE := device-tests LOCAL_C_INCLUDES := bootable/recovery Loading @@ -101,6 +105,7 @@ LOCAL_SRC_FILES := \ component/sideload_test.cpp \ component/uncrypt_test.cpp \ component/updater_test.cpp \ component/update_verifier_test.cpp \ component/verifier_test.cpp LOCAL_FORCE_STATIC_EXECUTABLE := true Loading Loading @@ -128,6 +133,7 @@ LOCAL_STATIC_LIBRARIES := \ libverifier \ libotautil \ libmounts \ libupdate_verifier \ libdivsufsort \ libdivsufsort64 \ libfs_mgr \ Loading tests/component/update_verifier_test.cpp 0 → 100644 +83 −0 Original line number Diff line number Diff line /* * 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 agreed 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 <string> #include <android-base/file.h> #include <android-base/test_utils.h> #include <gtest/gtest.h> #include <update_verifier/update_verifier.h> class UpdateVerifierTest : public ::testing::Test { protected: void SetUp() override { #ifdef PRODUCT_SUPPORTS_VERITY verity_supported = true; #else verity_supported = false; #endif } bool verity_supported; }; TEST_F(UpdateVerifierTest, verify_image_no_care_map) { // Non-existing care_map is allowed. ASSERT_TRUE(verify_image("/doesntexist")); } TEST_F(UpdateVerifierTest, verify_image_smoke) { // This test relies on dm-verity support. if (!verity_supported) { GTEST_LOG_(INFO) << "Test skipped on devices without dm-verity support."; return; } // The care map file can have only two or four lines. TemporaryFile temp_file; std::string content = "system\n2,0,1"; ASSERT_TRUE(android::base::WriteStringToFile(content, temp_file.path)); ASSERT_TRUE(verify_image(temp_file.path)); // Leading and trailing newlines should be accepted. ASSERT_TRUE(android::base::WriteStringToFile("\n" + content + "\n\n", temp_file.path)); ASSERT_TRUE(verify_image(temp_file.path)); } TEST_F(UpdateVerifierTest, verify_image_wrong_lines) { // The care map file can have only two or four lines. TemporaryFile temp_file; ASSERT_FALSE(verify_image(temp_file.path)); ASSERT_TRUE(android::base::WriteStringToFile("line1", temp_file.path)); ASSERT_FALSE(verify_image(temp_file.path)); ASSERT_TRUE(android::base::WriteStringToFile("line1\nline2\nline3", temp_file.path)); ASSERT_FALSE(verify_image(temp_file.path)); } TEST_F(UpdateVerifierTest, verify_image_malformed_care_map) { // This test relies on dm-verity support. if (!verity_supported) { GTEST_LOG_(INFO) << "Test skipped on devices without dm-verity support."; return; } TemporaryFile temp_file; std::string content = "system\n2,1,0"; ASSERT_TRUE(android::base::WriteStringToFile(content, temp_file.path)); ASSERT_FALSE(verify_image(temp_file.path)); } update_verifier/Android.mk +34 −8 Original line number Diff line number Diff line Loading @@ -14,12 +14,43 @@ LOCAL_PATH := $(call my-dir) # libupdate_verifier (static library) # =============================== include $(CLEAR_VARS) LOCAL_CLANG := true LOCAL_SRC_FILES := update_verifier.cpp LOCAL_SRC_FILES := \ update_verifier.cpp LOCAL_MODULE := libupdate_verifier LOCAL_SHARED_LIBRARIES := \ libbase \ libcutils \ android.hardware.boot@1.0 LOCAL_CFLAGS := -Wall -Werror LOCAL_EXPORT_C_INCLUDE_DIRS := \ $(LOCAL_PATH)/include LOCAL_C_INCLUDES := \ $(LOCAL_PATH)/include ifeq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),true) LOCAL_CFLAGS += -DPRODUCT_SUPPORTS_VERITY=1 endif include $(BUILD_STATIC_LIBRARY) # update_verifier (executable) # =============================== include $(CLEAR_VARS) LOCAL_SRC_FILES := \ update_verifier_main.cpp LOCAL_MODULE := update_verifier LOCAL_STATIC_LIBRARIES := \ libupdate_verifier LOCAL_SHARED_LIBRARIES := \ libbase \ libcutils \ Loading @@ -29,13 +60,8 @@ LOCAL_SHARED_LIBRARIES := \ libhidlbase \ android.hardware.boot@1.0 LOCAL_CFLAGS := -Werror LOCAL_C_INCLUDES += $(LOCAL_PATH)/.. LOCAL_CFLAGS := -Wall -Werror LOCAL_INIT_RC := update_verifier.rc ifeq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),true) LOCAL_CFLAGS += -DPRODUCT_SUPPORTS_VERITY=1 endif include $(BUILD_EXECUTABLE) update_verifier/include/update_verifier/update_verifier.h 0 → 100644 +24 −0 Original line number Diff line number Diff line /* * 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 agreed 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. */ #pragma once #include <string> int update_verifier(int argc, char** argv); // Exposed for testing purpose. bool verify_image(const std::string& care_map_name); update_verifier/update_verifier.cpp +9 −8 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ * verifier reaches the end after the verification. */ #include "update_verifier/update_verifier.h" #include <dirent.h> #include <errno.h> #include <fcntl.h> Loading @@ -59,12 +61,6 @@ using android::hardware::boot::V1_0::IBootControl; using android::hardware::boot::V1_0::BoolResult; using android::hardware::boot::V1_0::CommandResult; constexpr auto CARE_MAP_FILE = "/data/ota_package/care_map.txt"; constexpr auto DM_PATH_PREFIX = "/sys/block/"; constexpr auto DM_PATH_SUFFIX = "/dm/name"; constexpr auto DEV_PATH = "/dev/block/"; constexpr int BLOCKSIZE = 4096; // Find directories in format of "/sys/block/dm-X". static int dm_name_filter(const dirent* de) { if (android::base::StartsWith(de->d_name, "dm-")) { Loading @@ -82,6 +78,7 @@ static bool read_blocks(const std::string& partition, const std::string& range_s // (or "vendor"), then dm-X is a dm-wrapped system/vendor partition. // Afterwards, update_verifier will read every block on the care_map_file of // "/dev/block/dm-X" to ensure the partition's integrity. static constexpr auto DM_PATH_PREFIX = "/sys/block/"; dirent** namelist; int n = scandir(DM_PATH_PREFIX, &namelist, dm_name_filter, alphasort); if (n == -1) { Loading @@ -93,6 +90,8 @@ static bool read_blocks(const std::string& partition, const std::string& range_s return false; } static constexpr auto DM_PATH_SUFFIX = "/dm/name"; static constexpr auto DEV_PATH = "/dev/block/"; std::string dm_block_device; while (n--) { std::string path = DM_PATH_PREFIX + std::string(namelist[n]->d_name) + DM_PATH_SUFFIX; Loading Loading @@ -143,6 +142,7 @@ static bool read_blocks(const std::string& partition, const std::string& range_s return false; } static constexpr int BLOCKSIZE = 4096; if (lseek64(fd.get(), static_cast<off64_t>(range_start) * BLOCKSIZE, SEEK_SET) == -1) { PLOG(ERROR) << "lseek to " << range_start << " failed"; return false; Loading @@ -161,7 +161,7 @@ static bool read_blocks(const std::string& partition, const std::string& range_s return true; } static bool verify_image(const std::string& care_map_name) { bool verify_image(const std::string& care_map_name) { android::base::unique_fd care_map_fd(TEMP_FAILURE_RETRY(open(care_map_name.c_str(), O_RDONLY))); // If the device is flashed before the current boot, it may not have care_map.txt // in /data/ota_package. To allow the device to continue booting in this situation, Loading Loading @@ -205,7 +205,7 @@ static int reboot_device() { while (true) pause(); } int main(int argc, char** argv) { int update_verifier(int argc, char** argv) { for (int i = 1; i < argc; i++) { LOG(INFO) << "Started with arg " << i << ": " << argv[i]; } Loading Loading @@ -238,6 +238,7 @@ int main(int argc, char** argv) { return reboot_device(); } static constexpr auto CARE_MAP_FILE = "/data/ota_package/care_map.txt"; if (!verify_image(CARE_MAP_FILE)) { LOG(ERROR) << "Failed to verify all blocks in care map file."; return reboot_device(); Loading Loading
tests/Android.mk +6 −0 Original line number Diff line number Diff line Loading @@ -89,6 +89,10 @@ ifeq ($(AB_OTA_UPDATER),true) LOCAL_CFLAGS += -DAB_OTA_UPDATER=1 endif ifeq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),true) LOCAL_CFLAGS += -DPRODUCT_SUPPORTS_VERITY=1 endif LOCAL_MODULE := recovery_component_test LOCAL_COMPATIBILITY_SUITE := device-tests LOCAL_C_INCLUDES := bootable/recovery Loading @@ -101,6 +105,7 @@ LOCAL_SRC_FILES := \ component/sideload_test.cpp \ component/uncrypt_test.cpp \ component/updater_test.cpp \ component/update_verifier_test.cpp \ component/verifier_test.cpp LOCAL_FORCE_STATIC_EXECUTABLE := true Loading Loading @@ -128,6 +133,7 @@ LOCAL_STATIC_LIBRARIES := \ libverifier \ libotautil \ libmounts \ libupdate_verifier \ libdivsufsort \ libdivsufsort64 \ libfs_mgr \ Loading
tests/component/update_verifier_test.cpp 0 → 100644 +83 −0 Original line number Diff line number Diff line /* * 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 agreed 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 <string> #include <android-base/file.h> #include <android-base/test_utils.h> #include <gtest/gtest.h> #include <update_verifier/update_verifier.h> class UpdateVerifierTest : public ::testing::Test { protected: void SetUp() override { #ifdef PRODUCT_SUPPORTS_VERITY verity_supported = true; #else verity_supported = false; #endif } bool verity_supported; }; TEST_F(UpdateVerifierTest, verify_image_no_care_map) { // Non-existing care_map is allowed. ASSERT_TRUE(verify_image("/doesntexist")); } TEST_F(UpdateVerifierTest, verify_image_smoke) { // This test relies on dm-verity support. if (!verity_supported) { GTEST_LOG_(INFO) << "Test skipped on devices without dm-verity support."; return; } // The care map file can have only two or four lines. TemporaryFile temp_file; std::string content = "system\n2,0,1"; ASSERT_TRUE(android::base::WriteStringToFile(content, temp_file.path)); ASSERT_TRUE(verify_image(temp_file.path)); // Leading and trailing newlines should be accepted. ASSERT_TRUE(android::base::WriteStringToFile("\n" + content + "\n\n", temp_file.path)); ASSERT_TRUE(verify_image(temp_file.path)); } TEST_F(UpdateVerifierTest, verify_image_wrong_lines) { // The care map file can have only two or four lines. TemporaryFile temp_file; ASSERT_FALSE(verify_image(temp_file.path)); ASSERT_TRUE(android::base::WriteStringToFile("line1", temp_file.path)); ASSERT_FALSE(verify_image(temp_file.path)); ASSERT_TRUE(android::base::WriteStringToFile("line1\nline2\nline3", temp_file.path)); ASSERT_FALSE(verify_image(temp_file.path)); } TEST_F(UpdateVerifierTest, verify_image_malformed_care_map) { // This test relies on dm-verity support. if (!verity_supported) { GTEST_LOG_(INFO) << "Test skipped on devices without dm-verity support."; return; } TemporaryFile temp_file; std::string content = "system\n2,1,0"; ASSERT_TRUE(android::base::WriteStringToFile(content, temp_file.path)); ASSERT_FALSE(verify_image(temp_file.path)); }
update_verifier/Android.mk +34 −8 Original line number Diff line number Diff line Loading @@ -14,12 +14,43 @@ LOCAL_PATH := $(call my-dir) # libupdate_verifier (static library) # =============================== include $(CLEAR_VARS) LOCAL_CLANG := true LOCAL_SRC_FILES := update_verifier.cpp LOCAL_SRC_FILES := \ update_verifier.cpp LOCAL_MODULE := libupdate_verifier LOCAL_SHARED_LIBRARIES := \ libbase \ libcutils \ android.hardware.boot@1.0 LOCAL_CFLAGS := -Wall -Werror LOCAL_EXPORT_C_INCLUDE_DIRS := \ $(LOCAL_PATH)/include LOCAL_C_INCLUDES := \ $(LOCAL_PATH)/include ifeq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),true) LOCAL_CFLAGS += -DPRODUCT_SUPPORTS_VERITY=1 endif include $(BUILD_STATIC_LIBRARY) # update_verifier (executable) # =============================== include $(CLEAR_VARS) LOCAL_SRC_FILES := \ update_verifier_main.cpp LOCAL_MODULE := update_verifier LOCAL_STATIC_LIBRARIES := \ libupdate_verifier LOCAL_SHARED_LIBRARIES := \ libbase \ libcutils \ Loading @@ -29,13 +60,8 @@ LOCAL_SHARED_LIBRARIES := \ libhidlbase \ android.hardware.boot@1.0 LOCAL_CFLAGS := -Werror LOCAL_C_INCLUDES += $(LOCAL_PATH)/.. LOCAL_CFLAGS := -Wall -Werror LOCAL_INIT_RC := update_verifier.rc ifeq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),true) LOCAL_CFLAGS += -DPRODUCT_SUPPORTS_VERITY=1 endif include $(BUILD_EXECUTABLE)
update_verifier/include/update_verifier/update_verifier.h 0 → 100644 +24 −0 Original line number Diff line number Diff line /* * 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 agreed 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. */ #pragma once #include <string> int update_verifier(int argc, char** argv); // Exposed for testing purpose. bool verify_image(const std::string& care_map_name);
update_verifier/update_verifier.cpp +9 −8 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ * verifier reaches the end after the verification. */ #include "update_verifier/update_verifier.h" #include <dirent.h> #include <errno.h> #include <fcntl.h> Loading @@ -59,12 +61,6 @@ using android::hardware::boot::V1_0::IBootControl; using android::hardware::boot::V1_0::BoolResult; using android::hardware::boot::V1_0::CommandResult; constexpr auto CARE_MAP_FILE = "/data/ota_package/care_map.txt"; constexpr auto DM_PATH_PREFIX = "/sys/block/"; constexpr auto DM_PATH_SUFFIX = "/dm/name"; constexpr auto DEV_PATH = "/dev/block/"; constexpr int BLOCKSIZE = 4096; // Find directories in format of "/sys/block/dm-X". static int dm_name_filter(const dirent* de) { if (android::base::StartsWith(de->d_name, "dm-")) { Loading @@ -82,6 +78,7 @@ static bool read_blocks(const std::string& partition, const std::string& range_s // (or "vendor"), then dm-X is a dm-wrapped system/vendor partition. // Afterwards, update_verifier will read every block on the care_map_file of // "/dev/block/dm-X" to ensure the partition's integrity. static constexpr auto DM_PATH_PREFIX = "/sys/block/"; dirent** namelist; int n = scandir(DM_PATH_PREFIX, &namelist, dm_name_filter, alphasort); if (n == -1) { Loading @@ -93,6 +90,8 @@ static bool read_blocks(const std::string& partition, const std::string& range_s return false; } static constexpr auto DM_PATH_SUFFIX = "/dm/name"; static constexpr auto DEV_PATH = "/dev/block/"; std::string dm_block_device; while (n--) { std::string path = DM_PATH_PREFIX + std::string(namelist[n]->d_name) + DM_PATH_SUFFIX; Loading Loading @@ -143,6 +142,7 @@ static bool read_blocks(const std::string& partition, const std::string& range_s return false; } static constexpr int BLOCKSIZE = 4096; if (lseek64(fd.get(), static_cast<off64_t>(range_start) * BLOCKSIZE, SEEK_SET) == -1) { PLOG(ERROR) << "lseek to " << range_start << " failed"; return false; Loading @@ -161,7 +161,7 @@ static bool read_blocks(const std::string& partition, const std::string& range_s return true; } static bool verify_image(const std::string& care_map_name) { bool verify_image(const std::string& care_map_name) { android::base::unique_fd care_map_fd(TEMP_FAILURE_RETRY(open(care_map_name.c_str(), O_RDONLY))); // If the device is flashed before the current boot, it may not have care_map.txt // in /data/ota_package. To allow the device to continue booting in this situation, Loading Loading @@ -205,7 +205,7 @@ static int reboot_device() { while (true) pause(); } int main(int argc, char** argv) { int update_verifier(int argc, char** argv) { for (int i = 1; i < argc; i++) { LOG(INFO) << "Started with arg " << i << ": " << argv[i]; } Loading Loading @@ -238,6 +238,7 @@ int main(int argc, char** argv) { return reboot_device(); } static constexpr auto CARE_MAP_FILE = "/data/ota_package/care_map.txt"; if (!verify_image(CARE_MAP_FILE)) { LOG(ERROR) << "Failed to verify all blocks in care map file."; return reboot_device(); Loading