summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Rudenberg <jonathan@titanous.com>2018-01-14 01:51:07 +0100
committerJonathan Rudenberg <jonathan@titanous.com>2018-01-17 19:57:06 +0100
commit7db7d5b73368fde010a258a5b2c48faf0d3e82c8 (patch)
tree61a751696af8f102076b7228ec1af7829ab4f416
parentMerge pull request #7903 from yuwata/fix-7863 (diff)
downloadsystemd-7db7d5b73368fde010a258a5b2c48faf0d3e82c8.tar.xz
systemd-7db7d5b73368fde010a258a5b2c48faf0d3e82c8.zip
fuzz: add initial fuzzing infrastructure
The fuzzers will be used by oss-fuzz to automatically and continuously fuzz systemd. This commit includes the build tooling necessary to build fuzz targets, and a fuzzer for the DNS packet parser.
-rw-r--r--meson.build51
-rw-r--r--meson_options.txt3
-rwxr-xr-xscripts/oss-fuzz.sh36
-rw-r--r--src/fuzz/fuzz-dns-packet.c43
-rw-r--r--src/fuzz/fuzz-dns-packet.options2
-rw-r--r--src/fuzz/fuzz-main.c51
-rw-r--r--src/fuzz/fuzz.h23
-rw-r--r--src/fuzz/meson.build25
-rwxr-xr-x[-rw-r--r--]tools/meson-check-api-docs.sh0
9 files changed, 232 insertions, 2 deletions
diff --git a/meson.build b/meson.build
index 5066ccf432..784a138f2f 100644
--- a/meson.build
+++ b/meson.build
@@ -268,6 +268,11 @@ if get_option('tests') != 'false'
endif
endif
+ossfuzz = get_option('oss-fuzz')
+if ossfuzz
+ fuzzing_engine = meson.get_compiler('cpp').find_library('FuzzingEngine')
+endif
+
foreach arg : ['-Wextra',
'-Werror=undef',
'-Wlogical-op',
@@ -302,7 +307,6 @@ foreach arg : ['-Wextra',
'-fvisibility=hidden',
'-fstack-protector',
'-fstack-protector-strong',
- '-fPIE',
'--param=ssp-buffer-size=4',
]
if cc.has_argument(arg)
@@ -310,6 +314,14 @@ foreach arg : ['-Wextra',
endif
endforeach
+# the oss-fuzz fuzzers are not built with -fPIE, so don't
+# enable it when we are linking against them
+if not ossfuzz
+ if cc.has_argument('-fPIE')
+ add_project_arguments('-fPIE', language : 'c')
+ endif
+endif
+
# "negative" arguments: gcc on purpose does not return an error for "-Wno-"
# arguments, just emits a warnings. So test for the "positive" version instead.
foreach arg : ['unused-parameter',
@@ -360,7 +372,7 @@ foreach arg : ['-Wl,-z,relro',
cc.cmd_array(), '-x', 'c', arg,
'-include', link_test_c).returncode() == 0
message('Linking with @0@ supported: @1@'.format(arg, have ? 'yes' : 'no'))
- if have
+ if have and (arg != '-pie' or not ossfuzz)
add_project_link_arguments(arg, language : 'c')
endif
endforeach
@@ -1178,6 +1190,7 @@ endforeach
want_tests = get_option('tests')
install_tests = get_option('install-tests')
tests = []
+fuzzers = []
conf.set10('SYSTEMD_SLOW_TESTS_DEFAULT', get_option('slow-tests'))
@@ -1303,6 +1316,7 @@ subdir('src/vconsole')
subdir('src/boot/efi')
subdir('src/test')
+subdir('src/fuzz')
subdir('rules')
subdir('test')
@@ -2457,6 +2471,39 @@ test('test-libudev-sym',
############################################################
+fuzzer_exes = []
+
+foreach tuple : fuzzers
+ sources = tuple[0]
+ link_with = tuple[1].length() > 0 ? tuple[1] : [libshared]
+ dependencies = tuple[2]
+ defs = tuple.length() >= 4 ? tuple[3] : []
+ incs = tuple.length() >= 5 ? tuple[4] : includes
+
+ if ossfuzz
+ dependencies += fuzzing_engine
+ else
+ sources += 'src/fuzz/fuzz-main.c'
+ endif
+
+ name = sources[0].split('/')[-1].split('.')[0]
+
+ fuzzer_exes += executable(
+ name,
+ sources,
+ include_directories : [incs, include_directories('src/fuzz')],
+ link_with : link_with,
+ dependencies : dependencies,
+ c_args : defs,
+ install : false)
+endforeach
+
+run_target('fuzzers',
+ depends : fuzzer_exes,
+ command : ['true'])
+
+############################################################
+
make_directive_index_py = find_program('tools/make-directive-index.py')
make_man_index_py = find_program('tools/make-man-index.py')
xml_helper_py = find_program('tools/xml_helper.py')
diff --git a/meson_options.txt b/meson_options.txt
index af8be576a1..9e7cad7471 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -291,3 +291,6 @@ option('slow-tests', type : 'boolean', value : 'false',
description : 'run the slow tests by default')
option('install-tests', type : 'boolean', value : 'false',
description : 'install test executables')
+
+option('oss-fuzz', type : 'boolean', value : 'false',
+ description : 'build against oss-fuzz')
diff --git a/scripts/oss-fuzz.sh b/scripts/oss-fuzz.sh
new file mode 100755
index 0000000000..b871d744b9
--- /dev/null
+++ b/scripts/oss-fuzz.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# Copyright 2017 Jonathan Rudenberg
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# systemd is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with systemd; If not, see <http://www.gnu.org/licenses/>.
+
+set -ex
+
+export LC_CTYPE=C.UTF-8
+
+meson $WORK -Doss-fuzz=true -Db_lundef=false -Dseccomp=false -Dlz4=false -Dlibiptc=false -Dlibidn=false
+ninja -C $WORK fuzzers
+
+# get DNS packet corpus
+df=$WORK/dns-fuzzing
+rm -rf $df
+git clone --depth 1 https://github.com/CZ-NIC/dns-fuzzing $df
+zip -jqr $OUT/fuzz-dns-packet_seed_corpus.zip $df/packet
+
+mkdir -p $OUT/src/shared
+mv $WORK/src/shared/libsystemd-shared-*.so $OUT/src/shared
+
+find $WORK -maxdepth 1 -type f -executable -name "fuzz-*" -exec mv {} $OUT \;
+mv $WORK/*.so src/fuzz/*.options $OUT
diff --git a/src/fuzz/fuzz-dns-packet.c b/src/fuzz/fuzz-dns-packet.c
new file mode 100644
index 0000000000..3d8d79a42d
--- /dev/null
+++ b/src/fuzz/fuzz-dns-packet.c
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+/***
+ Copyright 2018 Jonathan Rudenberg
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "fuzz.h"
+#include "resolved-dns-packet.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
+ int r;
+
+ if (size > DNS_PACKET_SIZE_MAX)
+ return 0;
+
+ r = dns_packet_new(&p, DNS_PROTOCOL_DNS, 0, DNS_PACKET_SIZE_MAX);
+ if (r < 0)
+ return 0;
+ p->size = 0; /* by default append starts after the header, undo that */
+ dns_packet_append_blob(p, data, size, NULL);
+ if (size < DNS_PACKET_HEADER_SIZE) {
+ /* make sure we pad the packet back up to the minimum header size */
+ assert(p->allocated >= DNS_PACKET_HEADER_SIZE);
+ memzero(DNS_PACKET_DATA(p) + size, DNS_PACKET_HEADER_SIZE - size);
+ p->size = DNS_PACKET_HEADER_SIZE;
+ }
+ dns_packet_extract(p);
+
+ return 0;
+}
diff --git a/src/fuzz/fuzz-dns-packet.options b/src/fuzz/fuzz-dns-packet.options
new file mode 100644
index 0000000000..0824b19fab
--- /dev/null
+++ b/src/fuzz/fuzz-dns-packet.options
@@ -0,0 +1,2 @@
+[libfuzzer]
+max_len = 65535
diff --git a/src/fuzz/fuzz-main.c b/src/fuzz/fuzz-main.c
new file mode 100644
index 0000000000..ca9abe9068
--- /dev/null
+++ b/src/fuzz/fuzz-main.c
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+/***
+ Copyright 2018 Jonathan Rudenberg
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "alloc-util.h"
+#include "log.h"
+#include "fileio.h"
+#include "fuzz.h"
+
+/* This is a test driver for the systemd fuzzers that provides main function
+ * for regression testing outside of oss-fuzz (https://github.com/google/oss-fuzz)
+ *
+ * It reads files named on the command line and passes them one by one into the
+ * fuzzer that it is compiled into. */
+
+int main(int argc, char **argv) {
+ int i, r;
+ size_t size;
+ char *name;
+
+ log_set_max_level(LOG_DEBUG);
+ for (i = 1; i < argc; i++) {
+ _cleanup_free_ char *buf = NULL;
+
+ name = argv[i];
+ r = read_full_file(name, &buf, &size);
+ if (r < 0) {
+ log_error_errno(r, "Failed to open '%s': %m", name);
+ return EXIT_FAILURE;
+ }
+ printf("%s... ", name);
+ fflush(stdout);
+ (void)LLVMFuzzerTestOneInput((uint8_t*)buf, size);
+ printf("ok\n");
+ }
+ return EXIT_SUCCESS;
+}
diff --git a/src/fuzz/fuzz.h b/src/fuzz/fuzz.h
new file mode 100644
index 0000000000..5293c5762f
--- /dev/null
+++ b/src/fuzz/fuzz.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+/***
+ Copyright 2018 Jonathan Rudenberg
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stddef.h>
+#include <stdint.h>
+
+/* The entry point into the fuzzer */
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
diff --git a/src/fuzz/meson.build b/src/fuzz/meson.build
new file mode 100644
index 0000000000..66cdf13dbd
--- /dev/null
+++ b/src/fuzz/meson.build
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: LGPL-2.1+
+# Copyright 2018 Jonathan Rudenberg
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# systemd is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with systemd; If not, see <http://www.gnu.org/licenses/>.
+
+fuzzers += [
+ [['src/fuzz/fuzz-dns-packet.c',
+ dns_type_headers],
+ [libsystemd_resolve_core,
+ libshared],
+ [libgcrypt,
+ libgpg_error,
+ libm]],
+]
diff --git a/tools/meson-check-api-docs.sh b/tools/meson-check-api-docs.sh
index 5bc808c1e4..5bc808c1e4 100644..100755
--- a/tools/meson-check-api-docs.sh
+++ b/tools/meson-check-api-docs.sh