Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setting up Fuzz Testing with LibFuzzer and initial Server Fuzz Test #263

Merged
merged 14 commits into from
Jul 28, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,12 @@
libcrypto-build/*
libcrypto-root/*
tests/unit/*_test
tests/fuzz/fuzz-*.log
bin/s2nc
bin/s2nd
util-linux-*
Python-*
clang-*
fuzz_dependencies/*
.travis/prlimit
.travis/.libs/*
27 changes: 25 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
sudo: true
language: c

addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- gcc-6
- g++-6

os:
- osx
Expand All @@ -8,15 +17,29 @@ compiler:
- gcc
- clang

before_install:
# Install GCC 6 if on OSX
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew tap homebrew/versions ; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install gcc6 ; fi
# Set GCC 6 as Default on both Ubuntu and OSX
- alias gcc=$(which gcc-6)
# Install latest version of clang, clang++, and llvm-symbolizer and add them to beginning of PATH. Needed for fuzzing.
- (.travis/install_clang.sh `pwd`/clang-download `pwd`/clang-latest $TRAVIS_OS_NAME) && export PATH=`pwd`/clang-latest/bin:$PATH
install:
# Download and Install LibFuzzer
- .travis/install_libFuzzer.sh `pwd`/fuzz_dependencies/libFuzzer-download `pwd`/fuzz_dependencies $TRAVIS_OS_NAME
# Download and Install Openssl
- .travis/install_openssl.sh `pwd`/libcrypto-build `pwd`/libcrypto-root $TRAVIS_OS_NAME > /dev/null
# Install python linked with our compiled Openssl for integration tests
- sudo .travis/install_python.sh `pwd`/libcrypto-root > /dev/null
- sudo "PATH=$PATH" .travis/install_python.sh `pwd`/libcrypto-root > /dev/null
# Install prlimit to set the memlock limit to unlimited for this process
- (test "$TRAVIS_OS_NAME" = "linux" && sudo .travis/install_prlimit.sh $PWD/.travis > /dev/null && sudo .travis/prlimit --pid "$$" --memlock=unlimited:unlimited) || true
- (test "$TRAVIS_OS_NAME" = "linux" && sudo "PATH=$PATH" .travis/install_prlimit.sh $PWD/.travis > /dev/null && sudo .travis/prlimit --pid "$$" --memlock=unlimited:unlimited) || true
- mkdir -p .travis/checker && .travis/install_scan-build.sh .travis/checker && export PATH=$PATH:.travis/checker/bin

script:
- (test "$TRAVIS_OS_NAME" = "linux" && make -j8) || true
# Build and run unit tests with scan-build for osx. scan-build bundle isn't available for linux
- (test "$TRAVIS_OS_NAME" = "osx" && scan-build --status-bugs -o /tmp/scan-build make -j8; STATUS=$?; test $STATUS -ne 0 && cat /tmp/scan-build/*/*; exit $STATUS) || true
- make integration
- make clean && make fuzz
57 changes: 57 additions & 0 deletions .travis/install_clang.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#!/bin/bash
# Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License.
# A copy of the License is located at
#
# http://aws.amazon.com/apache2.0
#
# or in the "license" file accompanying this file. This file 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.
#

set -e

usage() {
echo "install_clang.sh download_dir install_dir travis_platform"
exit 1
}

if [ "$#" -ne "3" ]; then
usage
fi

CLANG_DOWNLOAD_DIR=$1
CLANG_INSTALL_DIR=$2
PLATFORM=$3

mkdir -p $CLANG_DOWNLOAD_DIR
cd $CLANG_DOWNLOAD_DIR

if [ "$PLATFORM" == "linux" ]; then
# The Certificate used by chromium.googlesource.com is not in the default CA
# list supported by git/curl on Ubuntu, but the certificate is in the
# ca-certificates.crt file in Ubuntu, so set this env variable so that it is
# picked up by git.
export SSL_CERT_FILE=/usr/lib/ssl/certs/ca-certificates.crt
fi

GIT_CURL_VERBOSE=1
echo "Downloading Clang..."
git clone https://chromium.googlesource.com/chromium/src/tools/clang

echo "Updating Clang..."
$CLANG_DOWNLOAD_DIR/clang/scripts/update.py

# "third_party" directory is created above $CLANG_DOWNLOAD_DIR after running
# update, move it into $CLANG_DOWNLOAD_DIR once update is complete.
mv ../third_party $CLANG_DOWNLOAD_DIR

echo "Installed Clang Version: "
$CLANG_DOWNLOAD_DIR/third_party/llvm-build/Release+Asserts/bin/clang --version

ln -s $CLANG_DOWNLOAD_DIR/third_party/llvm-build/Release+Asserts/ $CLANG_INSTALL_DIR

