diff --git a/tensorflow/opensource_only.files b/tensorflow/opensource_only.files index be0396dd113..d49b1c1e381 100644 --- a/tensorflow/opensource_only.files +++ b/tensorflow/opensource_only.files @@ -13,6 +13,7 @@ tensorflow/python/tpu/profiler/pip_package/README tensorflow/python/tpu/profiler/pip_package/build_pip_package.sh tensorflow/python/tpu/profiler/pip_package/setup.py tensorflow/python/tpu/tpu.bzl +tensorflow/security/fuzzing/tf_fuzzing.bzl tensorflow/stream_executor/build_defs.bzl tensorflow/third_party/BUILD tensorflow/third_party/__init__.py diff --git a/tensorflow/security/fuzzing/BUILD b/tensorflow/security/fuzzing/BUILD new file mode 100644 index 00000000000..887e1a23cdf --- /dev/null +++ b/tensorflow/security/fuzzing/BUILD @@ -0,0 +1,17 @@ +# Fuzzing TensorFlow. +# Since we use OSSFuzz, gather all fuzzers into a single place. +# This way, we can use tooling to determine the status of the fuzzing efforts. + +load( + "//tensorflow/security/fuzzing:tf_fuzzing.bzl", + "tf_fuzz_target", +) + +package( + licenses = ["notice"], # Apache 2.0 +) + +tf_fuzz_target( + name = "demo_fuzz", + srcs = ["demo_fuzz.cc"], +) diff --git a/tensorflow/security/fuzzing/demo_fuzz.cc b/tensorflow/security/fuzzing/demo_fuzz.cc new file mode 100644 index 00000000000..71777591694 --- /dev/null +++ b/tensorflow/security/fuzzing/demo_fuzz.cc @@ -0,0 +1,32 @@ +/* Copyright 2020 The TensorFlow Authors. 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. +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. +==============================================================================*/ +#include <cstdint> +#include <cstdlib> + +// This is a demo fuzzer to test that the entire framework functions correctly. +// Once we start moving the existing fuzzers to this framework we will delete +// this. +// TODO(mihaimaruseac): Delete this when no longer needed +void DemoFuzzer(const uint8_t* data, size_t size) { + // Trigger a small bug that should be found by the fuzzer quite quickly + if (size > 10 && size % 3 == 2) + if (data[0] > data[1]) + if (data[5] % data[2] == data[3]) abort(); +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + DemoFuzzer(data, size); + return 0; +} diff --git a/tensorflow/security/fuzzing/tf_fuzzing.bzl b/tensorflow/security/fuzzing/tf_fuzzing.bzl new file mode 100644 index 00000000000..63a8cbac704 --- /dev/null +++ b/tensorflow/security/fuzzing/tf_fuzzing.bzl @@ -0,0 +1,80 @@ +"""Definitions for rules to fuzz TensorFlow.""" + +# TensorFlow fuzzing can be done in open source too. +# +# For a fuzzer ${FUZZ} we have the following setup: +# - ${FUZZ}_fuzz.cc : the implementation of the fuzzer +# - corpus/${FUZZ}/... : public corpus for the fuzzer +# - dictionaries/${FUZZ}.dict : fuzzing dictionary for the fuzzer +# - ${FUZZ}_internal/... : internal data for the fuzzer +# +# If a fuzzer needs some framework to build, we can use the ${FUZZ}_internal/ +# directory to hold the harness. Or, if the infrastructure needs to be shared +# across multiple fuzzers (for example fuzzing ops), we can store it in other +# places in TF or move it to a different folder here. We will decide on these +# on a case by case basis, for now the ops fuzzing harness resides under +# tensorflow/core/kernels/fuzzing. +# +# The internal folder can also contain proto definitions (if using proto-based +# mutators to do structure aware fuzzing) or any other type of content that is +# not classified elsewhere. + +# tf_cc_fuzz_target is a cc_test modified to include fuzzing support. +def tf_fuzz_target( + name, + # Fuzzing specific arguments + fuzzing_dict = [], + corpus = [], + parsers = [], + # Reporting bugs arguments, not used in open source + componentid = None, + hotlists = [], + # Additional cc_test control + data = [], + deps = [], + tags = [], + # Remaining cc_test arguments + **kwargs): + """Specify how to build a TensorFlow fuzz target. + + Args: + name: Mandatory name of the fuzzer target. + + fuzzing_dict: An optional a set of dictionary files following + the AFL/libFuzzer dictionary syntax. + + corpus: An optional set of files used as the initial test corpus + for the target. When doing "bazel test" in the default null-fuzzer + (unittest) mode, these files are automatically passed to the target + function. + + parsers: An optional list of file extensions that the target supports. + Used by tools like autofuzz to reuse corpus sets across targets. + + componentid: Used internally for reporting fuzz discovered bugs. + + hotlists: Used internally for reporting fuzz discovered bugs. + + data: Additional data dependencies passed to the underlying cc_test rule. + + deps: An optional list of dependencies for the code you're fuzzing. + + tags: Additional tags passed to the underlying cc_test rule. + + **kwargs: Collects all remaining arguments and passes them to the + underlying cc_test rule generated by the macro. + """ + componentid = None + hotlists = None + + # Fuzzers in open source must be run manually + tags = tags + ["manual"] + + # Now, redirect to cc_test + native.cc_test( + name = name, + deps = deps, # TODO(mihaimaruseac): fuzzing lib? + data = data, # TODO(mihaimaruseac): dict, corpus, parsers?? + tags = tags, # TODO(mihaimaruseac): fuzzing tags? + **kwargs + )