Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d8c078d2 authored by Tao Bao's avatar Tao Bao Committed by android-build-merger
Browse files

Merge "Separate libupdate_verifier module and add testcases."

am: c99bb239

Change-Id: Idfcde607838bbcae2930fbcc9108756296f4ca34
parents 74812187 c99bb239
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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
@@ -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
@@ -128,6 +133,7 @@ LOCAL_STATIC_LIBRARIES := \
    libverifier \
    libotautil \
    libmounts \
    libupdate_verifier \
    libdivsufsort \
    libdivsufsort64 \
    libfs_mgr \
+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));
}
+34 −8
Original line number Diff line number Diff line
@@ -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 \
@@ -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)
+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);
+9 −8
Original line number Diff line number Diff line
@@ -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>
@@ -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-")) {
@@ -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) {
@@ -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;
@@ -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;
@@ -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,
@@ -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];
  }
@@ -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