40 changes: 40 additions & 0 deletions .travis/install_libFuzzer.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/bin/bash
# Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License.
# A copy of the License is located at
#
# http://aws.amazon.com/apache2.0
#
# or in the "license" file accompanying this file. This file 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.
#
set -e

usage() {
echo "install_libFuzzer.sh download_dir install_dir travis_platform"
exit 1
}

if [ "$#" -ne "3" ]; then
usage
fi

LIBFUZZER_DOWNLOAD_DIR=$1
LIBFUZZER_INSTALL_DIR=$2
PLATFORM=$3

mkdir -p $LIBFUZZER_DOWNLOAD_DIR
cd $LIBFUZZER_DOWNLOAD_DIR

git clone https://chromium.googlesource.com/chromium/llvm-project/llvm/lib/Fuzzer

echo "Compiling LibFuzzer..."
clang++ -c -g -v -O2 -lstdc++ -std=c++11 Fuzzer/*.cpp -IFuzzer
ar ruv libFuzzer.a Fuzzer*.o

echo "Copying libFuzzer.a to $LIBFUZZER_INSTALL_DIR"
cp libFuzzer.a $LIBFUZZER_INSTALL_DIR
2 changes: 1 addition & 1 deletion .travis/install_prlimit.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pushd $PWD
wget https://www.kernel.org/pub/linux/utils/util-linux/v2.25/util-linux-2.25.2.tar.gz
tar -xzvf util-linux-2.25.2.tar.gz
cd util-linux-2.25.2
./configure ADJTIME_PATH=/var/lib/hwclock/adjtime --disable-chfn-chsh --disable-login --disable-nologin --disable-su --disable-setpriv --disable-runuser --disable-pylibmount --disable-static --without-python --without-systemd --without-systemdsystemunitdir --without-ncurses
./configure ADJTIME_PATH=/var/lib/hwclock/adjtime --disable-chfn-chsh --disable-login --disable-nologin --disable-su --disable-setpriv --disable-runuser --disable-pylibmount --disable-static --without-python --without-systemd --without-systemdsystemunitdir --without-ncurses || cat config.log

# only compile prlimit
make prlimit
Expand Down
17 changes: 17 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,23 @@ bin: libs
integration: bin
$(MAKE) -C tests integration


.PHONY : fuzz
ifeq ($(shell uname),Linux)
fuzz : fuzz-linux
else
fuzz : fuzz-osx
endif

.PHONY : fuzz-osx
fuzz-osx :
@echo "\033[33;1mSKIPPED\033[0m Fuzzing is not supported on \"$$(uname -mprs)\" at this time."

.PHONY : fuzz-linux
fuzz-linux : export S2N_UNSAFE_FUZZING_MODE = 1
fuzz-linux : bin
$(MAKE) -C tests fuzz

.PHONY : indent
indent:
$(MAKE) -C tests indentsource
Expand Down
25 changes: 20 additions & 5 deletions s2n.mk
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,26 @@ SOURCES = $(wildcard *.c *.h)
CRUFT = $(wildcard *.c~ *.h~ *.c.BAK *.h.BAK *.o *.a *.so *.dylib)
INDENT = $(shell (if indent --version 2>&1 | grep GNU > /dev/null; then echo indent ; elif gindent --version 2>&1 | grep GNU > /dev/null; then echo gindent; else echo true ; fi ))

CFLAGS = -pedantic -Wall -Werror -Wimplicit -Wunused -Wcomment -Wchar-subscripts -Wuninitialized \
-Wshadow -Wcast-qual -Wcast-align -Wwrite-strings -Wstack-protector -fPIC \
-std=c99 -D_POSIX_C_SOURCE=200112L -fstack-protector-all -O2 -I$(LIBCRYPTO_ROOT)/include/ \
-I../api/ -I../ -Wno-deprecated-declarations -Wno-unknown-pragmas -Wformat-security \
-D_FORTIFY_SOURCE=2
DEFAULT_CFLAGS = -pedantic -Wall -Werror -Wimplicit -Wunused -Wcomment -Wchar-subscripts -Wuninitialized \
-Wshadow -Wcast-qual -Wcast-align -Wwrite-strings -Wstack-protector -fPIC \
-std=c99 -D_POSIX_C_SOURCE=200112L -fstack-protector-all -O2 -I$(LIBCRYPTO_ROOT)/include/ \
-I../api/ -I../ -Wno-deprecated-declarations -Wno-unknown-pragmas -Wformat-security \
-D_FORTIFY_SOURCE=2

CFLAGS = ${DEFAULT_CFLAGS}

DEBUG_CFLAGS = -g3 -ggdb -fno-omit-frame-pointer -fno-optimize-sibling-calls

FUZZ_CFLAGS = -fsanitize-coverage=edge,trace-cmp -fsanitize=address,undefined,leak

ifeq ($(S2N_UNSAFE_FUZZING_MODE),1)
# Override compiler to clang if fuzzing, since gcc does not support as many sanitizer flags as clang
CC=clang

# Turn on debugging and fuzzing flags when S2N_UNSAFE_FUZZING_MODE is enabled to give detailed stack traces in case
# an error occurs while fuzzing.
CFLAGS = ${DEFAULT_CFLAGS} ${DEBUG_FLAGS} ${FUZZ_CFLAGS}
endif

INDENTOPTS = -npro -kr -i4 -ts4 -nut -sob -l180 -ss -ncs -cp1

Expand Down
5 changes: 5 additions & 0 deletions tests/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,14 @@ all:
integration:
${MAKE} -C integration

.PHONY : fuzz
fuzz:
${MAKE} -C fuzz

include ../s2n.mk

.PHONY : clean
clean:
${MAKE} -C testlib decruft
${MAKE} -C unit decruft
${MAKE} -C fuzz decruft
31 changes: 31 additions & 0 deletions tests/fuzz/LD_PRELOAD/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#
# Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License.
# A copy of the License is located at
#
# http://aws.amazon.com/apache2.0
#
# or in the "license" file accompanying this file. This file 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.
#

SRCS=$(wildcard *.c)
OVERRIDES=$(SRCS:.c=)

.PHONY : all
all : $(OVERRIDES)

include ../../../s2n.mk

CRUFT += $(wildcard *.so)

LD_PRELOAD_CFLAGS = -Wno-unreachable-code -O0 -I$(LIBCRYPTO_ROOT)/include/ -I../../../ -I../../../api/

$(OVERRIDES)::
# Don't include Sanitizer/Fuzz compiler flags since when the LD_PRELOAD shared object is Preloaded, the Sanitizer init
# functions won't have been loaded yet, causing undefined symbol errors.
${CC} ${DEFAULT_CFLAGS} ${DEBUG_CFLAGS} ${LD_PRELOAD_CFLAGS} -shared -fPIC [email protected] -o [email protected] -ldl
66 changes: 66 additions & 0 deletions tests/fuzz/LD_PRELOAD/global_overrides.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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.
*/

