aboutsummaryrefslogtreecommitdiff
path: root/projects/firefox
diff options
context:
space:
mode:
authorpdknsk <pdknsk@gmail.com>2018-07-25 16:28:37 +0200
committerAbhishek Arya <inferno@chromium.org>2018-07-25 07:28:37 -0700
commitd96443b1b860207d2a0ca6d1ffd4004cf192048f (patch)
treea178edc1e289bbd13efcb6a7c5f98bd06174bda0 /projects/firefox
parentf3e21472aa5cda6664ac80ab2cf276721444541e (diff)
downloadoss-fuzz-d96443b1b860207d2a0ca6d1ffd4004cf192048f.tar.gz
firefox (#1546)
* firefox * make wrapper its own file * many minor changes * build package rather then copying * add (disabled) Qcms target * getenv doesn't use errno * make paths dynamically * minor find fix * handle absolute path * make run_minijail work * get required libraries automatically * Remove ContentParentIPC fuzz target
Diffstat (limited to 'projects/firefox')
-rw-r--r--projects/firefox/Dockerfile26
-rwxr-xr-xprojects/firefox/build.sh96
-rw-r--r--projects/firefox/project.yaml8
-rw-r--r--projects/firefox/target.c76
4 files changed, 206 insertions, 0 deletions
diff --git a/projects/firefox/Dockerfile b/projects/firefox/Dockerfile
new file mode 100644
index 000000000..690f5ca7b
--- /dev/null
+++ b/projects/firefox/Dockerfile
@@ -0,0 +1,26 @@
+# Copyright 2018 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+MAINTAINER pdknsk@gmail.com
+RUN apt-get update && \
+ apt-get install -y apt-file gawk mercurial parallel && \
+ apt-file --non-interactive update
+RUN hg clone https://hg.mozilla.org/mozilla-central
+WORKDIR mozilla-central
+ENV SHELL /bin/bash # required by mach for some reason
+RUN ./mach bootstrap --no-interactive --application-choice browser
+COPY build.sh target.c $SRC/
diff --git a/projects/firefox/build.sh b/projects/firefox/build.sh
new file mode 100755
index 000000000..80e8b5c3d
--- /dev/null
+++ b/projects/firefox/build.sh
@@ -0,0 +1,96 @@
+#!/bin/bash -eu
+# Copyright 2018 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+# Case-sensitive names of internal Firefox fuzzing targets. Edit to add more.
+FUZZ_TARGETS=(
+ SdpParser
+ StunParser
+ # Qcms # needn't be enabled; has its own project with more sanitizers/engines
+)
+
+# Firefox object (build) directory.
+OBJDIR=$WORK/obj-fuzz
+
+# Firefox fuzzing build configuration.
+cat << EOF > mozconfig
+ac_add_options --disable-debug
+ac_add_options --disable-elf-hack
+ac_add_options --disable-jemalloc
+ac_add_options --disable-crashreporter
+ac_add_options --enable-fuzzing
+ac_add_options --enable-optimize=-O1
+ac_add_options --enable-debug-symbols=-gline-tables-only
+mk_add_options MOZ_OBJDIR=${OBJDIR}
+mk_add_options MOZ_MAKE_FLAGS=-j$(nproc)
+mk_add_options CFLAGS=
+mk_add_options CXXFLAGS=
+EOF
+
+if [[ $SANITIZER = "address" ]]
+then
+cat << EOF >> mozconfig
+ac_add_options --enable-address-sanitizer
+EOF
+fi
+
+# Build! Takes about 15 minutes on a 32 vCPU instance.
+./mach build
+./mach gtest buildbutdontrun
+
+# Packages Firefox only to immediately extract the archive. Some files are
+# replaced with gtest-variants, which is required by the fuzzing interface.
+# Weighs in shy of 1GB afterwards.
+make -j$(nproc) -C $OBJDIR package
+tar -xf $OBJDIR/dist/firefox*bz2 -C $OUT
+mv $OBJDIR/toolkit/library/gtest/libxul.so $OUT/firefox
+mv $OUT/firefox/dependentlibs.list $OUT/firefox/dependentlibs.list.gtest
+
+# Get the absolute paths of the required libraries.
+export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$OUT/firefox
+REQUIRED_LIBRARIES=($(ldd $OUT/firefox/libxul.so | gawk '/=> [/]/ {print $3}'))
+REQUIRED_LIBRARIES=(${REQUIRED_LIBRARIES[@]##$OUT/*})
+
+mkdir $WORK/apt
+chown _apt $WORK/apt # suppress warning message on each file
+cd $WORK/apt
+
+# Find and download packages which have the required files, ignoring some.
+# Note that apt-file is very slow, hence parallel is used.
+# Takes only 1-2 minutes on a 32 vCPU instance.
+PACKAGES=($(parallel apt-file search -lFN "{}" ::: ${REQUIRED_LIBRARIES[@]}))
+PACKAGES=(${PACKAGES[@]##libc6*})
+PACKAGES=(${PACKAGES[@]##libstdc++*})
+apt-get -q download ${PACKAGES[@]}
+
+mkdir $WORK/deb
+# Extract downloaded packages.
+find $WORK/apt -type f -exec dpkg-deb --extract "{}" $WORK/deb \;
+
+mkdir $OUT/lib
+# Move required libraries (and symlinks). Less than 50MB total.
+for REQUIRED_LIBRARY in ${REQUIRED_LIBRARIES[@]}
+do
+ find $WORK/deb -name "${REQUIRED_LIBRARY##*/}*" -exec mv "{}" $OUT/lib \;
+done
+
+# Build a wrapper binary for each target to set environment variables.
+for FUZZ_TARGET in ${FUZZ_TARGETS[@]}
+do
+ $CC $CFLAGS -O0 \
+ -DFUZZ_TARGET=$FUZZ_TARGET \
+ $SRC/target.c -o $OUT/$FUZZ_TARGET
+done
diff --git a/projects/firefox/project.yaml b/projects/firefox/project.yaml
new file mode 100644
index 000000000..ec31b5865
--- /dev/null
+++ b/projects/firefox/project.yaml
@@ -0,0 +1,8 @@
+homepage: "https://www.mozilla.org/firefox/"
+primary_contact: "agaynor@mozilla.com"
+fuzzing_engines:
+- libfuzzer
+sanitizers:
+- address
+auto_ccs:
+- choller@mozilla.com
diff --git a/projects/firefox/target.c b/projects/firefox/target.c
new file mode 100644
index 000000000..1c225657d
--- /dev/null
+++ b/projects/firefox/target.c
@@ -0,0 +1,76 @@
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define STRINGLIT(S) #S
+#define STRINGIFY(S) STRINGLIT(S)
+
+// Required for oss-fuzz to consider the binary a target.
+static const char* magic = "LLVMFuzzerTestOneInput";
+
+int main(int argc, char* argv[]) {
+ char path[PATH_MAX] = {0};
+
+ if (**argv != '/') {
+ if (!getcwd(path, PATH_MAX)) {
+ perror("Couldn't get CWD");
+ exit(1);
+ }
+ strcat(path, "/");
+ }
+
+ if (strlen(path) + strlen(*argv) + 20 > PATH_MAX) {
+ fprintf(stderr, "Path length would exceed PATH_MAX\n");
+ exit(1);
+ }
+
+ strcat(path, *argv);
+
+ char* solidus = strrchr(path, '/');
+ *solidus = 0; // terminate string before last /
+
+ char ld_path[PATH_MAX] = {0};
+ strcpy(ld_path, path);
+ strcat(ld_path, "/lib");
+
+ char ff_path[PATH_MAX] = {0};
+ strcpy(ff_path, path);
+ strcat(ff_path, "/firefox/firefox");
+
+ if (getenv("LD_LIBRARY_PATH")) {
+ // Shouldn't be set. Code can be changed to append if it ever is.
+ fprintf(stderr, "LD_LIBRARY_PATH unexpectedly set\n");
+ exit(1);
+ }
+ if (setenv("LD_LIBRARY_PATH", ld_path, 0)) {
+ perror("Error setting LD_LIBRARY_PATH");
+ exit(1);
+ }
+
+ if (setenv("MOZ_RUN_GTEST", "1", 1) || setenv("LIBFUZZER", "1", 1) ||
+ setenv("FUZZER", STRINGIFY(FUZZ_TARGET), 1)) {
+ perror("Error setting fuzzing variables");
+ exit(1);
+ }
+
+ // Temporary (or permanent?) work-around for a bug in the fuzzing interface.
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1466021#c9
+ char* options = getenv("ASAN_OPTIONS");
+ if (!options) {
+ fprintf(stderr, "ASAN_OPTIONS not set ?!\n");
+ exit(1);
+ }
+ char append[] = ":detect_stack_use_after_return=0";
+ char* new_options = (char*)malloc(strlen(options) + sizeof(append));
+ memcpy(new_options, options, strlen(options));
+ memcpy(new_options + strlen(options), append, sizeof(append));
+ if (setenv("ASAN_OPTIONS", new_options, 1)) {
+ perror("Error setting ASAN_OPTIONS");
+ exit(1);
+ }
+ free(new_options);
+
+ return execv(ff_path, argv);
+}