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

Commit c819b29f authored by Kelvin Zhang's avatar Kelvin Zhang
Browse files

Always set a avb salt for hermetic build

When building images via `m` , build_image.py is invoked directly
without going through add_img_to_target_files. To ensure images built in
either way are identical, move uuid/salt computation to build_image.py,
so that the same uuid/salt will be used.

Bug: 281960439
Test: m installclean && m && m target-files-dir , maks sure images in
$OUT and $OUT/obj/PACKING/target_files_intermediates are identical

Change-Id: Icdab29df84f5a0ec7c080f99f9fdbdc3c9b10b90
parent ccf0471a
Loading
Loading
Loading
Loading
+9 −20
Original line number Diff line number Diff line
@@ -68,6 +68,7 @@ import sparse_img
from concurrent.futures import ThreadPoolExecutor
from apex_utils import GetApexInfoFromTargetFiles
from common import ZipDelete, PARTITIONS_WITH_CARE_MAP, ExternalError, RunAndCheckOutput, IsSparseImage, MakeTempFile, ZipWrite
from build_image import FIXED_FILE_TIMESTAMP

if sys.hexversion < 0x02070000:
  print("Python 2.7 or newer is required.", file=sys.stderr)
@@ -81,12 +82,6 @@ OPTIONS.rebuild_recovery = False
OPTIONS.replace_updated_files_list = []
OPTIONS.is_signing = False

# Use a fixed timestamp (01/01/2009 00:00:00 UTC) for files when packaging
# images. (b/24377993, b/80600931)
FIXED_FILE_TIMESTAMP = int((
    datetime.datetime(2009, 1, 1, 0, 0, 0, 0, None) -
    datetime.datetime.utcfromtimestamp(0)).total_seconds())


def ParseAvbFooter(img_path) -> avbtool.AvbFooter:
  with open(img_path, 'rb') as fp:
@@ -594,15 +589,6 @@ def CreateImage(input_dir, info_dict, what, output_file, block_list=None):
  if block_list:
    image_props["block_list"] = block_list.name

  # Use repeatable ext4 FS UUID and hash_seed UUID (based on partition name and
  # build fingerprint). Also use the legacy build id, because the vbmeta digest
  # isn't available at this point.
  build_info = common.BuildInfo(info_dict, use_legacy_id=True)
  uuid_seed = what + "-" + build_info.GetPartitionFingerprint(what)
  image_props["uuid"] = str(uuid.uuid5(uuid.NAMESPACE_URL, uuid_seed))
  hash_seed = "hash_seed-" + uuid_seed
  image_props["hash_seed"] = str(uuid.uuid5(uuid.NAMESPACE_URL, hash_seed))

  build_image.BuildImage(
      os.path.join(input_dir, what.upper()), image_props, output_file.name)

@@ -1144,14 +1130,18 @@ def AddImagesToTargetFiles(filename):
          item for item in vbmeta_partitions
          if item not in vbmeta_vendor.split()]
      vbmeta_partitions.append("vbmeta_vendor")
    custom_avb_partitions = OPTIONS.info_dict.get("avb_custom_vbmeta_images_partition_list", "").strip().split()
    custom_avb_partitions = OPTIONS.info_dict.get(
        "avb_custom_vbmeta_images_partition_list", "").strip().split()
    if custom_avb_partitions:
      for avb_part in custom_avb_partitions:
        partition_name = "vbmeta_" + avb_part
        included_partitions = OPTIONS.info_dict.get("avb_vbmeta_{}".format(avb_part), "").strip().split()
        assert included_partitions, "Custom vbmeta partition {0} missing avb_vbmeta_{0} prop".format(avb_part)
        included_partitions = OPTIONS.info_dict.get(
            "avb_vbmeta_{}".format(avb_part), "").strip().split()
        assert included_partitions, "Custom vbmeta partition {0} missing avb_vbmeta_{0} prop".format(
            avb_part)
        banner(partition_name)
        logger.info("VBMeta partition {} needs {}".format(partition_name, included_partitions))
        logger.info("VBMeta partition {} needs {}".format(
            partition_name, included_partitions))
        partitions[partition_name] = AddVBMeta(
            output_zip, partitions, partition_name, included_partitions)
        vbmeta_partitions = [
@@ -1159,7 +1149,6 @@ def AddImagesToTargetFiles(filename):
            if item not in included_partitions]
        vbmeta_partitions.append(partition_name)


    if OPTIONS.info_dict.get("avb_building_vbmeta_image") == "true":
      banner("vbmeta")
      AddVBMeta(output_zip, partitions, "vbmeta", vbmeta_partitions)
+42 −2
Original line number Diff line number Diff line
@@ -23,24 +23,34 @@ Usage: build_image input_directory properties_file output_image \\
"""

from __future__ import print_function
import datetime

import glob
import logging
import os
import os.path
import re
import shlex
import shutil
import sys
import uuid

import common
import verity_utils


logger = logging.getLogger(__name__)

OPTIONS = common.OPTIONS
BLOCK_SIZE = common.BLOCK_SIZE
BYTES_IN_MB = 1024 * 1024

# Use a fixed timestamp (01/01/2009 00:00:00 UTC) for files when packaging
# images. (b/24377993, b/80600931)
FIXED_FILE_TIMESTAMP = int((
    datetime.datetime(2009, 1, 1, 0, 0, 0, 0, None) -
    datetime.datetime.utcfromtimestamp(0)).total_seconds())


class BuildImageError(Exception):
  """An Exception raised during image building."""
@@ -487,6 +497,20 @@ def RunErofsFsck(out_file):
    raise


def SetUUIDIfNotExist(image_props):

  # Use repeatable ext4 FS UUID and hash_seed UUID (based on partition name and
  # build fingerprint). Also use the legacy build id, because the vbmeta digest
  # isn't available at this point.
  what = image_props["mount_point"]
  fingerprint = image_props.get("fingerprint", "")
  uuid_seed = what + "-" + fingerprint
  logger.info("Using fingerprint %s for partition %s", fingerprint, what)
  image_props["uuid"] = str(uuid.uuid5(uuid.NAMESPACE_URL, uuid_seed))
  hash_seed = "hash_seed-" + uuid_seed
  image_props["hash_seed"] = str(uuid.uuid5(uuid.NAMESPACE_URL, hash_seed))


def BuildImage(in_dir, prop_dict, out_file, target_out=None):
  """Builds an image for the files under in_dir and writes it to out_file.

