1// Copyright 2021 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package fuzz 16 17// This file contains the common code for compiling C/C++ and Rust fuzzers for Android. 18 19import ( 20 "encoding/json" 21 "fmt" 22 "sort" 23 "strings" 24 25 "github.com/google/blueprint" 26 "github.com/google/blueprint/proptools" 27 28 "android/soong/android" 29) 30 31type Lang string 32 33const ( 34 Cc Lang = "cc" 35 Rust Lang = "rust" 36 Java Lang = "java" 37) 38 39type Framework string 40 41const ( 42 AFL Framework = "afl" 43 LibFuzzer Framework = "libfuzzer" 44 Jazzer Framework = "jazzer" 45 UnknownFramework Framework = "unknownframework" 46) 47 48func (f Framework) Variant() string { 49 switch f { 50 case AFL: 51 return "afl" 52 case LibFuzzer: 53 return "libfuzzer" 54 case Jazzer: 55 return "jazzer" 56 default: 57 panic(fmt.Errorf("unknown fuzzer %q when getting variant", f)) 58 } 59} 60 61func FrameworkFromVariant(v string) Framework { 62 switch v { 63 case "afl": 64 return AFL 65 case "libfuzzer": 66 return LibFuzzer 67 case "jazzer": 68 return Jazzer 69 default: 70 panic(fmt.Errorf("unknown variant %q when getting fuzzer", v)) 71 } 72} 73 74var BoolDefault = proptools.BoolDefault 75 76type FuzzModule struct { 77 android.ModuleBase 78 android.DefaultableModuleBase 79 android.ApexModuleBase 80} 81 82type FuzzPackager struct { 83 Packages android.Paths 84 FuzzTargets map[string]bool 85 SharedLibInstallStrings []string 86} 87 88type FileToZip struct { 89 SourceFilePath android.Path 90 DestinationPathPrefix string 91 DestinationPath string 92} 93 94type ArchOs struct { 95 HostOrTarget string 96 Arch string 97 Dir string 98} 99 100type Vector string 101 102const ( 103 unknown_access_vector Vector = "unknown_access_vector" 104 // The code being fuzzed is reachable from a remote source, or using data 105 // provided by a remote source. For example: media codecs process media files 106 // from the internet, SMS processing handles remote message data. 107 // See 108 // https://source.android.com/docs/security/overview/updates-resources#local-vs-remote 109 // for an explanation of what's considered "remote." 110 remote = "remote" 111 // The code being fuzzed can only be reached locally, such as from an 112 // installed app. As an example, if it's fuzzing a Binder interface, it's 113 // assumed that you'd need a local app to make arbitrary Binder calls. 114 // And the app that's calling the fuzzed code does not require any privileges; 115 // any 3rd party app could make these calls. 116 local_no_privileges_required = "local_no_privileges_required" 117 // The code being fuzzed can only be called locally, and the calling process 118 // requires additional permissions that prevent arbitrary 3rd party apps from 119 // calling the code. For instance: this requires a privileged or signature 120 // permission to reach, or SELinux restrictions prevent the untrusted_app 121 // domain from calling it. 122 local_privileges_required = "local_privileges_required" 123 // The code is only callable on a PC host, not on a production Android device. 124 // For instance, this is fuzzing code used during the build process, or 125 // tooling that does not exist on a user's actual Android device. 126 host_access = "host_access" 127 // The code being fuzzed is only reachable if the user has enabled Developer 128 // Options, or has enabled a persistent Developer Options setting. 129 local_with_developer_options = "local_with_developer_options" 130) 131 132func (vector Vector) isValidVector() bool { 133 switch vector { 134 case "", 135 unknown_access_vector, 136 remote, 137 local_no_privileges_required, 138 local_privileges_required, 139 host_access, 140 local_with_developer_options: 141 return true 142 } 143 return false 144} 145 146type ServicePrivilege string 147 148const ( 149 unknown_service_privilege ServicePrivilege = "unknown_service_privilege" 150 // The code being fuzzed runs on a Secure Element. This has access to some 151 // of the most privileged data on the device, such as authentication keys. 152 // Not all devices have a Secure Element. 153 secure_element = "secure_element" 154 // The code being fuzzed runs in the TEE. The TEE is designed to be resistant 155 // to a compromised kernel, and stores sensitive data. 156 trusted_execution = "trusted_execution" 157 // The code being fuzzed has privileges beyond what arbitrary 3rd party apps 158 // have. For instance, it's running as the System UID, or it's in an SELinux 159 // domain that's able to perform calls that can't be made by 3rd party apps. 160 privileged = "privileged" 161 // The code being fuzzed is equivalent to a 3rd party app. It runs in the 162 // untrusted_app SELinux domain, or it only has privileges that are equivalent 163 // to what a 3rd party app could have. 164 unprivileged = "unprivileged" 165 // The code being fuzzed is significantly constrained, and even if it's 166 // compromised, it has significant restrictions that prevent it from 167 // performing most actions. This is significantly more restricted than 168 // UNPRIVILEGED. An example is the isolatedProcess=true setting in a 3rd 169 // party app. Or a process that's very restricted by SELinux, such as 170 // anything in the mediacodec SELinux domain. 171 constrained = "constrained" 172 // The code being fuzzed always has Negligible Security Impact. Even 173 // arbitrary out of bounds writes and full code execution would not be 174 // considered a security vulnerability. This typically only makes sense if 175 // FuzzedCodeUsage is set to FUTURE_VERSION or EXPERIMENTAL, and if 176 // AutomaticallyRouteTo is set to ALWAYS_NSI. 177 nsi = "nsi" 178 // The code being fuzzed only runs on a PC host, not on a production Android 179 // device. For instance, the fuzzer is fuzzing code used during the build 180 // process, or tooling that does not exist on a user's actual Android device. 181 host_only = "host_only" 182) 183 184func (service_privilege ServicePrivilege) isValidServicePrivilege() bool { 185 switch service_privilege { 186 case "", 187 unknown_service_privilege, 188 secure_element, 189 trusted_execution, 190 privileged, 191 unprivileged, 192 constrained, 193 nsi, 194 host_only: 195 return true 196 } 197 return false 198} 199 200type UsePlatformLibs string 201 202const ( 203 unknown_use_platform_libs UsePlatformLibs = "unknown_use_platform_libs" 204 // Use the native libraries on the device, typically in /system directory 205 use_platform_libs = "use_platform_libs" 206 // Do not use any native libraries (ART will not be initialized) 207 use_none = "use_none" 208) 209 210func (use_platform_libs UsePlatformLibs) isValidUsePlatformLibs() bool { 211 switch use_platform_libs { 212 case "", 213 unknown_use_platform_libs, 214 use_platform_libs, 215 use_none: 216 return true 217 } 218 return false 219} 220 221type UserData string 222 223const ( 224 unknown_user_data UserData = "unknown_user_data" 225 // The process being fuzzed only handles data from a single user, or from a 226 // single process or app. It's possible the process shuts down before 227 // handling data from another user/process/app, or it's possible the process 228 // only ever handles one user's/process's/app's data. As an example, some 229 // print spooler processes are started for a single document and terminate 230 // when done, so each instance only handles data from a single user/app. 231 single_user = "single_user" 232 // The process handles data from multiple users, or from multiple other apps 233 // or processes. Media processes, for instance, can handle media requests 234 // from multiple different apps without restarting. Wi-Fi and network 235 // processes handle data from multiple users, and processes, and apps. 236 multi_user = "multi_user" 237) 238 239func (user_data UserData) isValidUserData() bool { 240 switch user_data { 241 case "", 242 unknown_user_data, 243 single_user, 244 multi_user: 245 return true 246 } 247 return false 248} 249 250type FuzzedCodeUsage string 251 252const ( 253 undefined FuzzedCodeUsage = "undefined" 254 unknown = "unknown" 255 // The code being fuzzed exists in a shipped version of Android and runs on 256 // devices in production. 257 shipped = "shipped" 258 // The code being fuzzed is not yet in a shipping version of Android, but it 259 // will be at some point in the future. 260 future_version = "future_version" 261 // The code being fuzzed is not in a shipping version of Android, and there 262 // are no plans to ship it in the future. 263 experimental = "experimental" 264) 265 266func (fuzzed_code_usage FuzzedCodeUsage) isValidFuzzedCodeUsage() bool { 267 switch fuzzed_code_usage { 268 case "", 269 undefined, 270 unknown, 271 shipped, 272 future_version, 273 experimental: 274 return true 275 } 276 return false 277} 278 279type AutomaticallyRouteTo string 280 281const ( 282 undefined_routing AutomaticallyRouteTo = "undefined_routing" 283 // Automatically route this to the Android Automotive security team for 284 // assessment. 285 android_automotive = "android_automotive" 286 // This should not be used in fuzzer configurations. It is used internally 287 // by Severity Assigner to flag memory leak reports. 288 memory_leak = "memory_leak" 289 // Route this vulnerability to our Ittiam vendor team for assessment. 290 ittiam = "ittiam" 291 // Reports from this fuzzer are always NSI (see the NSI ServicePrivilegeEnum 292 // value for additional context). It is not possible for this code to ever 293 // have a security vulnerability. 294 always_nsi = "always_nsi" 295 // Route this vulnerability to AIDL team for assessment. 296 aidl = "aidl" 297) 298 299func (automatically_route_to AutomaticallyRouteTo) isValidAutomaticallyRouteTo() bool { 300 switch automatically_route_to { 301 case "", 302 undefined_routing, 303 android_automotive, 304 memory_leak, 305 ittiam, 306 always_nsi, 307 aidl: 308 return true 309 } 310 return false 311} 312 313func IsValidConfig(fuzzModule *FuzzPackagedModuleInfo, moduleName string) bool { 314 var config = fuzzModule.FuzzConfig 315 if config != nil { 316 if !config.Vector.isValidVector() { 317 panic(fmt.Errorf("Invalid vector in fuzz config in %s", moduleName)) 318 } 319 320 if !config.ServicePrivilege.isValidServicePrivilege() { 321 panic(fmt.Errorf("Invalid service_privilege in fuzz config in %s", moduleName)) 322 } 323 324 if !config.Users.isValidUserData() { 325 panic(fmt.Errorf("Invalid users (user_data) in fuzz config in %s", moduleName)) 326 } 327 328 if !config.FuzzedCodeUsage.isValidFuzzedCodeUsage() { 329 panic(fmt.Errorf("Invalid fuzzed_code_usage in fuzz config in %s", moduleName)) 330 } 331 332 if !config.AutomaticallyRouteTo.isValidAutomaticallyRouteTo() { 333 panic(fmt.Errorf("Invalid automatically_route_to in fuzz config in %s", moduleName)) 334 } 335 336 if !config.UsePlatformLibs.isValidUsePlatformLibs() { 337 panic(fmt.Errorf("Invalid use_platform_libs in fuzz config in %s", moduleName)) 338 } 339 } 340 return true 341} 342 343type FuzzConfig struct { 344 // Email address of people to CC on bugs or contact about this fuzz target. 345 Cc []string `json:"cc,omitempty"` 346 // A brief description of what the fuzzed code does. 347 Description string `json:"description,omitempty"` 348 // Whether the code being fuzzed is remotely accessible or requires privileges 349 // to access locally. 350 Vector Vector `json:"vector,omitempty"` 351 // How privileged the service being fuzzed is. 352 Service_privilege ServicePrivilege `json:"service_privilege,omitempty"` 353 // Whether the service being fuzzed handles data from multiple users or only 354 // a single one. 355 Users UserData `json:"users,omitempty"` 356 // Specifies the use state of the code being fuzzed. This state factors into 357 // how an issue is handled. 358 Fuzzed_code_usage FuzzedCodeUsage `json:"fuzzed_code_usage,omitempty"` 359 // Comment describing how we came to these settings for this fuzzer. 360 Config_comment string 361 // Which team to route this to, if it should be routed automatically. 362 Automatically_route_to AutomaticallyRouteTo `json:"automatically_route_to,omitempty"` 363 // Can third party/untrusted apps supply data to fuzzed code. 364 Untrusted_data *bool `json:"untrusted_data,omitempty"` 365 // When code was released or will be released. 366 Production_date string `json:"production_date,omitempty"` 367 // Prevents critical service functionality like phone calls, bluetooth, etc. 368 Critical *bool `json:"critical,omitempty"` 369 // Specify whether to enable continuous fuzzing on devices. Defaults to true. 370 Fuzz_on_haiku_device *bool `json:"fuzz_on_haiku_device,omitempty"` 371 // Specify whether to enable continuous fuzzing on host. Defaults to true. 372 Fuzz_on_haiku_host *bool `json:"fuzz_on_haiku_host,omitempty"` 373 // Component in Google's bug tracking system that bugs should be filed to. 374 Componentid *int64 `json:"componentid,omitempty"` 375 // Hotlist(s) in Google's bug tracking system that bugs should be marked with. 376 Hotlists []string `json:"hotlists,omitempty"` 377 // Specify whether this fuzz target was submitted by a researcher. Defaults 378 // to false. 379 Researcher_submitted *bool `json:"researcher_submitted,omitempty"` 380 // Specify who should be acknowledged for CVEs in the Android Security 381 // Bulletin. 382 Acknowledgement []string `json:"acknowledgement,omitempty"` 383 // Additional options to be passed to libfuzzer when run in Haiku. 384 Libfuzzer_options []string `json:"libfuzzer_options,omitempty"` 385 // Additional options to be passed to HWASAN when running on-device in Haiku. 386 Hwasan_options []string `json:"hwasan_options,omitempty"` 387 // Additional options to be passed to HWASAN when running on host in Haiku. 388 Asan_options []string `json:"asan_options,omitempty"` 389 // If there's a Java fuzzer with JNI, a different version of Jazzer would 390 // need to be added to the fuzzer package than one without JNI 391 IsJni *bool `json:"is_jni,omitempty"` 392 // List of modules for monitoring coverage drops in directories (e.g. "libicu") 393 Target_modules []string `json:"target_modules,omitempty"` 394 // Specifies a bug assignee to replace default ISE assignment 395 Triage_assignee string `json:"triage_assignee,omitempty"` 396 // Specifies libs used to initialize ART (java only, 'use_none' for no initialization) 397 Use_platform_libs UsePlatformLibs `json:"use_platform_libs,omitempty"` 398 // Specifies whether fuzz target should check presubmitted code changes for crashes. 399 // Defaults to false. 400 Use_for_presubmit *bool `json:"use_for_presubmit,omitempty"` 401 // Specify which paths to exclude from fuzzing coverage reports 402 Exclude_paths_from_reports []string `json:"exclude_paths_from_reports,omitempty"` 403} 404 405type FuzzFrameworks struct { 406 Afl *bool 407 Libfuzzer *bool 408 Jazzer *bool 409} 410 411type FuzzProperties struct { 412 // Optional list of seed files to be installed to the fuzz target's output 413 // directory. 414 Corpus []string `android:"path"` 415 416 // Same as corpus, but adds dependencies on module references using the device's os variant 417 // and the common arch variant. 418 Device_common_corpus []string `android:"path_device_common"` 419 420 // Optional list of data files to be installed to the fuzz target's output 421 // directory. Directory structure relative to the module is preserved. 422 Data []string `android:"path"` 423 // Same as data, but adds dependencies on modules using the device's os variant, and common 424 // architecture's variant. Can be useful to add device-built apps to the data of a host 425 // test. 426 Device_common_data []string `android:"path_device_common"` 427 // Same as data, but adds dependencies on modules using the device's os variant, and the 428 // device's first architecture's variant. Can be useful to add device-built apps to the data 429 // of a host test. 430 Device_first_data []string `android:"path_device_first"` 431 432 // Same as data, but will add dependencies on modules using the host's os variation and 433 // the common arch variation. Useful for a device test that wants to depend on a host 434 // module, for example to include a custom Tradefed test runner. 435 Host_common_data []string `android:"path_host_common"` 436 437 // Optional dictionary to be installed to the fuzz target's output directory. 438 Dictionary *string `android:"path"` 439 // Define the fuzzing frameworks this fuzz target can be built for. If 440 // empty then the fuzz target will be available to be built for all fuzz 441 // frameworks available 442 Fuzzing_frameworks *FuzzFrameworks 443 // Config for running the target on fuzzing infrastructure. 444 Fuzz_config *FuzzConfig 445} 446 447type FuzzPackagedModule struct { 448 FuzzProperties FuzzProperties 449 Dictionary android.Path 450 Corpus android.Paths 451 Config android.Path 452 Data android.Paths 453} 454 455type FuzzConfigInfo struct { 456 Vector Vector 457 // How privileged the service being fuzzed is. 458 ServicePrivilege ServicePrivilege 459 // Whether the service being fuzzed handles data from multiple users or only 460 // a single one. 461 Users UserData 462 // Specifies the use state of the code being fuzzed. This state factors into 463 // how an issue is handled. 464 FuzzedCodeUsage FuzzedCodeUsage 465 // Which team to route this to, if it should be routed automatically. 466 AutomaticallyRouteTo AutomaticallyRouteTo 467 // Specifies libs used to initialize ART (java only, 'use_none' for no initialization) 468 UsePlatformLibs UsePlatformLibs 469 // Specify whether to enable continuous fuzzing on devices. Defaults to true. 470 FuzzOnHaikuDevice bool 471 // Specify whether to enable continuous fuzzing on host. Defaults to true. 472 FuzzOnHaikuHost bool 473 // Specifies whether fuzz target should check presubmitted code changes for crashes. 474 // Defaults to false. 475 UseForPresubmit bool 476} 477type FuzzPackagedModuleInfo struct { 478 FuzzConfig *FuzzConfigInfo 479 Dictionary android.Path 480 Corpus android.Paths 481 Config android.Path 482 Data android.Paths 483} 484 485var FuzzPackagedModuleInfoProvider = blueprint.NewProvider[FuzzPackagedModuleInfo]() 486 487func SetFuzzPackagedModuleInfo(ctx android.ModuleContext, fm *FuzzPackagedModule) { 488 info := FuzzPackagedModuleInfo{ 489 Dictionary: fm.Dictionary, 490 Config: fm.Config, 491 Corpus: fm.Corpus, 492 Data: fm.Data, 493 } 494 if fm.FuzzProperties.Fuzz_config != nil { 495 info.FuzzConfig = &FuzzConfigInfo{ 496 Vector: fm.FuzzProperties.Fuzz_config.Vector, 497 ServicePrivilege: fm.FuzzProperties.Fuzz_config.Service_privilege, 498 Users: fm.FuzzProperties.Fuzz_config.Users, 499 FuzzedCodeUsage: fm.FuzzProperties.Fuzz_config.Fuzzed_code_usage, 500 AutomaticallyRouteTo: fm.FuzzProperties.Fuzz_config.Automatically_route_to, 501 FuzzOnHaikuDevice: BoolDefault(fm.FuzzProperties.Fuzz_config.Fuzz_on_haiku_device, true), 502 FuzzOnHaikuHost: BoolDefault(fm.FuzzProperties.Fuzz_config.Fuzz_on_haiku_host, true), 503 UsePlatformLibs: fm.FuzzProperties.Fuzz_config.Use_platform_libs, 504 UseForPresubmit: BoolDefault(fm.FuzzProperties.Fuzz_config.Use_for_presubmit, false), 505 } 506 } 507 508 android.SetProvider(ctx, FuzzPackagedModuleInfoProvider, info) 509} 510 511func GetFramework(ctx android.LoadHookContext, lang Lang) Framework { 512 framework := ctx.Config().Getenv("FUZZ_FRAMEWORK") 513 514 if lang == Cc { 515 switch strings.ToLower(framework) { 516 case "": 517 return LibFuzzer 518 case "libfuzzer": 519 return LibFuzzer 520 case "afl": 521 return AFL 522 } 523 } else if lang == Rust { 524 return LibFuzzer 525 } else if lang == Java { 526 return Jazzer 527 } 528 529 ctx.ModuleErrorf(fmt.Sprintf("%s is not a valid fuzzing framework for %s", framework, lang)) 530 return UnknownFramework 531} 532 533func IsValidFrameworkForModule(targetFramework Framework, lang Lang, moduleFrameworks *FuzzFrameworks) bool { 534 if targetFramework == UnknownFramework { 535 return false 536 } 537 538 if moduleFrameworks == nil { 539 return true 540 } 541 542 switch targetFramework { 543 case LibFuzzer: 544 return proptools.BoolDefault(moduleFrameworks.Libfuzzer, true) 545 case AFL: 546 return proptools.BoolDefault(moduleFrameworks.Afl, true) 547 case Jazzer: 548 return proptools.BoolDefault(moduleFrameworks.Jazzer, true) 549 default: 550 panic("%s is not supported as a fuzz framework") 551 } 552} 553 554func IsValid(ctx android.ConfigurableEvaluatorContext, fuzzModule FuzzModule) bool { 555 // Discard ramdisk + vendor_ramdisk + recovery modules, they're duplicates of 556 // fuzz targets we're going to package anyway. 557 if !fuzzModule.Enabled(ctx) || fuzzModule.InRamdisk() || fuzzModule.InVendorRamdisk() || fuzzModule.InRecovery() { 558 return false 559 } 560 561 // Discard modules that are in an unavailable namespace. 562 if !fuzzModule.ExportedToMake() { 563 return false 564 } 565 566 return true 567} 568 569// TODO(b/397766191): Change the signature to take ModuleProxy 570// Please only access the module's internal data through providers. 571func (s *FuzzPackager) PackageArtifacts(ctx android.SingletonContext, module android.Module, fuzzModule *FuzzPackagedModuleInfo, archDir android.OutputPath, builder *android.RuleBuilder) []FileToZip { 572 // Package the corpora into a zipfile. 573 var files []FileToZip 574 if fuzzModule.Corpus != nil { 575 corpusZip := archDir.Join(ctx, module.Name()+"_seed_corpus.zip") 576 command := builder.Command().BuiltTool("soong_zip"). 577 Flag("-j"). 578 FlagWithOutput("-o ", corpusZip) 579 rspFile := corpusZip.ReplaceExtension(ctx, "rsp") 580 command.FlagWithRspFileInputList("-r ", rspFile, fuzzModule.Corpus) 581 files = append(files, FileToZip{SourceFilePath: corpusZip}) 582 } 583 584 // Package the data into a zipfile. 585 if fuzzModule.Data != nil { 586 dataZip := archDir.Join(ctx, module.Name()+"_data.zip") 587 command := builder.Command().BuiltTool("soong_zip"). 588 FlagWithOutput("-o ", dataZip) 589 for _, f := range fuzzModule.Data { 590 intermediateDir := strings.TrimSuffix(f.String(), f.Rel()) 591 command.FlagWithArg("-C ", intermediateDir) 592 command.FlagWithInput("-f ", f) 593 } 594 files = append(files, FileToZip{SourceFilePath: dataZip}) 595 } 596 597 // The dictionary. 598 if fuzzModule.Dictionary != nil { 599 files = append(files, FileToZip{SourceFilePath: fuzzModule.Dictionary}) 600 } 601 602 // Additional fuzz config. 603 if fuzzModule.Config != nil && IsValidConfig(fuzzModule, module.Name()) { 604 files = append(files, FileToZip{SourceFilePath: fuzzModule.Config}) 605 } 606 607 return files 608} 609 610// TODO(b/397766191): Change the signature to take ModuleProxy 611// Please only access the module's internal data through providers. 612func (s *FuzzPackager) BuildZipFile(ctx android.SingletonContext, module android.Module, fuzzModule *FuzzPackagedModuleInfo, files []FileToZip, builder *android.RuleBuilder, archDir android.OutputPath, archString string, hostOrTargetString string, archOs ArchOs, archDirs map[ArchOs][]FileToZip) ([]FileToZip, bool) { 613 fuzzZip := archDir.Join(ctx, module.Name()+".zip") 614 615 command := builder.Command().BuiltTool("soong_zip"). 616 Flag("-j"). 617 FlagWithOutput("-o ", fuzzZip) 618 619 for _, file := range files { 620 if file.DestinationPathPrefix != "" { 621 command.FlagWithArg("-P ", file.DestinationPathPrefix) 622 } else { 623 command.Flag("-P ''") 624 } 625 if file.DestinationPath != "" { 626 command.FlagWithArg("-e ", file.DestinationPath) 627 } 628 command.FlagWithInput("-f ", file.SourceFilePath) 629 } 630 631 builder.Build("create-"+fuzzZip.String(), 632 "Package "+module.Name()+" for "+archString+"-"+hostOrTargetString) 633 634 if config := fuzzModule.FuzzConfig; config != nil { 635 if strings.Contains(hostOrTargetString, "host") && !config.FuzzOnHaikuHost { 636 return archDirs[archOs], false 637 } else if !strings.Contains(hostOrTargetString, "host") && !config.FuzzOnHaikuDevice { 638 return archDirs[archOs], false 639 } 640 } 641 642 s.FuzzTargets[module.Name()] = true 643 archDirs[archOs] = append(archDirs[archOs], FileToZip{SourceFilePath: fuzzZip}) 644 645 return archDirs[archOs], true 646} 647 648func (f *FuzzConfig) String() string { 649 b, err := json.Marshal(f) 650 if err != nil { 651 panic(err) 652 } 653 654 return string(b) 655} 656 657func (s *FuzzPackager) CreateFuzzPackage(ctx android.SingletonContext, archDirs map[ArchOs][]FileToZip, fuzzType Lang, pctx android.PackageContext) { 658 var archOsList []ArchOs 659 for archOs := range archDirs { 660 archOsList = append(archOsList, archOs) 661 } 662 sort.Slice(archOsList, func(i, j int) bool { return archOsList[i].Dir < archOsList[j].Dir }) 663 664 for _, archOs := range archOsList { 665 filesToZip := archDirs[archOs] 666 arch := archOs.Arch 667 hostOrTarget := archOs.HostOrTarget 668 builder := android.NewRuleBuilder(pctx, ctx) 669 zipFileName := "fuzz-" + hostOrTarget + "-" + arch + ".zip" 670 if fuzzType == Rust { 671 zipFileName = "fuzz-rust-" + hostOrTarget + "-" + arch + ".zip" 672 } 673 if fuzzType == Java { 674 zipFileName = "fuzz-java-" + hostOrTarget + "-" + arch + ".zip" 675 } 676 677 outputFile := android.PathForOutput(ctx, zipFileName) 678 679 s.Packages = append(s.Packages, outputFile) 680 681 command := builder.Command().BuiltTool("soong_zip"). 682 Flag("-j"). 683 FlagWithOutput("-o ", outputFile). 684 Flag("-L 0") // No need to try and re-compress the zipfiles. 685 686 for _, fileToZip := range filesToZip { 687 if fileToZip.DestinationPathPrefix != "" { 688 command.FlagWithArg("-P ", fileToZip.DestinationPathPrefix) 689 } else { 690 command.Flag("-P ''") 691 } 692 command.FlagWithInput("-f ", fileToZip.SourceFilePath) 693 694 } 695 builder.Build("create-fuzz-package-"+arch+"-"+hostOrTarget, 696 "Create fuzz target packages for "+arch+"-"+hostOrTarget) 697 } 698} 699 700func (s *FuzzPackager) PreallocateSlice(ctx android.MakeVarsContext, targets string) { 701 fuzzTargets := make([]string, 0, len(s.FuzzTargets)) 702 for target, _ := range s.FuzzTargets { 703 fuzzTargets = append(fuzzTargets, target) 704 } 705 706 sort.Strings(fuzzTargets) 707 ctx.Strict(targets, strings.Join(fuzzTargets, " ")) 708} 709