Merge "Error correction: Append codes to verified partitions"
This commit is contained in:
commit
87f582611a
5 changed files with 94 additions and 18 deletions
|
@ -724,6 +724,9 @@ INTERNAL_USERIMAGES_BINARY_PATHS := $(sort $(dir $(INTERNAL_USERIMAGES_DEPS)))
|
|||
|
||||
ifeq (true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY))
|
||||
INTERNAL_USERIMAGES_DEPS += $(BUILD_VERITY_TREE) $(APPEND2SIMG) $(VERITY_SIGNER)
|
||||
ifeq (true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY_FEC))
|
||||
INTERNAL_USERIMAGES_DEPS += $(FEC)
|
||||
endif
|
||||
endif
|
||||
|
||||
SELINUX_FC := $(TARGET_ROOT_OUT)/file_contexts.bin
|
||||
|
@ -754,6 +757,7 @@ $(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_BOOT_SIGNER),$(hide) echo "
|
|||
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),$(hide) echo "verity=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY)" >> $(1))
|
||||
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),$(hide) echo "verity_key=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY)" >> $(1))
|
||||
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),$(hide) echo "verity_signer_cmd=$(notdir $(VERITY_SIGNER))" >> $(1))
|
||||
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY_FEC),$(hide) echo "verity_fec=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY_FEC)" >> $(1))
|
||||
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_VERITY_PARTITION),$(hide) echo "system_verity_block_device=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_VERITY_PARTITION)" >> $(1))
|
||||
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_VERITY_PARTITION),$(hide) echo "vendor_verity_block_device=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_VERITY_PARTITION)" >> $(1))
|
||||
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT)" >> $(1))
|
||||
|
@ -1363,7 +1367,8 @@ OTATOOLS := $(HOST_OUT_EXECUTABLES)/minigzip \
|
|||
$(HOST_OUT_EXECUTABLES)/verity_signer \
|
||||
$(HOST_OUT_EXECUTABLES)/append2simg \
|
||||
$(HOST_OUT_EXECUTABLES)/img2simg \
|
||||
$(HOST_OUT_EXECUTABLES)/boot_signer
|
||||
$(HOST_OUT_EXECUTABLES)/boot_signer \
|
||||
$(HOST_OUT_EXECUTABLES)/fec
|
||||
|
||||
# Shared libraries.
|
||||
OTATOOLS += \
|
||||
|
|
|
@ -515,6 +515,7 @@ BUILD_VERITY_TREE := $(HOST_OUT_EXECUTABLES)/build_verity_tree
|
|||
BOOT_SIGNER := $(HOST_OUT_EXECUTABLES)/boot_signer
|
||||
FUTILITY := prebuilts/misc/$(BUILD_OS)-$(HOST_PREBUILT_ARCH)/futility/futility
|
||||
VBOOT_SIGNER := prebuilts/misc/scripts/vboot_signer/vboot_signer.sh
|
||||
FEC := $(HOST_OUT_EXECUTABLES)/fec
|
||||
|
||||
# ACP is always for the build OS, not for the host OS
|
||||
ACP := $(BUILD_OUT_EXECUTABLES)/acp$(BUILD_EXECUTABLE_SUFFIX)
|
||||
|
|
|
@ -100,6 +100,7 @@ _product_var_list := \
|
|||
PRODUCT_SUPPORTS_BOOT_SIGNER \
|
||||
PRODUCT_SUPPORTS_VBOOT \
|
||||
PRODUCT_SUPPORTS_VERITY \
|
||||
PRODUCT_SUPPORTS_VERITY_FEC \
|
||||
PRODUCT_OEM_PROPERTIES \
|
||||
PRODUCT_SYSTEM_PROPERTY_BLACKLIST \
|
||||
PRODUCT_SYSTEM_SERVER_JARS \
|
||||
|
|
|
@ -21,6 +21,7 @@ user_variant := $(filter user userdebug,$(TARGET_BUILD_VARIANT))
|
|||
ifneq (,$(user_variant))
|
||||
PRODUCT_SUPPORTS_BOOT_SIGNER := true
|
||||
PRODUCT_SUPPORTS_VERITY := true
|
||||
PRODUCT_SUPPORTS_VERITY_FEC := true
|
||||
|
||||
# The dev key is used to sign boot and recovery images, and the verity
|
||||
# metadata table. Actual product deliverables will be re-signed by hand.
|
||||
|
|
|
@ -33,6 +33,7 @@ import tempfile
|
|||
OPTIONS = common.OPTIONS
|
||||
|
||||
FIXED_SALT = "aee087a5be3b982978c923f566a94613496b417f2af592639bc80d141e34dfe7"
|
||||
BLOCK_SIZE = 4096
|
||||
|
||||
def RunCommand(cmd):
|
||||
"""Echo and run the given command.
|
||||
|
@ -48,6 +49,14 @@ def RunCommand(cmd):
|
|||
print "%s" % (output.rstrip(),)
|
||||
return (output, p.returncode)
|
||||
|
||||
def GetVerityFECSize(partition_size):
|
||||
cmd = "fec -s %d" % partition_size
|
||||
status, output = commands.getstatusoutput(cmd)
|
||||
if status:
|
||||
print output
|
||||
return False, 0
|
||||
return True, int(output)
|
||||
|
||||
def GetVerityTreeSize(partition_size):
|
||||
cmd = "build_verity_tree -s %d"
|
||||
cmd %= partition_size
|
||||
|
@ -67,7 +76,22 @@ def GetVerityMetadataSize(partition_size):
|
|||
return False, 0
|
||||
return True, int(output)
|
||||
|
||||
def AdjustPartitionSizeForVerity(partition_size):
|
||||
def GetVeritySize(partition_size, fec_supported):
|
||||
success, verity_tree_size = GetVerityTreeSize(partition_size)
|
||||
if not success:
|
||||
return 0
|
||||
success, verity_metadata_size = GetVerityMetadataSize(partition_size)
|
||||
if not success:
|
||||
return 0
|
||||
verity_size = verity_tree_size + verity_metadata_size
|
||||
if fec_supported:
|
||||
success, fec_size = GetVerityFECSize(partition_size + verity_size)
|
||||
if not success:
|
||||
return 0
|
||||
return verity_size + fec_size
|
||||
return verity_size
|
||||
|
||||
def AdjustPartitionSizeForVerity(partition_size, fec_supported):
|
||||
"""Modifies the provided partition size to account for the verity metadata.
|
||||
|
||||
This information is used to size the created image appropriately.
|
||||
|
@ -76,13 +100,43 @@ def AdjustPartitionSizeForVerity(partition_size):
|
|||
Returns:
|
||||
The size of the partition adjusted for verity metadata.
|
||||
"""
|
||||
success, verity_tree_size = GetVerityTreeSize(partition_size)
|
||||
if not success:
|
||||
return 0
|
||||
success, verity_metadata_size = GetVerityMetadataSize(partition_size)
|
||||
if not success:
|
||||
return 0
|
||||
return partition_size - verity_tree_size - verity_metadata_size
|
||||
key = "%d %d" % (partition_size, fec_supported)
|
||||
if key in AdjustPartitionSizeForVerity.results:
|
||||
return AdjustPartitionSizeForVerity.results[key]
|
||||
|
||||
hi = partition_size
|
||||
if hi % BLOCK_SIZE != 0:
|
||||
hi = (hi // BLOCK_SIZE) * BLOCK_SIZE
|
||||
|
||||
# verity tree and fec sizes depend on the partition size, which
|
||||
# means this estimate is always going to be unnecessarily small
|
||||
lo = partition_size - GetVeritySize(hi, fec_supported)
|
||||
result = lo
|
||||
|
||||
# do a binary search for the optimal size
|
||||
while lo < hi:
|
||||
i = ((lo + hi) // (2 * BLOCK_SIZE)) * BLOCK_SIZE
|
||||
size = i + GetVeritySize(i, fec_supported)
|
||||
if size <= partition_size:
|
||||
if result < i:
|
||||
result = i
|
||||
lo = i + BLOCK_SIZE
|
||||
else:
|
||||
hi = i
|
||||
|
||||
AdjustPartitionSizeForVerity.results[key] = result
|
||||
return result
|
||||
|
||||
AdjustPartitionSizeForVerity.results = {}
|
||||
|
||||
def BuildVerityFEC(sparse_image_path, verity_fec_path, prop_dict):
|
||||
cmd = "fec -e %s %s" % (sparse_image_path, verity_fec_path)
|
||||
print cmd
|
||||
status, output = commands.getstatusoutput(cmd)
|
||||
if status:
|
||||
print "Could not build FEC data! Error: %s" % output
|
||||
return False
|
||||
return True
|
||||
|
||||
def BuildVerityTree(sparse_image_path, verity_image_path, prop_dict):
|
||||
cmd = "build_verity_tree -A %s %s %s" % (
|
||||
|
@ -130,12 +184,12 @@ def Append2Simg(sparse_image_path, unsparse_image_path, error_message):
|
|||
|
||||
def BuildVerifiedImage(data_image_path, verity_image_path,
|
||||
verity_metadata_path):
|
||||
if not Append2Simg(data_image_path, verity_metadata_path,
|
||||
"Could not append verity metadata!"):
|
||||
return False
|
||||
if not Append2Simg(data_image_path, verity_image_path,
|
||||
"Could not append verity tree!"):
|
||||
return False
|
||||
if not Append2Simg(data_image_path, verity_metadata_path,
|
||||
"Could not append verity metadata!"):
|
||||
return False
|
||||
return True
|
||||
|
||||
def UnsparseImage(sparse_image_path, replace=True):
|
||||
|
@ -154,7 +208,7 @@ def UnsparseImage(sparse_image_path, replace=True):
|
|||
return False, None
|
||||
return True, unsparse_image_path
|
||||
|
||||
def MakeVerityEnabledImage(out_file, prop_dict):
|
||||
def MakeVerityEnabledImage(out_file, fec_supported, prop_dict):
|
||||
"""Creates an image that is verifiable using dm-verity.
|
||||
|
||||
Args:
|
||||
|
@ -180,6 +234,7 @@ def MakeVerityEnabledImage(out_file, prop_dict):
|
|||
# get partial image paths
|
||||
verity_image_path = os.path.join(tempdir_name, "verity.img")
|
||||
verity_metadata_path = os.path.join(tempdir_name, "verity_metadata.img")
|
||||
verity_fec_path = os.path.join(tempdir_name, "verity_fec.img")
|
||||
|
||||
# build the verity tree and get the root hash and salt
|
||||
if not BuildVerityTree(out_file, verity_image_path, prop_dict):
|
||||
|
@ -201,6 +256,16 @@ def MakeVerityEnabledImage(out_file, prop_dict):
|
|||
shutil.rmtree(tempdir_name, ignore_errors=True)
|
||||
return False
|
||||
|
||||
if fec_supported:
|
||||
# build FEC for the entire partition, including metadata
|
||||
if not BuildVerityFEC(out_file, verity_fec_path, prop_dict):
|
||||
shutil.rmtree(tempdir_name, ignore_errors=True)
|
||||
return False
|
||||
|
||||
if not Append2Simg(out_file, verity_fec_path, "Could not append FEC!"):
|
||||
shutil.rmtree(tempdir_name, ignore_errors=True)
|
||||
return False
|
||||
|
||||
shutil.rmtree(tempdir_name, ignore_errors=True)
|
||||
return True
|
||||
|
||||
|
@ -248,12 +313,14 @@ def BuildImage(in_dir, prop_dict, out_file, target_out=None):
|
|||
|
||||
is_verity_partition = "verity_block_device" in prop_dict
|
||||
verity_supported = prop_dict.get("verity") == "true"
|
||||
verity_fec_supported = prop_dict.get("verity_fec") == "true"
|
||||
|
||||
# Adjust the partition size to make room for the hashes if this is to be
|
||||
# verified.
|
||||
if verity_supported and is_verity_partition and fs_spans_partition:
|
||||
partition_size = int(prop_dict.get("partition_size"))
|
||||
|
||||
adjusted_size = AdjustPartitionSizeForVerity(partition_size)
|
||||
adjusted_size = AdjustPartitionSizeForVerity(partition_size,
|
||||
verity_fec_supported)
|
||||
if not adjusted_size:
|
||||
return False
|
||||
prop_dict["partition_size"] = str(adjusted_size)
|
||||
|
@ -366,7 +433,7 @@ def BuildImage(in_dir, prop_dict, out_file, target_out=None):
|
|||
"%d" % (mount_point, image_size, partition_size))
|
||||
return False
|
||||
if verity_supported and is_verity_partition:
|
||||
if 2 * image_size - AdjustPartitionSizeForVerity(image_size) > partition_size:
|
||||
if 2 * image_size - AdjustPartitionSizeForVerity(image_size, verity_fec_supported) > partition_size:
|
||||
print "Error: No more room on %s to fit verity data" % mount_point
|
||||
return False
|
||||
prop_dict["original_partition_size"] = prop_dict["partition_size"]
|
||||
|
@ -374,7 +441,7 @@ def BuildImage(in_dir, prop_dict, out_file, target_out=None):
|
|||
|
||||
# create the verified image if this is to be verified
|
||||
if verity_supported and is_verity_partition:
|
||||
if not MakeVerityEnabledImage(out_file, prop_dict):
|
||||
if not MakeVerityEnabledImage(out_file, verity_fec_supported, prop_dict):
|
||||
return False
|
||||
|
||||
if run_fsck and prop_dict.get("skip_fsck") != "true":
|
||||
|
@ -416,7 +483,8 @@ def ImagePropFromGlobalDict(glob_dict, mount_point):
|
|||
"skip_fsck",
|
||||
"verity",
|
||||
"verity_key",
|
||||
"verity_signer_cmd"
|
||||
"verity_signer_cmd",
|
||||
"verity_fec"
|
||||
)
|
||||
for p in common_props:
|
||||
copy_prop(p, p)
|
||||
|
|
Loading…
Reference in a new issue