[build][fuzzing] Allow fuzzers to customize sandbox
fxrev.dev/428892 removed the unused `cmx` property from the `fuzzer()`
template, but in some cases a fuzzer still needs to request specific
features and services in its sandbox. This CL addresses that by adding
back narrowly-scoped `features` and `services` properties to the
template.
Additionally, an `example-fuzzers/extended_sandbox` fuzzer is added as a
basic test for this feature.
Test: fx test extended_sandbox_test
Change-Id: Ia594e26390cc6b0abf96813c670dbf20dd67f268
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/450935
Reviewed-by: Aaron Green <aarongreen@google.com>
Testability-Review: Aaron Green <aarongreen@google.com>
Commit-Queue: Cameron Finucane <eep@google.com>
diff --git a/build/fuzzing/fuzzer.gni b/build/fuzzing/fuzzer.gni
index c5a4178d..ff6bff7 100644
--- a/build/fuzzing/fuzzer.gni
+++ b/build/fuzzing/fuzzer.gni
@@ -44,6 +44,9 @@
# [file] If specified, a file containing quoted inputs, one per line, that the fuzzer will use
# to generate new mutations.
#
+# features, services (optional)
+# [list of strings] Extra (v1) sandbox features/services for the fuzzer and test components.
+#
# options (optional)
# [list of strings] Each option is of the form "key=value" and indicates command line options
# that the fuzzer should be invoked with. Valid keys are libFuzzer options
@@ -82,8 +85,10 @@
exclude_from_mass_forwards = [
"corpus",
"dictionary",
+ "features",
"options",
"output_name",
+ "services",
"target_name",
"visibility",
]
@@ -131,7 +136,9 @@
fuzzer_component(component_target) {
forward_variables_from(invoker,
[
+ "features",
"options",
+ "services",
"visibility",
])
fuzzer = fuzzer_name
@@ -155,7 +162,9 @@
fuzzer_test_component(test_component_target) {
forward_variables_from(invoker,
[
+ "features",
"corpus",
+ "services",
"visibility",
])
fuzzer = fuzzer_name
diff --git a/build/fuzzing/fuzzer_component.gni b/build/fuzzing/fuzzer_component.gni
index aa47c12..4da7cae 100644
--- a/build/fuzzing/fuzzer_component.gni
+++ b/build/fuzzing/fuzzer_component.gni
@@ -28,6 +28,9 @@
# includes the fuzzer binary. It may also include the fuzzer corpus and dictionary, when
# present.
#
+# features, services (optional)
+# [list of strings] Extra (v1) sandbox features/services for the fuzzer and test components.
+#
# options (optional)
# [list of strings] Key-value pairs representing libFuzzer options, e.g. "foo=bar". See
# See https://llvm.org/docs/LibFuzzer.html#options.
@@ -51,11 +54,22 @@
args += [ "-$option" ]
}
}
- services = [
+ forward_variables_from(invoker,
+ [
+ "features",
+ "services",
+ ])
+ if (!defined(features)) {
+ features = []
+ }
+ if (!defined(services)) {
+ services = []
+ }
+ services += [
"fuchsia.logger.LogSink",
"fuchsia.process.Launcher",
]
- features = [
+ features += [
"isolated-persistent-storage",
"isolated-temp",
]
diff --git a/build/fuzzing/fuzzer_test_component.gni b/build/fuzzing/fuzzer_test_component.gni
index acfcf9a..64ff6be 100644
--- a/build/fuzzing/fuzzer_test_component.gni
+++ b/build/fuzzing/fuzzer_test_component.gni
@@ -30,6 +30,9 @@
# [label] If present, includes program arguments in the component manifest
# to use the corpus when testing.
#
+# features, services (optional)
+# [list of strings] Extra (v1) sandbox features/services for the fuzzer and test components.
+#
template("fuzzer_test_component") {
assert(defined(invoker.fuzzer),
"missing 'fuzzer' for fuzzer_test_component($target_name)")
@@ -54,8 +57,19 @@
args += [ "pkg/data/" + rebase_path(corpus_path, "//") ]
}
args += [ "data/corpus" ]
- services = [ "fuchsia.logger.LogSink" ]
- features = [ "isolated-persistent-storage" ]
+ forward_variables_from(invoker,
+ [
+ "features",
+ "services",
+ ])
+ if (!defined(features)) {
+ features = []
+ }
+ if (!defined(services)) {
+ services = []
+ }
+ services += [ "fuchsia.logger.LogSink" ]
+ features += [ "isolated-persistent-storage" ]
metadata = {
fuzz_spec = [
{
diff --git a/examples/fuzzers/BUILD.gn b/examples/fuzzers/BUILD.gn
index 5cd438a..070ed7a 100644
--- a/examples/fuzzers/BUILD.gn
+++ b/examples/fuzzers/BUILD.gn
@@ -34,6 +34,10 @@
"cpp:corpus_fuzzer_without_corpus",
"cpp:dictionary_fuzzer",
"cpp:dictionary_fuzzer_without_dictionary",
+ {
+ label = "cpp:extended_sandbox"
+ fuzz_host = false
+ },
"cpp:fuzzed_data_provider_fuzzer",
"cpp:noop_fuzzer",
{
diff --git a/examples/fuzzers/cpp/BUILD.gn b/examples/fuzzers/cpp/BUILD.gn
index bb86210..9b67128 100644
--- a/examples/fuzzers/cpp/BUILD.gn
+++ b/examples/fuzzers/cpp/BUILD.gn
@@ -44,6 +44,12 @@
sources = [ "noop.cc" ]
}
+fuzzer("extended_sandbox") {
+ sources = [ "extended_sandbox.cc" ]
+ deps = [ "//src/lib/files" ]
+ features = [ "isolated-cache-storage" ]
+}
+
# Uses non-default output name. See the corresponding scope in //examples/fuzzer:fuzzing-examples
fuzzer("oom_fuzzer") {
output_name = "out_of_memory_fuzzer"
diff --git a/examples/fuzzers/cpp/extended_sandbox.cc b/examples/fuzzers/cpp/extended_sandbox.cc
new file mode 100644
index 0000000..10b4ca4
--- /dev/null
+++ b/examples/fuzzers/cpp/extended_sandbox.cc
@@ -0,0 +1,17 @@
+// Copyright 2020 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "src/lib/files/directory.h"
+
+// A simple fuzzer that needs the non-default `isolated-cache-storage` sandbox feature to run
+// correctly.
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ assert(files::IsDirectory("/cache"));
+ return 0;
+}