Commit 4365cb23 authored by Tim Taubert's avatar Tim Taubert

Bug 1308874 - Land basic libFuzzer fuzzing framework r=franziskus

Differential Revision: https://nss-dev.phacility.com/D76
parent ef4fdb55
......@@ -13,3 +13,5 @@ GTAGS
#*
.#*
.ycm_extra_conf.py*
fuzz/libFuzzer/*
fuzz/corpus
......@@ -13,3 +13,5 @@ GTAGS
#*
.#*
.ycm_extra_conf.py*
fuzz/libFuzzer/*
fuzz/corpus
......@@ -8,6 +8,10 @@ ifeq ($(USE_UBSAN), 1)
SANITIZER_FLAGS_COMMON += -fsanitize=undefined -fno-sanitize-recover=undefined
endif
ifeq ($(FUZZ), 1)
SANITIZER_FLAGS_COMMON += -fsanitize-coverage=edge
endif
SANITIZER_FLAGS_COMMON += $(EXTRA_SANITIZER_FLAGS)
SANITIZER_CFLAGS = $(SANITIZER_FLAGS_COMMON)
SANITIZER_LDFLAGS = $(SANITIZER_FLAGS_COMMON)
......
---
Language: Cpp
BasedOnStyle: Google
...
#! gmake
#
# This Source Code Form is subject to the terms of the Mozilla Public
# 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/.
#######################################################################
# (1) Include initial platform-independent assignments (MANDATORY). #
#######################################################################
include manifest.mn
#######################################################################
# (2) Include "global" configuration information. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/config.mk
#######################################################################
# (3) Include "component" configuration information. (OPTIONAL) #
#######################################################################
#######################################################################
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
#######################################################################
#######################################################################
# (5) Execute "global" rules. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/rules.mk
#######################################################################
# (6) Execute "component" rules. (OPTIONAL) #
#######################################################################
#######################################################################
# (7) Execute "local" rules. (OPTIONAL). #
#######################################################################
#!/bin/sh
cd $(dirname $0)
git clone https://github.com/mozilla/nss-fuzzing-corpus corpus
#!/bin/sh
cd $(dirname $0)
mkdir tmp/
git clone -q https://chromium.googlesource.com/chromium/llvm-project/llvm/lib/Fuzzer tmp/
mv tmp/.git libFuzzer
rm -fr tmp
cd libFuzzer
git reset --hard 4333f2ca71eb7951fcafcdcb111012fbe25c5e7e
#! gmake
#
# This Source Code Form is subject to the terms of the Mozilla Public
# 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/.
MKPROG = $(CCC)
MKSHLIB = $(CCC) $(DSO_LDOPTS) $(DARWIN_SDK_SHLIBFLAGS)
CXXFLAGS += -std=c++11
#! gmake
#
# This Source Code Form is subject to the terms of the Mozilla Public
# 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/.
#######################################################################
# (1) Include initial platform-independent assignments (MANDATORY). #
#######################################################################
include manifest.mn
#######################################################################
# (2) Include "global" configuration information. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/config.mk
#######################################################################
# (3) Include "component" configuration information. (OPTIONAL) #
#######################################################################
include config.mk
include ../common.mk
#######################################################################
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
#######################################################################
#######################################################################
# (5) Execute "global" rules. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/rules.mk
#######################################################################
# (6) Execute "component" rules. (OPTIONAL) #
#######################################################################
#######################################################################
# (7) Execute "local" rules. (OPTIONAL). #
#######################################################################
#
# This Source Code Form is subject to the terms of the Mozilla Public
# 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/.
# According to the LLVM docs, LibFuzzer isn't supposed to be built with any
# sanitizer flags and in fact, building it with ASan coverage currently causes
# Clang 3.9+ to crash, so we filter out all sanitizer-related flags here.
CXXFLAGS := $(filter-out -fsanitize%,$(CXXFLAGS))
CFLAGS := $(filter-out -fsanitize%,$(CFLAGS))
LDFLAGS := $(filter-out -fsanitize%,$(LDFLAGS))
DARWIN_SDK_SHLIBFLAGS := $(filter-out -fsanitize%,$(DARWIN_SDK_SHLIBFLAGS))
CXXFLAGS += -g -O2
#
# This Source Code Form is subject to the terms of the Mozilla Public
# 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/.
CORE_DEPTH = ../..
DEPTH = ../..
MODULE = nss
CPPSRCS = \
FuzzerCrossOver.cpp \
FuzzerDriver.cpp \
FuzzerExtFunctionsDlsym.cpp \
FuzzerExtFunctionsWeak.cpp \
FuzzerIO.cpp \
FuzzerLoop.cpp \
FuzzerMutate.cpp \
FuzzerSHA1.cpp \
FuzzerTracePC.cpp \
FuzzerTraceState.cpp \
FuzzerUtil.cpp \
FuzzerUtilDarwin.cpp \
FuzzerUtilLinux.cpp \
$(NULL)
LIBRARY_NAME = Fuzzer
LIBRARY_VERSION = 1
#
# This Source Code Form is subject to the terms of the Mozilla Public
# 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/.
CORE_DEPTH = ..
DEPTH = ..
DIRS = libFuzzer nssfuzz
#! gmake
#
# This Source Code Form is subject to the terms of the Mozilla Public
# 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/.
#######################################################################
# (1) Include initial platform-independent assignments (MANDATORY). #
#######################################################################
include manifest.mn
#######################################################################
# (2) Include "global" configuration information. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/config.mk
#######################################################################
# (3) Include "component" configuration information. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/cmd/platlibs.mk
include ../common.mk
#######################################################################
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
#######################################################################
#######################################################################
# (5) Execute "global" rules. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/rules.mk
#######################################################################
# (6) Execute "component" rules. (OPTIONAL) #
#######################################################################
#######################################################################
# (7) Execute "local" rules. (OPTIONAL). #
#######################################################################
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
#include <assert.h>
#include <stdint.h>
#include <memory>
#include "cert.h"
#include "registry.h"
#include "shared.h"
extern "C" int cert_fuzzing_target(const uint8_t *Data, size_t Size) {
SECItem data = {siBuffer, (unsigned char *)Data, (unsigned int)Size};
static std::unique_ptr<NSSDatabase> db(new NSSDatabase());
assert(db != nullptr);
static CERTCertDBHandle *certDB = CERT_GetDefaultCertDB();
assert(certDB != NULL);
CERTCertificate *cert =
CERT_NewTempCertificate(certDB, &data, nullptr, false, true);
if (cert) {
CERT_DestroyCertificate(cert);
}
return 0;
}
REGISTER_FUZZING_TARGET("cert", cert_fuzzing_target, 3072, "Certificate Import")
#
# This Source Code Form is subject to the terms of the Mozilla Public
# 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/.
CORE_DEPTH = ../..
DEPTH = ../..
MODULE = nss
CPPSRCS = \
cert_target.cc \
pkcs8_target.cc \
spki_target.cc \
nssfuzz.cc \
$(NULL)
INCLUDES += -I$(CORE_DEPTH)/fuzz/libFuzzer
REQUIRES = nspr nss
PROGRAM = nssfuzz
EXTRA_LIBS = $(DIST)/lib/$(LIB_PREFIX)Fuzzer.$(LIB_SUFFIX)
USE_STATIC_LIBS = 1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
#include <iomanip>
#include <iostream>
#include <memory>
#include "keyhi.h"
#include "pk11pub.h"
#include "FuzzerInternal.h"
#include "registry.h"
#include "shared.h"
using namespace std;
void printUsage(const vector<string> &args) {
size_t sep = args.at(0).rfind("/") + 1;
string progName = args.at(0).substr(sep);
cerr << progName << " - Various libFuzzer targets for NSS" << endl << endl;
cerr << "Usage: " << progName << " <target> <libFuzzer options>" << endl
<< endl;
cerr << "Valid targets:" << endl;
vector<string> names = Registry::Names();
// Find length of the longest name.
size_t name_w =
max_element(names.begin(), names.end(), [](string &a, string &b) {
return a.size() < b.size();
})->size();
// Find length of the longest description.
auto max = max_element(names.begin(), names.end(), [](string &a, string &b) {
return Registry::Desc(a).size() < Registry::Desc(b).size();
});
size_t desc_w = Registry::Desc(*max).size();
// Print list of targets.
for (string name : names) {
cerr << " " << left << setw(name_w) << name << " - " << setw(desc_w)
<< Registry::Desc(name)
<< " [default max_len=" << Registry::MaxLen(name) << "]" << endl;
}
// Some usage examples.
cerr << endl << "Run fuzzer with a given corpus directory:" << endl;
cerr << " " << progName << " <target> /path/to/corpus" << endl;
cerr << endl << "Run fuzzer with a single test input:" << endl;
cerr << " " << progName
<< " <target> ./crash-14d4355b971092e39572bc306a135ddf9f923e19" << endl;
cerr << endl
<< "Specify the number of cores you wish to dedicate to fuzzing:"
<< endl;
cerr << " " << progName << " <target> -jobs=8 -workers=8 /path/to/corpus"
<< endl;
cerr << endl << "Override the maximum length of a test input:" << endl;
cerr << " " << progName << " <target> -max_len=2048 /path/to/corpus" << endl;
cerr << endl
<< "Minimize a given corpus and put the result into 'new_corpus':"
<< endl;
cerr << " " << progName
<< " <target> -merge=1 -max_len=50000 ./new_corpus /path/to/corpus"
<< endl;
cerr << endl << "Merge new test inputs into a corpus:" << endl;
cerr
<< " " << progName
<< " <target> -merge=1 -max_len=50000 /path/to/corpus ./inputs1 ./inputs2"
<< endl;
cerr << endl << "Print libFuzzer usage information:" << endl;
cerr << " " << progName << " <target> -help=1" << endl << endl;
cerr << "Check out the docs at http://llvm.org/docs/LibFuzzer.html" << endl;
}
int main(int argc, char **argv) {
vector<string> args(argv, argv + argc);
if (args.size() < 2 || !Registry::Has(args[1])) {
printUsage(args);
return 1;
}
string targetName = args.at(1);
uint16_t maxLen = Registry::MaxLen(targetName);
string maxLenArg = "-max_len=" + to_string(maxLen);
auto find = [](string &a) {
return a.find("-max_len=") == 0 || a.find("-merge=1") == 0;
};
if (any_of(args.begin(), args.end(), find)) {
// Remove the 2nd argument.
argv[1] = argv[0];
argv++;
argc--;
} else {
// Set default max_len arg, if none given and we're not merging.
argv[1] = const_cast<char *>(maxLenArg.c_str());
}
// Hand control to the libFuzzer driver.
return fuzzer::FuzzerDriver(&argc, &argv, Registry::Func(targetName));
}
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
#include <assert.h>
#include <stdint.h>
#include <memory>
#include "keyhi.h"
#include "pk11pub.h"
#include "registry.h"
#include "shared.h"
extern "C" int pkcs8_fuzzing_target(const uint8_t *Data, size_t Size) {
SECItem data = {siBuffer, (unsigned char *)Data, (unsigned int)Size};
static std::unique_ptr<NSSDatabase> db(new NSSDatabase());
assert(db != nullptr);
PK11SlotInfo *slot = PK11_GetInternalSlot();
assert(slot != nullptr);
SECKEYPrivateKey *key = nullptr;
if (PK11_ImportDERPrivateKeyInfoAndReturnKey(slot, &data, nullptr, nullptr,
false, false, KU_ALL, &key,
nullptr) == SECSuccess) {
SECKEY_DestroyPrivateKey(key);
}
PK11_FreeSlot(slot);
return 0;
}
REGISTER_FUZZING_TARGET("pkcs8", pkcs8_fuzzing_target, 2048, "PKCS#8 Import")
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
#ifndef registry_h__
#define registry_h__
#include <map>
#include "nss.h"
#include "FuzzerInternal.h"
class Registry {
public:
static void Add(std::string name, fuzzer::UserCallback func,
uint16_t max_len, std::string desc) {
assert(!Has(name));
GetInstance().targets_[name] = TargetData(func, max_len, desc);
}
static bool Has(std::string name) {
return GetInstance().targets_.count(name) > 0;
}
static fuzzer::UserCallback Func(std::string name) {
assert(Has(name));
return std::get<0>(Get(name));
}
static uint16_t MaxLen(std::string name) {
assert(Has(name));
return std::get<1>(Get(name));
}
static std::string& Desc(std::string name) {
assert(Has(name));
return std::get<2>(Get(name));
}
static std::vector<std::string> Names() {
std::vector<std::string> names;
for (auto &it : GetInstance().targets_) {
names.push_back(it.first);
}
return names;
}
private:
typedef std::tuple<fuzzer::UserCallback, uint16_t, std::string> TargetData;
static Registry& GetInstance() {
static Registry registry;
return registry;
}
static TargetData& Get(std::string name) {
return GetInstance().targets_[name];
}
Registry() {}
std::map<std::string, TargetData> targets_;
};
#define REGISTER_FUZZING_TARGET(name, func, max_len, desc) \
static void __attribute__ ((constructor)) RegisterFuzzingTarget() { \
Registry::Add(name, func, max_len, desc); \
}
#endif // registry_h__
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
#ifndef shared_h__
#define shared_h__
#include "nss.h"
class NSSDatabase {
public:
NSSDatabase() { NSS_NoDB_Init(nullptr); }
~NSSDatabase() { NSS_Shutdown(); }
};
#endif // shared_h__
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
#include <assert.h>
#include <stdint.h>
#include <memory>
#include "keyhi.h"
#include "pk11pub.h"
#include "registry.h"
#include "shared.h"
extern "C" int spki_fuzzing_target(const uint8_t *Data, size_t Size) {
SECItem data = {siBuffer, (unsigned char *)Data, (unsigned int)Size};
static std::unique_ptr<NSSDatabase> db(new NSSDatabase());
assert(db != nullptr);
CERTSubjectPublicKeyInfo *spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&data);
if (spki) {
SECKEYPublicKey *key = SECKEY_ExtractPublicKey(spki);
SECKEY_DestroyPublicKey(key);
}
SECKEY_DestroySubjectPublicKeyInfo(spki);
return 0;
}
REGISTER_FUZZING_TARGET("spki", spki_fuzzing_target, 1024, "SPKI Import")
......@@ -11,3 +11,7 @@ IMPORTS = nspr20/v4.8 \
RELEASE = nss
DIRS = coreconf lib cmd external_tests
ifdef FUZZ
DIRS += fuzz
endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment