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:
@@ -228,6 +228,15 @@ func (b *bootimg) signImage(ctx android.ModuleContext, unsignedImage android.Out
|
|||||||
return output
|
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) {
|
func (b *bootimg) buildPropFile(ctx android.ModuleContext) (propFile android.OutputPath, toolDeps android.Paths) {
|
||||||
var sb strings.Builder
|
var sb strings.Builder
|
||||||
var deps android.Paths
|
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
|
addStr("avb_add_hash_footer_args", "") // TODO(jiyong): add --rollback_index
|
||||||
partitionName := proptools.StringDefault(b.properties.Partition_name, b.Name())
|
partitionName := proptools.StringDefault(b.properties.Partition_name, b.Name())
|
||||||
addStr("partition_name", partitionName)
|
addStr("partition_name", partitionName)
|
||||||
|
addStr("avb_salt", b.salt())
|
||||||
|
|
||||||
propFile = android.PathForModuleOut(ctx, "prop").OutputPath
|
propFile = android.PathForModuleOut(ctx, "prop").OutputPath
|
||||||
android.WriteFileRule(ctx, propFile, sb.String())
|
android.WriteFileRule(ctx, propFile, sb.String())
|
||||||
|
@@ -15,7 +15,9 @@
|
|||||||
package filesystem
|
package filesystem
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -88,6 +90,13 @@ type filesystemProperties struct {
|
|||||||
|
|
||||||
// Symbolic links to be created under root with "ln -sf <target> <name>".
|
// Symbolic links to be created under root with "ln -sf <target> <name>".
|
||||||
Symlinks []symlinkDefinition
|
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
|
// 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
|
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) {
|
func (f *filesystem) buildPropFile(ctx android.ModuleContext) (propFile android.OutputPath, toolDeps android.Paths) {
|
||||||
type prop struct {
|
type prop struct {
|
||||||
name string
|
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")
|
addStr("avb_add_hashtree_footer_args", "--do_not_generate_fec")
|
||||||
partitionName := proptools.StringDefault(f.properties.Partition_name, f.Name())
|
partitionName := proptools.StringDefault(f.properties.Partition_name, f.Name())
|
||||||
addStr("partition_name", partitionName)
|
addStr("partition_name", partitionName)
|
||||||
|
addStr("avb_salt", f.salt())
|
||||||
}
|
}
|
||||||
|
|
||||||
if proptools.String(f.properties.File_contexts) != "" {
|
if proptools.String(f.properties.File_contexts) != "" {
|
||||||
addPath("selinux_fc", f.buildFileContexts(ctx))
|
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
|
propFile = android.PathForModuleOut(ctx, "prop").OutputPath
|
||||||
builder := android.NewRuleBuilder(pctx, ctx)
|
builder := android.NewRuleBuilder(pctx, ctx)
|
||||||
builder.Command().Text("rm").Flag("-rf").Output(propFile)
|
builder.Command().Text("rm").Flag("-rf").Output(propFile)
|
||||||
@@ -451,3 +472,11 @@ func (f *filesystem) gatherFilteredPackagingSpecs(ctx android.ModuleContext) map
|
|||||||
}
|
}
|
||||||
return specs
|
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))
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user