#define _GNU_SOURCE

#include <stdio.h>
#include <dlfcn.h>

#include "crypto/s2n_drbg.h"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd separate each section, s2n-style.


#include "stuffer/s2n_stuffer.h"

#include "utils/s2n_safety.h"
#include "utils/s2n_random.h"

int s2n_drbg_generate(struct s2n_drbg *drbg, struct s2n_blob *blob) {

/* If fuzzing, only generate "fake" random numbers in order to ensure that fuzz tests are deterministic and repeatable.
* This function should generate non-zero values since this function may be called repeatedly at startup until a
* non-zero value is generated.
*/
GUARD(s2n_get_urandom_data(blob));
drbg->bytes_used += blob->size;
return 0;
}

int s2n_stuffer_send_to_fd(struct s2n_stuffer *stuffer, int wfd, uint32_t len)
{
/* Override the original s2n_stuffer_send_to_fd to check if the write file descriptor is -1, and if so, skip
* writing anything. This is to speed up fuzz tests that write unnecessary data that is never actually read.
*/
if(wfd == -1){
stuffer->read_cursor += len;
return len;
}

/* Otherwise, call the original s2n_stuffer_send_to_fd() */
typedef int (*orig_s2n_stuffer_send_to_fd_func_type)(struct s2n_stuffer *stuffer, int wfd, uint32_t len);
orig_s2n_stuffer_send_to_fd_func_type orig_s2n_stuffer_send_to_fd;
orig_s2n_stuffer_send_to_fd = (orig_s2n_stuffer_send_to_fd_func_type) dlsym(RTLD_NEXT, "s2n_stuffer_send_to_fd");
return orig_s2n_stuffer_send_to_fd(stuffer, wfd, len);
}

int s2n_get_urandom_data(struct s2n_blob *blob){

/* If fuzzing, only generate "fake" random numbers in order to ensure that fuzz tests are deterministic and repeatable.
* This function should generate non-zero values since this function may be called repeatedly at startup until a
* non-zero value is generated.
*/
for(int i=0; i < blob->size; i++){
blob->data[i] = 4; /* Fake RNG. Chosen by fair dice roll. https://xkcd.com/221/ */
}
return 0;
}
24 changes: 24 additions & 0 deletions tests/fuzz/LD_PRELOAD/s2n_memory_leak_negative_test_overrides.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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.
*/

#include "utils/s2n_blob.h"

int s2n_free(struct s2n_blob *b)
{
/* This will cause large amounts of memory leaks. This should be caught by LibFuzzer as a negative fuzz test to
* ensure that LibFuzzer will catch these memory leaks.
*/
return 0;
}
Loading