Bug 1339539 - Build and run the TLS client fuzzer in non-TLS fuzzing mode r=franziskus
authorTim Taubert <ttaubert@mozilla.com>
Wed, 15 Feb 2017 11:11:36 +0100
changeset 13131 ff69598a84f0c9a51fa7a748185f24f5a124f1ab
parent 13130 78c630064cc8c0d29feab0c2be9a3210c9457d9a
child 13132 3cd42b902761a49d30b5648b00e477fadfe9bd53
push id2014
push userttaubert@mozilla.com
push dateWed, 15 Feb 2017 10:11:57 +0000
reviewersfranziskus
bugs1339539
Bug 1339539 - Build and run the TLS client fuzzer in non-TLS fuzzing mode r=franziskus Differential Revision: https://nss-review.dev.mozaws.net/D215
automation/ossfuzz/build.sh
automation/taskcluster/graph/src/extend.js
fuzz/fuzz.gyp
fuzz/tls-client-no_fuzzer_mode.options
fuzz/tls_client_target.cc
--- a/automation/ossfuzz/build.sh
+++ b/automation/ossfuzz/build.sh
@@ -4,30 +4,54 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 #
 ################################################################################
 
 # List of targets disabled for oss-fuzz.
 declare -A disabled=([pkcs8]=1)
 
-# Build the library.
-CXX="$CXX -stdlib=libc++" LDFLAGS="$CFLAGS" \
-    ./build.sh -c -v --fuzz=oss --fuzz=tls --disable-tests
+# List of targets we want to fuzz in TLS and non-TLS mode.
+declare -A tls_targets=([tls-client]=1)
 
-# Copy libFuzzer options
-cp fuzz/*.options $OUT/
-
-# Find fuzzing targets.
-for fuzzer in $(find ../dist/Debug/bin -name "nssfuzz-*" -printf "%f\n"); do
-    name=${fuzzer:8}
-    [ -n "${disabled[$name]:-}" ] && continue;
+# Helper function that copies a fuzzer binary and its seed corpus.
+copy_fuzzer()
+{
+    local fuzzer=$1
+    local name=$2
 
     # Copy the binary.
     cp ../dist/Debug/bin/$fuzzer $OUT/$name
 
     # Zip and copy the corpus, if any.
     if [ -d "$SRC/nss-corpus/$name" ]; then
         zip $OUT/${name}_seed_corpus.zip $SRC/nss-corpus/$name/*
     else
         zip $OUT/${name}_seed_corpus.zip $SRC/nss-corpus/*/*
     fi
+}
+
+# Copy libFuzzer options
+cp fuzz/*.options $OUT/
+
+# Build the library (non-TLS fuzzing mode).
+CXX="$CXX -stdlib=libc++" LDFLAGS="$CFLAGS" \
+    ./build.sh -c -v --fuzz=oss --fuzz --disable-tests
+
+# Copy fuzzing targets.
+for fuzzer in $(find ../dist/Debug/bin -name "nssfuzz-*" -printf "%f\n"); do
+    name=${fuzzer:8}
+    if [ -z "${disabled[$name]:-}" ]; then
+        [ -n "${tls_targets[$name]:-}" ] && name="${name}-no_fuzzer_mode"
+        copy_fuzzer $fuzzer $name
+    fi
 done
+
+# Build the library again (TLS fuzzing mode).
+CXX="$CXX -stdlib=libc++" LDFLAGS="$CFLAGS" \
+    ./build.sh -c -v --fuzz=oss --fuzz=tls --disable-tests
+
+# Copy dual mode targets in TLS mode.
+for name in "${!tls_targets[@]}"; do
+    if [ -z "${disabled[$name]:-}" ]; then
+        copy_fuzzer nssfuzz-$name $name
+    fi
+done
--- a/automation/taskcluster/graph/src/extend.js
+++ b/automation/taskcluster/graph/src/extend.js
@@ -259,26 +259,26 @@ async function scheduleLinux(name, base)
     symbol: "modular"
   }));
 
   return queue.submit();
 }
 
 /*****************************************************************************/
 
