From 65f402b7809b14063b1e7705ae0b4fae6b060c36 Mon Sep 17 00:00:00 2001 From: Jooyung Han Date: Thu, 21 Apr 2022 14:24:04 +0900 Subject: [PATCH] Support deterministic output for bootimg/filesystem Adding salt to bootimg/filesystem so that avbtool can produce the same output with same input. Adding timestamp/uuid to filesystem so that resulting image can be deterministic. Bug: 229784558 Test: m com.android.virt # remove intermediates and touch some sources m com.android.virt # compare two built artifacts Change-Id: I4e4668fd0ac42a35bea5a33ec3ae8c362b6a6bd2 --- filesystem/bootimg.go | 10 ++++++++++ filesystem/filesystem.go | 31 ++++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/filesystem/bootimg.go b/filesystem/bootimg.go index 33beb37bf..352b45178 100644 --- a/filesystem/bootimg.go +++ b/filesystem/bootimg.go @@ -228,6 +228,15 @@ func (b *bootimg) signImage(ctx android.ModuleContext, unsignedImage android.Out return output } +// Calculates avb_salt from some input for deterministic output. +func (b *bootimg) salt() string { + var input []string + input = append(input, b.properties.Cmdline...) + input = append(input, proptools.StringDefault(b.properties.Partition_name, b.Name())) + input = append(input, proptools.String(b.properties.Header_version)) + return sha1sum(input) +} + func (b *bootimg) buildPropFile(ctx android.ModuleContext) (propFile android.OutputPath, toolDeps android.Paths) { var sb strings.Builder var deps android.Paths @@ -248,6 +257,7 @@ func (b *bootimg) buildPropFile(ctx android.ModuleContext) (propFile android.Out addStr("avb_add_hash_footer_args", "") // TODO(jiyong): add --rollback_index partitionName := proptools.StringDefault(b.properties.Partition_name, b.Name()) addStr("partition_name", partitionName) + addStr("avb_salt", b.salt()) propFile = android.PathForModuleOut(ctx, "prop").OutputPath android.WriteFileRule(ctx, propFile, sb.String()) diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go index ccf9e9d3b..6e1e78a69 100644 --- a/filesystem/filesystem.go +++ b/filesystem/filesystem.go @@ -15,7 +15,9 @@ package filesystem import ( + "crypto/sha256" "fmt" + "io" "path/filepath" "strings" @@ -88,6 +90,13 @@ type filesystemProperties struct { // Symbolic links to be created under root with "ln -sf ". Symlinks []symlinkDefinition + + // Seconds since unix epoch to override timestamps of file entries + Fake_timestamp *string + + // When set, passed to mkuserimg_mke2fs --mke2fs_uuid & --mke2fs_hash_seed. + // Otherwise, they'll be set as random which might cause indeterministic build output. + Uuid *string } // android_filesystem packages a set of modules and their transitive dependencies into a filesystem @@ -276,6 +285,11 @@ func (f *filesystem) buildFileContexts(ctx android.ModuleContext) android.Output return fcBin.OutputPath } +// Calculates avb_salt from entry list (sorted) for deterministic output. +func (f *filesystem) salt() string { + return sha1sum(f.entries) +} + func (f *filesystem) buildPropFile(ctx android.ModuleContext) (propFile android.OutputPath, toolDeps android.Paths) { type prop struct { name string @@ -321,12 +335,19 @@ func (f *filesystem) buildPropFile(ctx android.ModuleContext) (propFile android. addStr("avb_add_hashtree_footer_args", "--do_not_generate_fec") partitionName := proptools.StringDefault(f.properties.Partition_name, f.Name()) addStr("partition_name", partitionName) + addStr("avb_salt", f.salt()) } if proptools.String(f.properties.File_contexts) != "" { addPath("selinux_fc", f.buildFileContexts(ctx)) } - + if timestamp := proptools.String(f.properties.Fake_timestamp); timestamp != "" { + addStr("timestamp", timestamp) + } + if uuid := proptools.String(f.properties.Uuid); uuid != "" { + addStr("uuid", uuid) + addStr("hash_seed", uuid) + } propFile = android.PathForModuleOut(ctx, "prop").OutputPath builder := android.NewRuleBuilder(pctx, ctx) builder.Command().Text("rm").Flag("-rf").Output(propFile) @@ -451,3 +472,11 @@ func (f *filesystem) gatherFilteredPackagingSpecs(ctx android.ModuleContext) map } return specs } + +func sha1sum(values []string) string { + h := sha256.New() + for _, value := range values { + io.WriteString(h, value) + } + return fmt.Sprintf("%x", h.Sum(nil)) +}