diff --git a/cc/cc.go b/cc/cc.go index bc958134f..fd57e9e59 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -62,7 +62,6 @@ func RegisterCCBuildComponents(ctx android.RegistrationContext) { ctx.BottomUp("sanitize_runtime", sanitizerRuntimeMutator).Parallel() ctx.TopDown("fuzz_deps", fuzzMutatorDeps) - ctx.BottomUp("fuzz", fuzzMutator) ctx.BottomUp("coverage", coverageMutator).Parallel() diff --git a/cc/cc_test.go b/cc/cc_test.go index 24732bf7d..ac1a49fd8 100644 --- a/cc/cc_test.go +++ b/cc/cc_test.go @@ -3343,8 +3343,8 @@ func TestErrorsIfAModuleDependsOnDisabled(t *testing.T) { } func TestAFLFuzzTarget(t *testing.T) { - ctx := testCc(t, ` - cc_afl_fuzz { + bp := ` + cc_fuzz { name: "test_afl_fuzz_target", srcs: ["foo.c"], host_supported: true, @@ -3354,17 +3354,10 @@ func TestAFLFuzzTarget(t *testing.T) { shared_libs: [ "afl_fuzz_shared_lib", ], - } - cc_fuzz { - name: "test_fuzz_target", - srcs: ["foo.c"], - static_libs: [ - "afl_fuzz_static_lib", - "libfuzzer_only_static_lib", - ], - shared_libs: [ - "afl_fuzz_shared_lib", - ], + fuzzing_frameworks: { + afl: true, + libfuzzer: false, + }, } cc_library { name: "afl_fuzz_static_lib", @@ -3409,12 +3402,19 @@ func TestAFLFuzzTarget(t *testing.T) { host_supported: true, srcs: ["second_file.c"], } - filegroup { + cc_object { name: "aflpp_driver", + host_supported: true, srcs: [ "aflpp_driver.c", ], - }`) + }` + + testEnv := map[string]string{ + "FUZZ_FRAMEWORK": "AFL", + } + + ctx := android.GroupFixturePreparers(prepareForCcTest, android.FixtureMergeEnv(testEnv)).RunTestWithBp(t, bp) checkPcGuardFlag := func( modName string, variantName string, shouldHave bool) { @@ -3434,31 +3434,28 @@ func TestAFLFuzzTarget(t *testing.T) { } } - for _, vnt := range ctx.ModuleVariantsForTests("libfuzzer_only_static_lib") { - if strings.Contains(vnt, "fuzzer_afl") { - t.Errorf("libfuzzer_only_static_lib has afl variant and should not") - } - } - moduleName := "test_afl_fuzz_target" - variantName := "android_arm64_armv8-a_fuzzer_afl" - checkPcGuardFlag(moduleName, variantName, true) + hostVariant := "linux_glibc_x86_64" + armVariant := "android_arm64_armv8-a" + checkPcGuardFlag(moduleName, armVariant+"_fuzzer", true) + checkPcGuardFlag(moduleName, hostVariant+"_fuzzer", true) moduleName = "afl_fuzz_static_lib" - variantName = "android_arm64_armv8-a_static" - checkPcGuardFlag(moduleName, variantName, false) - checkPcGuardFlag(moduleName, variantName+"_fuzzer", false) - checkPcGuardFlag(moduleName, variantName+"_fuzzer_afl", true) + checkPcGuardFlag(moduleName, armVariant+"_static", false) + checkPcGuardFlag(moduleName, armVariant+"_static_fuzzer", true) + checkPcGuardFlag(moduleName, hostVariant+"_static", false) + checkPcGuardFlag(moduleName, hostVariant+"_static_fuzzer", true) moduleName = "second_static_lib" - checkPcGuardFlag(moduleName, variantName, false) - checkPcGuardFlag(moduleName, variantName+"_fuzzer", false) - checkPcGuardFlag(moduleName, variantName+"_fuzzer_afl", true) + checkPcGuardFlag(moduleName, armVariant+"_static", false) + checkPcGuardFlag(moduleName, armVariant+"_static_fuzzer", true) + checkPcGuardFlag(moduleName, hostVariant+"_static", false) + checkPcGuardFlag(moduleName, hostVariant+"_static_fuzzer", true) ctx.ModuleForTests("afl_fuzz_shared_lib", "android_arm64_armv8-a_shared").Rule("cc") ctx.ModuleForTests("afl_fuzz_shared_lib", - "android_arm64_armv8-a_shared_fuzzer_afl").Rule("cc") + "android_arm64_armv8-a_shared_fuzzer").Rule("cc") } // Simple smoke test for the cc_fuzz target that ensures the rule compiles diff --git a/cc/fuzz.go b/cc/fuzz.go index d6af97f6d..dfc718e85 100644 --- a/cc/fuzz.go +++ b/cc/fuzz.go @@ -27,15 +27,12 @@ import ( ) func init() { - android.RegisterModuleType("cc_afl_fuzz", AFLFuzzFactory) android.RegisterModuleType("cc_fuzz", LibFuzzFactory) android.RegisterSingletonType("cc_fuzz_packaging", fuzzPackagingFactory) - android.RegisterSingletonType("cc_afl_fuzz_packaging", fuzzAFLPackagingFactory) } type FuzzProperties struct { - AFLEnabled bool `blueprint:"mutated"` - AFLAddFlags bool `blueprint:"mutated"` + FuzzFramework fuzz.Framework `blueprint:"mutated"` } type fuzzer struct { @@ -43,8 +40,13 @@ type fuzzer struct { } func (fuzzer *fuzzer) flags(ctx ModuleContext, flags Flags) Flags { - if fuzzer.Properties.AFLAddFlags { - flags.Local.CFlags = append(flags.Local.CFlags, "-fsanitize-coverage=trace-pc-guard") + if fuzzer.Properties.FuzzFramework == fuzz.AFL { + flags.Local.CFlags = append(flags.Local.CFlags, []string{ + "-fsanitize-coverage=trace-pc-guard", + "-Wno-unused-result", + "-Wno-unused-parameter", + "-Wno-unused-function", + }...) } return flags @@ -60,7 +62,7 @@ func fuzzMutatorDeps(mctx android.TopDownMutatorContext) { return } - if currentModule.fuzzer == nil || !currentModule.fuzzer.Properties.AFLEnabled { + if currentModule.fuzzer == nil { return } @@ -83,48 +85,16 @@ func fuzzMutatorDeps(mctx android.TopDownMutatorContext) { return false } - c.fuzzer.Properties.AFLEnabled = true - c.fuzzer.Properties.AFLAddFlags = true + c.fuzzer.Properties.FuzzFramework = currentModule.fuzzer.Properties.FuzzFramework return true }) } -func fuzzMutator(mctx android.BottomUpMutatorContext) { - if c, ok := mctx.Module().(*Module); ok && c.fuzzer != nil { - if !c.fuzzer.Properties.AFLEnabled { - return - } - - if c.Binary() { - m := mctx.CreateVariations("afl") - m[0].(*Module).fuzzer.Properties.AFLEnabled = true - m[0].(*Module).fuzzer.Properties.AFLAddFlags = true - } else { - m := mctx.CreateVariations("", "afl") - m[0].(*Module).fuzzer.Properties.AFLEnabled = false - m[0].(*Module).fuzzer.Properties.AFLAddFlags = false - - m[1].(*Module).fuzzer.Properties.AFLEnabled = true - m[1].(*Module).fuzzer.Properties.AFLAddFlags = true - } - } -} - // cc_fuzz creates a host/device fuzzer binary. Host binaries can be found at // $ANDROID_HOST_OUT/fuzz/, and device binaries can be found at /data/fuzz on // your device, or $ANDROID_PRODUCT_OUT/data/fuzz in your build tree. func LibFuzzFactory() android.Module { - module := NewFuzzer(android.HostAndDeviceSupported, fuzz.Cc) - return module.Init() -} - -// cc_afl_fuzz creates a host/device AFL++ fuzzer binary. -// AFL++ is an open source framework used to fuzz libraries -// Host binaries can be found at $ANDROID_HOST_OUT/afl_fuzz/ and device -// binaries can be found at $ANDROID_PRODUCT_OUT/data/afl_fuzz in your -// build tree -func AFLFuzzFactory() android.Module { - module := NewFuzzer(android.HostAndDeviceSupported, fuzz.AFL) + module := NewFuzzer(android.HostAndDeviceSupported) return module.Init() } @@ -133,7 +103,6 @@ type fuzzBinary struct { *baseCompiler fuzzPackagedModule fuzz.FuzzPackagedModule installedSharedDeps []string - fuzzType fuzz.FuzzType } func (fuzz *fuzzBinary) fuzzBinary() bool { @@ -143,6 +112,7 @@ func (fuzz *fuzzBinary) fuzzBinary() bool { func (fuzz *fuzzBinary) linkerProps() []interface{} { props := fuzz.binaryDecorator.linkerProps() props = append(props, &fuzz.fuzzPackagedModule.FuzzProperties) + return props } @@ -151,16 +121,14 @@ func (fuzz *fuzzBinary) linkerInit(ctx BaseModuleContext) { } func (fuzzBin *fuzzBinary) linkerDeps(ctx DepsContext, deps Deps) Deps { - if fuzzBin.fuzzType == fuzz.AFL { + if ctx.Config().Getenv("FUZZ_FRAMEWORK") == "AFL" { deps.HeaderLibs = append(deps.HeaderLibs, "libafl_headers") - deps = fuzzBin.binaryDecorator.linkerDeps(ctx, deps) - return deps - } else { deps.StaticLibs = append(deps.StaticLibs, config.LibFuzzerRuntimeLibrary(ctx.toolchain())) - deps = fuzzBin.binaryDecorator.linkerDeps(ctx, deps) - return deps } + + deps = fuzzBin.binaryDecorator.linkerDeps(ctx, deps) + return deps } func (fuzz *fuzzBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags { @@ -257,9 +225,6 @@ func sharedLibrarySymbolsInstallLocation(libraryPath android.Path, fuzzDir strin func (fuzzBin *fuzzBinary) install(ctx ModuleContext, file android.Path) { installBase := "fuzz" - if fuzzBin.fuzzType == fuzz.AFL { - installBase = "afl_fuzz" - } fuzzBin.binaryDecorator.baseInstaller.dir = filepath.Join( installBase, ctx.Target().Arch.ArchType.String(), ctx.ModuleName()) @@ -333,12 +298,9 @@ func (fuzzBin *fuzzBinary) install(ctx ModuleContext, file android.Path) { } } -func NewFuzzer(hod android.HostOrDeviceSupported, fuzzType fuzz.FuzzType) *Module { +func NewFuzzer(hod android.HostOrDeviceSupported) *Module { module, binary := newBinary(hod, false) baseInstallerPath := "fuzz" - if fuzzType == fuzz.AFL { - baseInstallerPath = "afl_fuzz" - } binary.baseInstaller = NewBaseInstaller(baseInstallerPath, baseInstallerPath, InstallInData) module.sanitize.SetSanitizer(Fuzzer, true) @@ -346,12 +308,13 @@ func NewFuzzer(hod android.HostOrDeviceSupported, fuzzType fuzz.FuzzType) *Modul fuzzBin := &fuzzBinary{ binaryDecorator: binary, baseCompiler: NewBaseCompiler(), - fuzzType: fuzzType, } module.compiler = fuzzBin module.linker = fuzzBin module.installer = fuzzBin + module.fuzzer.Properties.FuzzFramework = fuzz.LibFuzzer + // The fuzzer runtime is not present for darwin host modules, disable cc_fuzz modules when targeting darwin. android.AddLoadHook(module, func(ctx android.LoadHookContext) { disableDarwinAndLinuxBionic := struct { @@ -367,18 +330,18 @@ func NewFuzzer(hod android.HostOrDeviceSupported, fuzzType fuzz.FuzzType) *Modul disableDarwinAndLinuxBionic.Target.Darwin.Enabled = BoolPtr(false) disableDarwinAndLinuxBionic.Target.Linux_bionic.Enabled = BoolPtr(false) ctx.AppendProperties(&disableDarwinAndLinuxBionic) - }) - if fuzzType == fuzz.AFL { - // Add cc_objects to Srcs - fuzzBin.baseCompiler.Properties.Srcs = append(fuzzBin.baseCompiler.Properties.Srcs, ":aflpp_driver", ":afl-compiler-rt") - module.fuzzer.Properties.AFLEnabled = true - module.compiler.appendCflags([]string{ - "-Wno-unused-result", - "-Wno-unused-parameter", - "-Wno-unused-function", - }) - } + targetFramework := fuzz.GetFramework(ctx, fuzz.Cc) + if !fuzz.IsValidFrameworkForModule(targetFramework, fuzz.Cc, fuzzBin.fuzzPackagedModule.FuzzProperties.Fuzzing_frameworks) { + ctx.Module().Disable() + return + } + + if targetFramework == fuzz.AFL { + fuzzBin.baseCompiler.Properties.Srcs = append(fuzzBin.baseCompiler.Properties.Srcs, ":aflpp_driver", ":afl-compiler-rt") + module.fuzzer.Properties.FuzzFramework = fuzz.AFL + } + }) return module } @@ -399,17 +362,6 @@ func fuzzPackagingFactory() android.Singleton { fuzzTargetSharedDepsInstallPairs: "FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS", allFuzzTargetsName: "ALL_FUZZ_TARGETS", } - fuzzPackager.FuzzType = fuzz.Cc - return fuzzPackager -} - -func fuzzAFLPackagingFactory() android.Singleton { - fuzzPackager := &ccFuzzPackager{ - fuzzPackagingArchModules: "SOONG_AFL_FUZZ_PACKAGING_ARCH_MODULES", - fuzzTargetSharedDepsInstallPairs: "AFL_FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS", - allFuzzTargetsName: "ALL_AFL_FUZZ_TARGETS", - } - fuzzPackager.FuzzType = fuzz.AFL return fuzzPackager } @@ -440,7 +392,7 @@ func (s *ccFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) { sharedLibsInstallDirPrefix := "lib" fuzzModule, ok := ccModule.compiler.(*fuzzBinary) - if !ok || fuzzModule.fuzzType != s.FuzzType { + if !ok { return } @@ -455,9 +407,6 @@ func (s *ccFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) { } intermediatePath := "fuzz" - if s.FuzzType == fuzz.AFL { - intermediatePath = "afl_fuzz" - } archString := ccModule.Arch().ArchType.String() archDir := android.PathForIntermediates(ctx, intermediatePath, hostOrTargetString, archString) @@ -484,7 +433,7 @@ func (s *ccFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) { } }) - s.CreateFuzzPackage(ctx, archDirs, s.FuzzType, pctx) + s.CreateFuzzPackage(ctx, archDirs, fuzz.Cc, pctx) } func (s *ccFuzzPackager) MakeVars(ctx android.MakeVarsContext) { @@ -511,9 +460,6 @@ func GetSharedLibsToZip(sharedLibraries android.Paths, module LinkableInterface, var files []fuzz.FileToZip fuzzDir := "fuzz" - if s.FuzzType == fuzz.AFL { - fuzzDir = "afl_fuzz" - } for _, library := range sharedLibraries { files = append(files, fuzz.FileToZip{library, destinationPathPrefix}) diff --git a/cc/testing.go b/cc/testing.go index d70ec9bb5..79ae3c3ae 100644 --- a/cc/testing.go +++ b/cc/testing.go @@ -531,7 +531,6 @@ var PrepareForTestWithCcBuildComponents = android.GroupFixturePreparers( android.FixtureRegisterWithContext(RegisterRequiredBuildComponentsForTest), android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) { ctx.RegisterModuleType("cc_fuzz", LibFuzzFactory) - ctx.RegisterModuleType("cc_afl_fuzz", AFLFuzzFactory) ctx.RegisterModuleType("cc_test", TestFactory) ctx.RegisterModuleType("cc_test_library", TestLibraryFactory) ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory) @@ -646,7 +645,6 @@ func CreateTestContext(config android.Config) *android.TestContext { ctx := android.NewTestArchContext(config) genrule.RegisterGenruleBuildComponents(ctx) ctx.RegisterModuleType("cc_fuzz", LibFuzzFactory) - ctx.RegisterModuleType("cc_afl_fuzz", AFLFuzzFactory) ctx.RegisterModuleType("cc_test", TestFactory) ctx.RegisterModuleType("cc_test_library", TestLibraryFactory) ctx.RegisterModuleType("filegroup", android.FileGroupFactory) diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go index 2474cbc9e..c8cd21b7e 100644 --- a/fuzz/fuzz_common.go +++ b/fuzz/fuzz_common.go @@ -27,13 +27,21 @@ import ( "android/soong/android" ) -type FuzzType string +type Lang string const ( - Cc FuzzType = "" - Rust FuzzType = "rust" - Java FuzzType = "java" - AFL FuzzType = "AFL" + Cc Lang = "cc" + Rust Lang = "rust" + Java Lang = "java" +) + +type Framework string + +const ( + AFL Framework = "afl" + LibFuzzer Framework = "libfuzzer" + Jazzer Framework = "jazzer" + UnknownFramework Framework = "unknownframework" ) var BoolDefault = proptools.BoolDefault @@ -48,7 +56,6 @@ type FuzzPackager struct { Packages android.Paths FuzzTargets map[string]bool SharedLibInstallStrings []string - FuzzType FuzzType } type FileToZip struct { @@ -146,6 +153,12 @@ type FuzzConfig struct { IsJni *bool `json:"is_jni,omitempty"` } +type FuzzFrameworks struct { + Afl *bool + Libfuzzer *bool + Jazzer *bool +} + type FuzzProperties struct { // Optional list of seed files to be installed to the fuzz target's output // directory. @@ -155,6 +168,10 @@ type FuzzProperties struct { Data []string `android:"path"` // Optional dictionary to be installed to the fuzz target's output directory. Dictionary *string `android:"path"` + // Define the fuzzing frameworks this fuzz target can be built for. If + // empty then the fuzz target will be available to be built for all fuzz + // frameworks available + Fuzzing_frameworks *FuzzFrameworks // Config for running the target on fuzzing infrastructure. Fuzz_config *FuzzConfig } @@ -169,6 +186,49 @@ type FuzzPackagedModule struct { DataIntermediateDir android.Path } +func GetFramework(ctx android.LoadHookContext, lang Lang) Framework { + framework := ctx.Config().Getenv("FUZZ_FRAMEWORK") + + if lang == Cc { + switch strings.ToLower(framework) { + case "": + return LibFuzzer + case "libfuzzer": + return LibFuzzer + case "afl": + return AFL + } + } else if lang == Rust { + return LibFuzzer + } else if lang == Java { + return Jazzer + } + + ctx.ModuleErrorf(fmt.Sprintf("%s is not a valid fuzzing framework for %s", framework, lang)) + return UnknownFramework +} + +func IsValidFrameworkForModule(targetFramework Framework, lang Lang, moduleFrameworks *FuzzFrameworks) bool { + if targetFramework == UnknownFramework { + return false + } + + if moduleFrameworks == nil { + return true + } + + switch targetFramework { + case LibFuzzer: + return proptools.BoolDefault(moduleFrameworks.Libfuzzer, true) + case AFL: + return proptools.BoolDefault(moduleFrameworks.Afl, true) + case Jazzer: + return proptools.BoolDefault(moduleFrameworks.Jazzer, true) + default: + panic("%s is not supported as a fuzz framework") + } +} + func IsValid(fuzzModule FuzzModule) bool { // Discard ramdisk + vendor_ramdisk + recovery modules, they're duplicates of // fuzz targets we're going to package anyway. @@ -267,7 +327,7 @@ func (f *FuzzConfig) String() string { return string(b) } -func (s *FuzzPackager) CreateFuzzPackage(ctx android.SingletonContext, archDirs map[ArchOs][]FileToZip, fuzzType FuzzType, pctx android.PackageContext) { +func (s *FuzzPackager) CreateFuzzPackage(ctx android.SingletonContext, archDirs map[ArchOs][]FileToZip, fuzzType Lang, pctx android.PackageContext) { var archOsList []ArchOs for archOs := range archDirs { archOsList = append(archOsList, archOs) @@ -286,9 +346,7 @@ func (s *FuzzPackager) CreateFuzzPackage(ctx android.SingletonContext, archDirs if fuzzType == Java { zipFileName = "fuzz-java-" + hostOrTarget + "-" + arch + ".zip" } - if fuzzType == AFL { - zipFileName = "fuzz-afl-" + hostOrTarget + "-" + arch + ".zip" - } + outputFile := android.PathForOutput(ctx, zipFileName) s.Packages = append(s.Packages, outputFile)