-function scheduleFuzzingRun(base, name, target, max_len, symbol = null) {
+function scheduleFuzzingRun(base, name, target, max_len, symbol = null, corpus = null) {
   const MAX_FUZZ_TIME = 300;
 
   queue.scheduleTask(merge(base, {
     name,
     command: [
       "/bin/bash",
       "-c",
       "bin/checkout.sh && nss/automation/taskcluster/scripts/fuzz.sh " +
-        `${target} nss/fuzz/corpus/${target} ` +
+        `${target} nss/fuzz/corpus/${corpus || target} ` +
         `-max_total_time=${MAX_FUZZ_TIME} ` +
         `-max_len=${max_len}`
     ],
     symbol: symbol || name
   }));
 }
 
 async function scheduleFuzzing() {
@@ -298,17 +298,17 @@ async function scheduleFuzzing() {
   };
 
   // Build base definition.
   let build_base = merge({
     command: [
       "/bin/bash",
       "-c",
       "bin/checkout.sh && " +
-      "nss/automation/taskcluster/scripts/build_gyp.sh -g -v --fuzz=tls"
+      "nss/automation/taskcluster/scripts/build_gyp.sh -g -v --fuzz"
     ],
     artifacts: {
       public: {
         expires: 24 * 7,
         type: "directory",
         path: "/home/worker/artifacts"
       }
     },
@@ -316,19 +316,32 @@ async function scheduleFuzzing() {
     symbol: "B"
   }, base);
 
   // The task that builds NSPR+NSS.
   let task_build = queue.scheduleTask(merge(build_base, {
     name: "Linux x64 (debug, fuzz)"
   }));
 
+  // The task that builds NSPR+NSS (TLS fuzzing mode).
+  let task_build_tls = queue.scheduleTask(merge(build_base, {
+    name: "Linux x64 (debug, TLS fuzz)",
+    symbol: "B",
+    group: "TLS",
+    command: [
+      "/bin/bash",
+      "-c",
+      "bin/checkout.sh && " +
+      "nss/automation/taskcluster/scripts/build_gyp.sh -g -v --fuzz=tls"
+    ],
+  }));
+
   // Schedule tests.
   queue.scheduleTask(merge(base, {
-    parent: task_build,
+    parent: task_build_tls,
     name: "Gtests",
     command: [
       "/bin/bash",
       "-c",
       "bin/checkout.sh && nss/automation/taskcluster/scripts/run_tests.sh"
     ],
     env: {GTESTFILTER: "*Fuzz*"},
     tests: "ssl_gtests gtests",
@@ -346,19 +359,24 @@ async function scheduleFuzzing() {
   // Schedule MPI fuzzing runs.
   let mpi_base = merge(run_base, {group: "MPI"});
   let mpi_names = ["add", "addmod", "div", "expmod", "mod", "mulmod", "sqr",
                    "sqrmod", "sub", "submod"];
   for (let name of mpi_names) {
     scheduleFuzzingRun(mpi_base, `MPI (${name})`, `mpi-${name}`, 4096, name);
   }
 
-  // Schedule TLS fuzzing runs.
+  // Schedule TLS fuzzing runs (non-fuzzing mode).
   let tls_base = merge(run_base, {group: "TLS"});
-  scheduleFuzzingRun(tls_base, "TLS Client", "tls-client", 20000, "client");
+  scheduleFuzzingRun(tls_base, "TLS Client", "tls-client", 20000, "client-nfm",
+                     "tls-client-no_fuzzer_mode");
+
+  // Schedule TLS fuzzing runs (fuzzing mode).
+  let tls_fm_base = merge(tls_base, {parent: task_build_tls});
+  scheduleFuzzingRun(tls_fm_base, "TLS Client", "tls-client", 20000, "client");
 
   return queue.submit();
 }
 
 /*****************************************************************************/
 
 async function scheduleTestBuilds() {
   let base = {
--- a/fuzz/fuzz.gyp
+++ b/fuzz/fuzz.gyp
@@ -255,16 +255,23 @@
       'dependencies': [
         '<(DEPTH)/cpputil/cpputil.gyp:cpputil',
         '<(DEPTH)/exports.gyp:nss_exports',
         'fuzz_base',
       ],
       'include_dirs': [
         '<(DEPTH)/lib/freebl',
       ],
+      'conditions': [
+        [ 'fuzz_tls==1', {
+          'defines': [
+            'UNSAFE_FUZZER_MODE',
+          ],
+        }],
+      ],
     },
     {
       'target_name': 'nssfuzz',
       'type': 'none',
       'dependencies': [
         'nssfuzz-certDN',
         'nssfuzz-hash',
         'nssfuzz-pkcs8',
new file mode 100644
--- /dev/null
+++ b/fuzz/tls-client-no_fuzzer_mode.options
@@ -0,0 +1,3 @@
+[libfuzzer]
+max_len = 20000
+
--- a/fuzz/tls_client_target.cc
+++ b/fuzz/tls_client_target.cc
@@ -100,19 +100,21 @@ static void DoHandshake(PRFileDesc* fd) 
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t len) {
   static std::unique_ptr<NSSDatabase> db(new NSSDatabase());
   assert(db != nullptr);
 
   EnableAllProtocolVersions();
   std::unique_ptr<ClientConfig> config(new ClientConfig(data, len));
 
+#ifdef UNSAFE_FUZZER_MODE
   // Reset the RNG state.
   SECStatus rv = RNG_ResetForFuzzing();
   assert(rv == SECSuccess);
+#endif
 
   // Create and import dummy socket.
   std::unique_ptr<DummyPrSocket> socket(new DummyPrSocket(data, len));
   static PRDescIdentity id = PR_GetUniqueIdentity("fuzz-client");
   ScopedPRFileDesc fd(DummyIOLayerMethods::CreateFD(id, socket.get()));
   PRFileDesc* ssl_fd = SSL_ImportFD(nullptr, fd.get());
   assert(ssl_fd == fd.get());