fuzz: add DHCP server fuzzer
authorJonathan Rudenberg <jonathan@titanous.com>
Sat, 20 Jan 2018 00:44:56 +0000 (19:44 -0500)
committerJonathan Rudenberg <jonathan@titanous.com>
Sat, 20 Jan 2018 02:48:14 +0000 (21:48 -0500)
scripts/oss-fuzz.sh
src/fuzz/fuzz-dhcp-server.c [new file with mode: 0644]
src/fuzz/fuzz-dns-server.options [new file with mode: 0644]
src/fuzz/meson.build
test/fuzz-corpus/dhcp-server/discover-existing [new file with mode: 0644]
test/fuzz-corpus/dhcp-server/discover-new [new file with mode: 0644]
test/fuzz-corpus/dhcp-server/release [new file with mode: 0644]
test/fuzz-corpus/dhcp-server/request-existing [new file with mode: 0644]
test/fuzz-corpus/dhcp-server/request-new [new file with mode: 0644]
test/fuzz-corpus/dhcp-server/request-reboot [new file with mode: 0644]
test/fuzz-corpus/dhcp-server/request-renew [new file with mode: 0644]

index 8ae7625..2c4e58e 100755 (executable)
@@ -43,7 +43,11 @@ fi
 meson $build -D$fuzzflag -Db_lundef=false
 ninja -C $build fuzzers
 
-# get DNS packet corpus
+for d in "$(dirname "$0")/../test/fuzz-corpus/"*; do
+        zip -jqr $OUT/fuzz-$(basename "$d")_seed_corpus.zip "$d"
+done
+
+# get fuzz-dns-packet corpus
 df=$build/dns-fuzzing
 git clone --depth 1 https://github.com/CZ-NIC/dns-fuzzing $df
 zip -jqr $OUT/fuzz-dns-packet_seed_corpus.zip $df/packet
diff --git a/src/fuzz/fuzz-dhcp-server.c b/src/fuzz/fuzz-dhcp-server.c
new file mode 100644 (file)
index 0000000..bdebb37
--- /dev/null
@@ -0,0 +1,68 @@
+/* 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 "sd-dhcp-server.c"
+
+/* stub out network so that the server doesn't send */
+ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) {
+        return len;
+}
+
+ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags) {
+        return 0;
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+        _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
+        struct in_addr address = {.s_addr = htobe32(UINT32_C(10) << 24 | UINT32_C(1))};
+        static const uint8_t chaddr[] = {3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3};
+        uint8_t *client_id;
+        DHCPLease *lease;
+        int pool_offset;
+
+        if (size < sizeof(DHCPMessage))
+                return 0;
+
+        assert_se(sd_dhcp_server_new(&server, 1) >= 0);
+        server->fd = open("/dev/null", O_RDWR|O_CLOEXEC|O_NOCTTY);
+        assert_se(server->fd >= 0);
+        assert_se(sd_dhcp_server_configure_pool(server, &address, 24, 0, 0) >= 0);
+
+        /* add a lease to the pool to expose additional code paths */
+        client_id = malloc(2);
+        assert_se(client_id);
+        client_id[0] = 2;
+        client_id[1] = 2;
+        lease = new0(DHCPLease, 1);
+        assert_se(lease);
+        lease->client_id.length = 2;
+        lease->client_id.data = client_id;
+        lease->address = htobe32(UINT32_C(10) << 24 | UINT32_C(2));
+        lease->gateway = htobe32(UINT32_C(10) << 24 | UINT32_C(1));
+        lease->expiration = UINT64_MAX;
+        memcpy(lease->chaddr, chaddr, 16);
+        pool_offset = get_pool_offset(server, lease->address);
+        server->bound_leases[pool_offset] = lease;
+        assert_se(hashmap_put(server->leases_by_client_id, &lease->client_id, lease) >= 0);
+
+        dhcp_server_handle_message(server, (DHCPMessage*)data, size);
+
+        return 0;
+}
diff --git a/src/fuzz/fuzz-dns-server.options b/src/fuzz/fuzz-dns-server.options
new file mode 100644 (file)
index 0000000..5c330e5
--- /dev/null
@@ -0,0 +1,2 @@
+[libfuzzer]
+max_len = 600
index 66cdf13..09a8c8a 100644 (file)
@@ -22,4 +22,9 @@ fuzzers += [
          [libgcrypt,
           libgpg_error,
           libm]],
+        [['src/fuzz/fuzz-dhcp-server.c',
+          ],
+         [libsystemd_network,
+          libshared],
+          []]
 ]
diff --git a/test/fuzz-corpus/dhcp-server/discover-existing b/test/fuzz-corpus/dhcp-server/discover-existing
new file mode 100644 (file)
index 0000000..1e26bf0
Binary files /dev/null and b/test/fuzz-corpus/dhcp-server/discover-existing differ
diff --git a/test/fuzz-corpus/dhcp-server/discover-new b/test/fuzz-corpus/dhcp-server/discover-new
new file mode 100644 (file)
index 0000000..feeae55
Binary files /dev/null and b/test/fuzz-corpus/dhcp-server/discover-new differ
diff --git a/test/fuzz-corpus/dhcp-server/release b/test/fuzz-corpus/dhcp-server/release
new file mode 100644 (file)
index 0000000..4f3eadb
Binary files /dev/null and b/test/fuzz-corpus/dhcp-server/release differ
diff --git a/test/fuzz-corpus/dhcp-server/request-existing b/test/fuzz-corpus/dhcp-server/request-existing
new file mode 100644 (file)
index 0000000..9f7a0d8
Binary files /dev/null and b/test/fuzz-corpus/dhcp-server/request-existing differ
diff --git a/test/fuzz-corpus/dhcp-server/request-new b/test/fuzz-corpus/dhcp-server/request-new
new file mode 100644 (file)
index 0000000..fc6f586
Binary files /dev/null and b/test/fuzz-corpus/dhcp-server/request-new differ
diff --git a/test/fuzz-corpus/dhcp-server/request-reboot b/test/fuzz-corpus/dhcp-server/request-reboot
new file mode 100644 (file)
index 0000000..fde74b2
Binary files /dev/null and b/test/fuzz-corpus/dhcp-server/request-reboot differ
diff --git a/test/fuzz-corpus/dhcp-server/request-renew b/test/fuzz-corpus/dhcp-server/request-renew
new file mode 100644 (file)
index 0000000..8dcda2a
Binary files /dev/null and b/test/fuzz-corpus/dhcp-server/request-renew differ