Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit edadcdb1 authored by Cory Barker's avatar Cory Barker Committed by Gerrit Code Review
Browse files

Merge "Updated the way we build AFL++ fuzz binaries"

parents 8e77db3b cecb7546
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -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()

+28 −31
Original line number Diff line number Diff line
@@ -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
+32 −86
Original line number Diff line number Diff line
@@ -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,17 +121,15 @@ 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
}
}

func (fuzz *fuzzBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags {
	flags = fuzz.binaryDecorator.linkerFlags(ctx, 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
		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.AFLEnabled = true
		module.compiler.appendCflags([]string{
			"-Wno-unused-result",
			"-Wno-unused-parameter",
			"-Wno-unused-function",
		})
			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})
+0 −2
Original line number Diff line number Diff line
@@ -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)
+68 −10
Original line number Diff line number Diff line
@@ -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)