@@ -504,6 +528,7 @@ def BuildImage(in_dir, prop_dict, out_file, target_out=None):
    BuildImageError: On build image failures.
  """
  in_dir, fs_config = SetUpInDirAndFsConfig(in_dir, prop_dict)
  SetUUIDIfNotExist(prop_dict)

  build_command = []
  fs_type = prop_dict.get("fs_type", "")
@@ -635,6 +660,19 @@ def BuildImage(in_dir, prop_dict, out_file, target_out=None):
    verity_image_builder.Build(out_file)


def TryParseFingerprint(glob_dict: dict):
  for (key, val) in glob_dict.items():
    if not key.endswith("_add_hashtree_footer_args") and not key.endswith("_add_hash_footer_args"):
      continue
    for arg in shlex.split(val):
      m = re.match(r"^com\.android\.build\.\w+\.fingerprint:", arg)
      if m is None:
        continue
      fingerprint = arg[len(m.group()):]
      glob_dict["fingerprint"] = fingerprint
      return


def ImagePropFromGlobalDict(glob_dict, mount_point):
  """Build an image property dictionary from the global dictionary.

@@ -643,7 +681,9 @@ def ImagePropFromGlobalDict(glob_dict, mount_point):
    mount_point: such as "system", "data" etc.
  """
  d = {}
  TryParseFingerprint(glob_dict)

  d["timestamp"] = FIXED_FILE_TIMESTAMP
  if "build.prop" in glob_dict:
    timestamp = glob_dict["build.prop"].GetProp("ro.build.date.utc")
    if timestamp:
@@ -680,6 +720,7 @@ def ImagePropFromGlobalDict(glob_dict, mount_point):
      "avb_enable",
      "avb_avbtool",
      "use_dynamic_partition_size",
      "fingerprint",
  )
  for p in common_props:
    copy_prop(p, p)
@@ -870,7 +911,6 @@ def BuildVBMeta(in_dir, glob_dict, output_path):
          if item not in vbmeta_vendor.split()]
      vbmeta_partitions.append("vbmeta_vendor")


  partitions = {part: os.path.join(in_dir, part + ".img")
                for part in vbmeta_partitions}
  partitions = {part: path for (part, path) in partitions.items() if os.path.exists(path)}
+0 −13
Original line number Diff line number Diff line
@@ -928,20 +928,7 @@ def LoadInfoDict(input_file, repacking=False):
        input_file, partition, ramdisk_format=ramdisk_format)
  d["build.prop"] = d["system.build.prop"]

  # Set up the salt (based on fingerprint) that will be used when adding AVB
  # hash / hashtree footers.
  if d.get("avb_enable") == "true":
    build_info = BuildInfo(d, use_legacy_id=True)
    for partition in PARTITIONS_WITH_BUILD_PROP:
      fingerprint = build_info.GetPartitionFingerprint(partition)
      if fingerprint:
        d["avb_{}_salt".format(partition)] = sha256(
            fingerprint.encode()).hexdigest()

    # Set up the salt for partitions without build.prop
    if build_info.fingerprint:
      d["avb_salt"] = sha256(build_info.fingerprint.encode()).hexdigest()

    # Set the vbmeta digest if exists
    try:
      d["vbmeta_digest"] = read_helper("META/vbmeta_digest.txt").rstrip()
+10 −3
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import sys
import common
import sparse_img
from rangelib import RangeSet
from hashlib import sha256

logger = logging.getLogger(__name__)

@@ -42,6 +43,7 @@ FIXED_SALT = "aee087a5be3b982978c923f566a94613496b417f2af592639bc80d141e34dfe7"
MAX_VBMETA_SIZE = 64 * 1024
MAX_FOOTER_SIZE = 4096


class BuildVerityImageError(Exception):
  """An Exception raised during verity image building."""

@@ -64,6 +66,11 @@ def CreateVerityImageBuilder(prop_dict):
  # partition_size could be None at this point, if using dynamic partitions.
  if partition_size:
    partition_size = int(partition_size)
  # Set up the salt (based on fingerprint) that will be used when adding AVB
  # hash / hashtree footers.
  salt = prop_dict.get("avb_salt")
  if salt is None:
    salt = sha256(prop_dict.get("fingerprint", "").encode()).hexdigest()

  # Verified Boot 2.0
  if (prop_dict.get("avb_hash_enable") == "true" or
@@ -81,7 +88,7 @@ def CreateVerityImageBuilder(prop_dict):
          prop_dict["avb_avbtool"],
          key_path,
          algorithm,
          prop_dict.get("avb_salt"),
          salt,
          prop_dict["avb_add_hash_footer_args"])

    # Image uses hashtree footer.
@@ -92,7 +99,7 @@ def CreateVerityImageBuilder(prop_dict):
        prop_dict["avb_avbtool"],
        key_path,
        algorithm,
        prop_dict.get("avb_salt"),
        salt,
        prop_dict["avb_add_hashtree_footer_args"])

  return None