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
This commit is contained in:
Jooyung Han 2022-04-21 14:24:04 +09:00
parent e3db7f6d38
commit 65f402b780
2 changed files with 40 additions and 1 deletions

View file

@ -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())

View file

@ -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 <target> <name>".
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))
}