diff --git a/android/prebuilt.go b/android/prebuilt.go index 734871b6b..294a6e080 100644 --- a/android/prebuilt.go +++ b/android/prebuilt.go @@ -93,7 +93,7 @@ func (p *Prebuilt) Prefer() bool { // more modules like this. func (p *Prebuilt) SingleSourcePath(ctx ModuleContext) Path { if p.srcsSupplier != nil { - srcs := p.srcsSupplier() + srcs := p.srcsSupplier(ctx) if len(srcs) == 0 { ctx.PropertyErrorf(p.srcsPropertyName, "missing prebuilt source file") @@ -122,7 +122,7 @@ func (p *Prebuilt) UsePrebuilt() bool { // Called to provide the srcs value for the prebuilt module. // // Return the src value or nil if it is not available. -type PrebuiltSrcsSupplier func() []string +type PrebuiltSrcsSupplier func(ctx BaseModuleContext) []string // Initialize the module as a prebuilt module that uses the provided supplier to access the // prebuilt sources of the module. @@ -156,7 +156,7 @@ func InitPrebuiltModule(module PrebuiltInterface, srcs *[]string) { panic(fmt.Errorf("srcs must not be nil")) } - srcsSupplier := func() []string { + srcsSupplier := func(ctx BaseModuleContext) []string { return *srcs } @@ -177,7 +177,7 @@ func InitSingleSourcePrebuiltModule(module PrebuiltInterface, srcProps interface srcFieldIndex := srcStructField.Index srcPropertyName := proptools.PropertyNameForField(srcField) - srcsSupplier := func() []string { + srcsSupplier := func(ctx BaseModuleContext) []string { value := srcPropsValue.FieldByIndex(srcFieldIndex) if value.Kind() == reflect.Ptr { value = value.Elem() @@ -287,7 +287,7 @@ func PrebuiltPostDepsMutator(ctx BottomUpMutatorContext) { // usePrebuilt returns true if a prebuilt should be used instead of the source module. The prebuilt // will be used if it is marked "prefer" or if the source module is disabled. func (p *Prebuilt) usePrebuilt(ctx TopDownMutatorContext, source Module) bool { - if p.srcsSupplier != nil && len(p.srcsSupplier()) == 0 { + if p.srcsSupplier != nil && len(p.srcsSupplier(ctx)) == 0 { return false } diff --git a/apex/apex_test.go b/apex/apex_test.go index cf2c9533b..006838354 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -5597,6 +5597,36 @@ func TestAppSetBundle(t *testing.T) { ensureMatches(t, copyCmds[2], "^unzip .*-d .*/app/AppSet .*/AppSet.zip$") } +func TestAppSetBundlePrebuilt(t *testing.T) { + ctx, _ := testApex(t, "", func(fs map[string][]byte, config android.Config) { + bp := ` + apex_set { + name: "myapex", + filename: "foo_v2.apex", + sanitized: { + none: { set: "myapex.apks", }, + hwaddress: { set: "myapex.hwasan.apks", }, + }, + }` + fs["Android.bp"] = []byte(bp) + + config.TestProductVariables.SanitizeDevice = []string{"hwaddress"} + }) + + m := ctx.ModuleForTests("myapex", "android_common") + extractedApex := m.Output(buildDir + "/.intermediates/myapex/android_common/foo_v2.apex") + + actual := extractedApex.Inputs + if len(actual) != 1 { + t.Errorf("expected a single input") + } + + expected := "myapex.hwasan.apks" + if actual[0].String() != expected { + t.Errorf("expected %s, got %s", expected, actual[0].String()) + } +} + func testNoUpdatableJarsInBootImage(t *testing.T, errmsg string, transformDexpreoptConfig func(*dexpreopt.GlobalConfig)) { t.Helper() diff --git a/apex/prebuilt.go b/apex/prebuilt.go index de8ff9979..f7a556100 100644 --- a/apex/prebuilt.go +++ b/apex/prebuilt.go @@ -49,6 +49,10 @@ type prebuiltCommon struct { properties prebuiltCommonProperties } +type sanitizedPrebuilt interface { + hasSanitizedSource(sanitizer string) bool +} + type prebuiltCommonProperties struct { ForceDisable bool `blueprint:"mutated"` } @@ -74,9 +78,10 @@ func (p *prebuiltCommon) checkForceDisable(ctx android.ModuleContext) bool { forceDisable = forceDisable || ctx.DeviceConfig().NativeCoverageEnabled() forceDisable = forceDisable || ctx.Config().IsEnvTrue("EMMA_INSTRUMENT") - // b/137216042 don't use prebuilts when address sanitizer is on - forceDisable = forceDisable || android.InList("address", ctx.Config().SanitizeDevice()) || - android.InList("hwaddress", ctx.Config().SanitizeDevice()) + // b/137216042 don't use prebuilts when address sanitizer is on, unless the prebuilt has a sanitized source + sanitized := ctx.Module().(sanitizedPrebuilt) + forceDisable = forceDisable || (android.InList("address", ctx.Config().SanitizeDevice()) && !sanitized.hasSanitizedSource("address")) + forceDisable = forceDisable || (android.InList("hwaddress", ctx.Config().SanitizeDevice()) && !sanitized.hasSanitizedSource("hwaddress")) if forceDisable && p.prebuilt.SourceExists() { p.properties.ForceDisable = true @@ -134,6 +139,10 @@ type PrebuiltProperties struct { Overrides []string } +func (a *Prebuilt) hasSanitizedSource(sanitizer string) bool { + return false +} + func (p *Prebuilt) installable() bool { return p.properties.Installable == nil || proptools.Bool(p.properties.Installable) } @@ -262,6 +271,18 @@ type ApexSetProperties struct { // the .apks file path that contains prebuilt apex files to be extracted. Set *string + Sanitized struct { + None struct { + Set *string + } + Address struct { + Set *string + } + Hwaddress struct { + Set *string + } + } + // whether the extracted apex file installable. Installable *bool @@ -280,6 +301,41 @@ type ApexSetProperties struct { Prerelease *bool } +func (a *ApexSet) prebuiltSrcs(ctx android.BaseModuleContext) []string { + var srcs []string + if a.properties.Set != nil { + srcs = append(srcs, *a.properties.Set) + } + + var sanitizers []string + if ctx.Host() { + sanitizers = ctx.Config().SanitizeHost() + } else { + sanitizers = ctx.Config().SanitizeDevice() + } + + if android.InList("address", sanitizers) && a.properties.Sanitized.Address.Set != nil { + srcs = append(srcs, *a.properties.Sanitized.Address.Set) + } else if android.InList("hwaddress", sanitizers) && a.properties.Sanitized.Hwaddress.Set != nil { + srcs = append(srcs, *a.properties.Sanitized.Hwaddress.Set) + } else if a.properties.Sanitized.None.Set != nil { + srcs = append(srcs, *a.properties.Sanitized.None.Set) + } + + return srcs +} + +func (a *ApexSet) hasSanitizedSource(sanitizer string) bool { + if sanitizer == "address" { + return a.properties.Sanitized.Address.Set != nil + } + if sanitizer == "hwaddress" { + return a.properties.Sanitized.Hwaddress.Set != nil + } + + return false +} + func (a *ApexSet) installable() bool { return a.properties.Installable == nil || proptools.Bool(a.properties.Installable) } @@ -300,7 +356,12 @@ func (a *ApexSet) Overrides() []string { func apexSetFactory() android.Module { module := &ApexSet{} module.AddProperties(&module.properties) - android.InitSingleSourcePrebuiltModule(module, &module.properties, "Set") + + srcsSupplier := func(ctx android.BaseModuleContext) []string { + return module.prebuiltSrcs(ctx) + } + + android.InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "set") android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) return module } diff --git a/cc/library.go b/cc/library.go index 35828aa71..f5b2b65dd 100644 --- a/cc/library.go +++ b/cc/library.go @@ -121,7 +121,10 @@ type SharedProperties struct { } type StaticOrSharedProperties struct { - Srcs []string `android:"path,arch_variant"` + Srcs []string `android:"path,arch_variant"` + + Sanitized Sanitized `android:"arch_variant"` + Cflags []string `android:"arch_variant"` Enabled *bool `android:"arch_variant"` diff --git a/cc/prebuilt.go b/cc/prebuilt.go index 9d1b01608..e8d3422e8 100644 --- a/cc/prebuilt.go +++ b/cc/prebuilt.go @@ -38,10 +38,11 @@ type prebuiltLinkerInterface interface { } type prebuiltLinkerProperties struct { - // a prebuilt library or binary. Can reference a genrule module that generates an executable file. Srcs []string `android:"path,arch_variant"` + Sanitized Sanitized `android:"arch_variant"` + // Check the prebuilt ELF files (e.g. DT_SONAME, DT_NEEDED, resolution of undefined // symbols, etc), default true. Check_elf_files *bool @@ -105,7 +106,7 @@ func (p *prebuiltLibraryLinker) link(ctx ModuleContext, p.libraryDecorator.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...) // TODO(ccross): verify shared library dependencies - srcs := p.prebuiltSrcs() + srcs := p.prebuiltSrcs(ctx) if len(srcs) > 0 { builderFlags := flagsToBuilderFlags(flags) @@ -177,15 +178,18 @@ func (p *prebuiltLibraryLinker) link(ctx ModuleContext, return nil } -func (p *prebuiltLibraryLinker) prebuiltSrcs() []string { +func (p *prebuiltLibraryLinker) prebuiltSrcs(ctx android.BaseModuleContext) []string { + sanitize := ctx.Module().(*Module).sanitize srcs := p.properties.Srcs + srcs = append(srcs, srcsForSanitizer(sanitize, p.properties.Sanitized)...) if p.static() { srcs = append(srcs, p.libraryDecorator.StaticProperties.Static.Srcs...) + srcs = append(srcs, srcsForSanitizer(sanitize, p.libraryDecorator.StaticProperties.Static.Sanitized)...) } if p.shared() { srcs = append(srcs, p.libraryDecorator.SharedProperties.Shared.Srcs...) + srcs = append(srcs, srcsForSanitizer(sanitize, p.libraryDecorator.SharedProperties.Shared.Sanitized)...) } - return srcs } @@ -212,8 +216,8 @@ func NewPrebuiltLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDec module.AddProperties(&prebuilt.properties) - srcsSupplier := func() []string { - return prebuilt.prebuiltSrcs() + srcsSupplier := func(ctx android.BaseModuleContext) []string { + return prebuilt.prebuiltSrcs(ctx) } android.InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "srcs") @@ -425,3 +429,28 @@ func NewPrebuiltBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecor android.InitPrebuiltModule(module, &prebuilt.properties.Srcs) return module, binary } + +type Sanitized struct { + None struct { + Srcs []string `android:"path,arch_variant"` + } `android:"arch_variant"` + Address struct { + Srcs []string `android:"path,arch_variant"` + } `android:"arch_variant"` + Hwaddress struct { + Srcs []string `android:"path,arch_variant"` + } `android:"arch_variant"` +} + +func srcsForSanitizer(sanitize *sanitize, sanitized Sanitized) []string { + if sanitize == nil { + return nil + } + if Bool(sanitize.Properties.Sanitize.Address) && sanitized.Address.Srcs != nil { + return sanitized.Address.Srcs + } + if Bool(sanitize.Properties.Sanitize.Hwaddress) && sanitized.Hwaddress.Srcs != nil { + return sanitized.Hwaddress.Srcs + } + return sanitized.None.Srcs +} diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go index 52416ac3b..1f070a508 100644 --- a/cc/prebuilt_test.go +++ b/cc/prebuilt_test.go @@ -23,7 +23,7 @@ import ( "github.com/google/blueprint" ) -func testPrebuilt(t *testing.T, bp string, fs map[string][]byte) *android.TestContext { +func testPrebuilt(t *testing.T, bp string, fs map[string][]byte, handlers ...configCustomizer) *android.TestContext { config := TestConfig(buildDir, android.Android, nil, bp, fs) ctx := CreateTestContext() @@ -34,6 +34,10 @@ func testPrebuilt(t *testing.T, bp string, fs map[string][]byte) *android.TestCo android.RegisterAndroidMkBuildComponents(ctx) android.SetInMakeForTests(config) + for _, handler := range handlers { + handler(config) + } + ctx.Register(config) _, errs := ctx.ParseFileList(".", []string{"Android.bp"}) android.FailIfErrored(t, errs) @@ -42,6 +46,8 @@ func testPrebuilt(t *testing.T, bp string, fs map[string][]byte) *android.TestCo return ctx } +type configCustomizer func(config android.Config) + func TestPrebuilt(t *testing.T) { bp := ` cc_library { @@ -321,3 +327,62 @@ func TestPrebuiltSymlinkedHostBinary(t *testing.T) { assertString(t, libfooDep.String(), filepath.Join(buildDir, ".intermediates/libfoo/linux_glibc_x86_64_shared/libfoo.so")) } + +func TestPrebuiltLibrarySanitized(t *testing.T) { + bp := `cc_prebuilt_library { + name: "libtest", + static: { + sanitized: { none: { srcs: ["libf.a"], }, hwaddress: { srcs: ["libf.hwasan.a"], }, }, + }, + shared: { + sanitized: { none: { srcs: ["libf.so"], }, hwaddress: { srcs: ["hwasan/libf.so"], }, }, + }, + } + cc_prebuilt_library_static { + name: "libtest_static", + sanitized: { none: { srcs: ["libf.a"], }, hwaddress: { srcs: ["libf.hwasan.a"], }, }, + } + cc_prebuilt_library_shared { + name: "libtest_shared", + sanitized: { none: { srcs: ["libf.so"], }, hwaddress: { srcs: ["hwasan/libf.so"], }, }, + }` + + fs := map[string][]byte{ + "libf.a": nil, + "libf.hwasan.a": nil, + "libf.so": nil, + "hwasan/libf.so": nil, + } + + // Without SANITIZE_TARGET. + ctx := testPrebuilt(t, bp, fs) + + shared_rule := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Rule("android/soong/cc.strip") + assertString(t, shared_rule.Input.String(), "libf.so") + + static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module) + assertString(t, static.OutputFile().Path().Base(), "libf.a") + + shared_rule2 := ctx.ModuleForTests("libtest_shared", "android_arm64_armv8-a_shared").Rule("android/soong/cc.strip") + assertString(t, shared_rule2.Input.String(), "libf.so") + + static2 := ctx.ModuleForTests("libtest_static", "android_arm64_armv8-a_static").Module().(*Module) + assertString(t, static2.OutputFile().Path().Base(), "libf.a") + + // With SANITIZE_TARGET=hwaddress + ctx = testPrebuilt(t, bp, fs, func(config android.Config) { + config.TestProductVariables.SanitizeDevice = []string{"hwaddress"} + }) + + shared_rule = ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared_hwasan").Rule("android/soong/cc.strip") + assertString(t, shared_rule.Input.String(), "hwasan/libf.so") + + static = ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static_hwasan").Module().(*Module) + assertString(t, static.OutputFile().Path().Base(), "libf.hwasan.a") + + shared_rule2 = ctx.ModuleForTests("libtest_shared", "android_arm64_armv8-a_shared_hwasan").Rule("android/soong/cc.strip") + assertString(t, shared_rule2.Input.String(), "hwasan/libf.so") + + static2 = ctx.ModuleForTests("libtest_static", "android_arm64_armv8-a_static_hwasan").Module().(*Module) + assertString(t, static2.OutputFile().Path().Base(), "libf.hwasan.a") +}