[firefox] more targets and more (#1762)

* ASAN_OPTIONS might not be set for each mode

* no point in checking setenv, can only fail with EOMEM here

* minor changes to target.c

* new target: ContentSecurityPolicyParser

* new target: ContentParentIPC

* better corpus and dictionary for {Sdp,Stun}Parser

* bootstrap already installs all required libraries

* faster hg clone

* don't install cargo again, better explanation
This commit is contained in:
pdknsk 2018-08-27 15:27:12 +02:00 committed by jonathanmetzman
parent 57cfaddfd8
commit 4fd7dbcaf6
4 changed files with 61 additions and 88 deletions

View File

@ -0,0 +1,2 @@
[libfuzzer]
close_fd_mask = 2

View File

@ -16,9 +16,8 @@
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
RUN apt-get update && apt-get install -y gawk mercurial
RUN hg clone --uncompressed https://hg.mozilla.org/mozilla-central
RUN git clone --depth 1 https://github.com/mozillasecurity/fuzzdata
WORKDIR mozilla-central
COPY build.sh target.c $SRC/
COPY build.sh target.c *options $SRC/

View File

@ -19,6 +19,8 @@
FUZZ_TARGETS=(
SdpParser
StunParser
ContentParentIPC
ContentSecurityPolicyParser
# Qcms # needn't be enabled; has its own project with more sanitizers/engines
)
@ -49,14 +51,12 @@ mk_add_options CXXFLAGS=
EOF
fi
# Remove existing cargo configs (if any). Otherwise, mach fails.
if [ -d "$HOME/.cargo" ]; then rm -rf $HOME/.cargo; fi
# Install dependencies.
# Install dependencies. Note that bootstrap installs cargo, which must be added
# to PATH via source. In a successive run (for a different sanitizer), the
# cargo installation carries over, but bootstrap fails if cargo is not in PATH.
export SHELL=/bin/bash
[ -f "$HOME/.cargo/env" ] && source $HOME/.cargo/env
./mach bootstrap --no-interactive --application-choice browser
# Set environment for rustc.
source $HOME/.cargo/env
# Update internal libFuzzer.
@ -74,34 +74,16 @@ 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.
# Get the absolute paths of the required system 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[@]##libgcc*})
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. Less than 50MB total.
# Copy libraries. Less than 50MB total.
mkdir -p $OUT/lib
for REQUIRED_LIBRARY in ${REQUIRED_LIBRARIES[@]}
do
find $WORK/deb \
-xtype f -name "${REQUIRED_LIBRARY##*/}" -exec cp -uL "{}" $OUT/lib \;
cp -L $REQUIRED_LIBRARY $OUT/lib
done
# Build a wrapper binary for each target to set environment variables.
@ -112,16 +94,18 @@ do
$SRC/target.c -o $OUT/$FUZZ_TARGET
done
cd $SRC/mozilla-central
# SdpParser
find media/webrtc/trunk/webrtc/test/fuzzers/corpora/sdp-corpus \
-type f -exec zip -qju $OUT/SdpParser_seed_corpus.zip "{}" \;
cp media/webrtc/trunk/webrtc/test/fuzzers/corpora/sdp.tokens \
$OUT/SdpParser.dict
find media/webrtc -iname "*.sdp" \
-type f -exec zip -qu $OUT/SdpParser_seed_corpus.zip "{}" \;
cp $SRC/fuzzdata/dicts/sdp.dict $OUT/SdpParser.dict
# StunParser
find media/webrtc/trunk/webrtc/test/fuzzers/corpora/stun-corpus \
-type f -exec zip -qju $OUT/StunParser_seed_corpus.zip "{}" \;
cp media/webrtc/trunk/webrtc/test/fuzzers/corpora/stun.tokens \
$OUT/StunParser.dict
find media/webrtc -iname "*.stun" \
-type f -exec zip -qu $OUT/StunParser_seed_corpus.zip "{}" \;
cp $SRC/fuzzdata/dicts/stun.dict $OUT/StunParser.dict
# ContentParentIPC
cp $SRC/fuzzdata/settings/ipc/libfuzzer.content.blacklist.txt $OUT/firefox
# ContentSecurityPolicyParser
cp dom/security/fuzztest/csp_fuzzer.dict $OUT/ContentSecurityPolicyParser.dict

View File

@ -13,72 +13,60 @@ static const char* magic __attribute__((used)) = "LLVMFuzzerTestOneInput";
int main(int argc, char* argv[]) {
char path[PATH_MAX] = {0};
// Handle (currently not used) relative binary path.
if (**argv != '/') {
if (!getcwd(path, PATH_MAX)) {
perror("Couldn't get CWD");
if (!getcwd(path, PATH_MAX - 1)) {
perror("getcwd");
exit(1);
}
strcat(path, "/");
}
if (strlen(path) + strlen(*argv) + 20 > PATH_MAX) {
if (strlen(path) + strlen(*argv) + 40 >= 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 /
*solidus = 0; // terminate path before last /
char ld_path[PATH_MAX] = {0};
strcpy(ld_path, path);
strcat(ld_path, "/lib");
// Expects LD_LIBRARY_PATH to not also be set by oss-fuzz.
setenv("LD_LIBRARY_PATH", ld_path, 0);
setenv("HOME", "/tmp", 0);
setenv("MOZ_RUN_GTEST", "1", 1);
setenv("LIBFUZZER", "1", 1);
setenv("FUZZER", STRINGIFY(FUZZ_TARGET), 1);
// ContentParentIPC
char blacklist_path[PATH_MAX] = {0};
strcpy(blacklist_path, path);
strcat(blacklist_path, "/firefox/libfuzzer.content.blacklist.txt");
setenv("MOZ_IPC_MESSAGE_FUZZ_BLACKLIST", blacklist_path, 1);
// Temporary (or permanent?) work-arounds for fuzzing interface bugs.
char* options = getenv("ASAN_OPTIONS");
if (options) {
char* ptr;
char* new_options = strdup(options);
// https://bugzilla.mozilla.org/1477846
ptr = strstr(new_options, "detect_stack_use_after_return=1");
if (ptr) ptr[30] = '0';
// https://bugzilla.mozilla.org/1477844
ptr = strstr(new_options, "detect_leaks=1");
if (ptr) ptr[13] = '0';
setenv("ASAN_OPTIONS", new_options, 1);
free(new_options);
}
char ff_path[PATH_MAX] = {0};
strcpy(ff_path, path);
strcat(ff_path, "/firefox/firefox");
// Expects LD_LIBRARY_PATH to not also be set by oss-fuzz.
// If it ever is, this has to be replaced with more complex code.
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);
}
if (setenv("HOME", "/tmp", 0)) {
perror("Error setting HOME");
exit(1);
}
char* options = getenv("ASAN_OPTIONS");
if (!options) {
fprintf(stderr, "ASAN_OPTIONS not set ?!\n");
exit(1);
}
// Temporary (or permanent?) work-arounds for fuzzing interface bugs.
char* new_options = strdup(options);
char* ptr;
// https://bugzilla.mozilla.org/show_bug.cgi?id=1477846
ptr = strstr(new_options, "detect_stack_use_after_return=1");
if (ptr) ptr[30] = '0';
// https://bugzilla.mozilla.org/show_bug.cgi?id=1477844
ptr = strstr(new_options, "detect_leaks=1");
if (ptr) ptr[13] = '0';
if (setenv("ASAN_OPTIONS", new_options, 1)) {
perror("Error setting ASAN_OPTIONS");
exit(1);
}
free(new_options);
int ret = execv(ff_path, argv);
if (ret)
perror("execv");