diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2020-12-31 23:28:58 +0100 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2021-01-18 23:04:19 +0100 |
commit | 09f7c7c6687a6d0c939e7e54a433e0bab63292f8 (patch) | |
tree | eac34d88e3c4afd87d0a562a32b4f718054f90e2 /src/libsystemd-network | |
parent | meson: fix indentation (diff) | |
download | systemd-09f7c7c6687a6d0c939e7e54a433e0bab63292f8.tar.xz systemd-09f7c7c6687a6d0c939e7e54a433e0bab63292f8.zip |
fuzzers: move several fuzzers
Diffstat (limited to 'src/libsystemd-network')
-rw-r--r-- | src/libsystemd-network/fuzz-dhcp-server.c | 56 | ||||
-rw-r--r-- | src/libsystemd-network/fuzz-dhcp-server.options | 2 | ||||
-rw-r--r-- | src/libsystemd-network/fuzz-dhcp6-client.c | 62 | ||||
-rw-r--r-- | src/libsystemd-network/fuzz-dhcp6-client.options | 2 | ||||
-rw-r--r-- | src/libsystemd-network/fuzz-lldp.c | 43 | ||||
-rw-r--r-- | src/libsystemd-network/fuzz-lldp.options | 2 | ||||
-rw-r--r-- | src/libsystemd-network/fuzz-ndisc-rs.c | 61 | ||||
-rw-r--r-- | src/libsystemd-network/fuzz-ndisc-rs.options | 2 |
8 files changed, 230 insertions, 0 deletions
diff --git a/src/libsystemd-network/fuzz-dhcp-server.c b/src/libsystemd-network/fuzz-dhcp-server.c new file mode 100644 index 0000000000..c854d921c0 --- /dev/null +++ b/src/libsystemd-network/fuzz-dhcp-server.c @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> + +#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); + + (void) dhcp_server_handle_message(server, (DHCPMessage*)data, size); + + return 0; +} diff --git a/src/libsystemd-network/fuzz-dhcp-server.options b/src/libsystemd-network/fuzz-dhcp-server.options new file mode 100644 index 0000000000..5c330e5cec --- /dev/null +++ b/src/libsystemd-network/fuzz-dhcp-server.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 600 diff --git a/src/libsystemd-network/fuzz-dhcp6-client.c b/src/libsystemd-network/fuzz-dhcp6-client.c new file mode 100644 index 0000000000..e5e70dd606 --- /dev/null +++ b/src/libsystemd-network/fuzz-dhcp6-client.c @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include <unistd.h> + +#include "sd-dhcp6-client.h" +#include "sd-event.h" + +#include "dhcp6-internal.h" +#include "dhcp6-protocol.h" +#include "fd-util.h" +#include "fuzz.h" + +static int test_dhcp_fd[2] = { -1, -1 }; + +int dhcp6_network_send_udp_socket(int s, struct in6_addr *server_address, + const void *packet, size_t len) { + return len; +} + +int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) { + assert_se(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_dhcp_fd) >= 0); + return test_dhcp_fd[0]; +} + +static void fuzz_client(const uint8_t *data, size_t size, bool is_information_request_enabled) { + _cleanup_(sd_event_unrefp) sd_event *e; + _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL; + struct in6_addr address = { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 } } }; + + assert_se(sd_event_new(&e) >= 0); + assert_se(sd_dhcp6_client_new(&client) >= 0); + assert_se(sd_dhcp6_client_attach_event(client, e, 0) >= 0); + assert_se(sd_dhcp6_client_set_ifindex(client, 42) == 0); + assert_se(sd_dhcp6_client_set_local_address(client, &address) >= 0); + assert_se(sd_dhcp6_client_set_information_request(client, is_information_request_enabled) == 0); + + assert_se(sd_dhcp6_client_start(client) >= 0); + + if (size >= sizeof(DHCP6Message)) + assert_se(sd_dhcp6_client_set_transaction_id(client, htobe32(0x00ffffff) & ((const DHCP6Message *) data)->transaction_id) == 0); + + assert_se(write(test_dhcp_fd[1], data, size) == (ssize_t) size); + + sd_event_run(e, (uint64_t) -1); + + assert_se(sd_dhcp6_client_stop(client) >= 0); + + test_dhcp_fd[1] = safe_close(test_dhcp_fd[1]); +} + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + if (size > 65536) + return 0; + + /* This triggers client_receive_advertise */ + fuzz_client(data, size, false); + + /* This triggers client_receive_reply */ + fuzz_client(data, size, true); + + return 0; +} diff --git a/src/libsystemd-network/fuzz-dhcp6-client.options b/src/libsystemd-network/fuzz-dhcp6-client.options new file mode 100644 index 0000000000..678d526b1e --- /dev/null +++ b/src/libsystemd-network/fuzz-dhcp6-client.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 65536 diff --git a/src/libsystemd-network/fuzz-lldp.c b/src/libsystemd-network/fuzz-lldp.c new file mode 100644 index 0000000000..5747135b32 --- /dev/null +++ b/src/libsystemd-network/fuzz-lldp.c @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include <errno.h> +#include <unistd.h> + +#include "sd-event.h" +#include "sd-lldp.h" + +#include "fd-util.h" +#include "fuzz.h" +#include "lldp-network.h" + +static int test_fd[2] = { -1, -1 }; + +int lldp_network_bind_raw_socket(int ifindex) { + if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) < 0) + return -errno; + + return test_fd[0]; +} + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + _cleanup_(sd_event_unrefp) sd_event *e = NULL; + _cleanup_(sd_lldp_unrefp) sd_lldp *lldp = NULL; + + if (size > 2048) + return 0; + + assert_se(sd_event_new(&e) == 0); + assert_se(sd_lldp_new(&lldp) >= 0); + assert_se(sd_lldp_set_ifindex(lldp, 42) >= 0); + assert_se(sd_lldp_attach_event(lldp, e, 0) >= 0); + assert_se(sd_lldp_start(lldp) >= 0); + + assert_se(write(test_fd[1], data, size) == (ssize_t) size); + assert_se(sd_event_run(e, 0) >= 0); + + assert_se(sd_lldp_stop(lldp) >= 0); + assert_se(sd_lldp_detach_event(lldp) >= 0); + test_fd[1] = safe_close(test_fd[1]); + + return 0; +} diff --git a/src/libsystemd-network/fuzz-lldp.options b/src/libsystemd-network/fuzz-lldp.options new file mode 100644 index 0000000000..60bd9b0b2f --- /dev/null +++ b/src/libsystemd-network/fuzz-lldp.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 2048 diff --git a/src/libsystemd-network/fuzz-ndisc-rs.c b/src/libsystemd-network/fuzz-ndisc-rs.c new file mode 100644 index 0000000000..d74cd2fffc --- /dev/null +++ b/src/libsystemd-network/fuzz-ndisc-rs.c @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include <arpa/inet.h> +#include <netinet/icmp6.h> +#include <unistd.h> + +#include "alloc-util.h" +#include "icmp6-util.h" +#include "fuzz.h" +#include "sd-ndisc.h" +#include "socket-util.h" +#include "ndisc-internal.h" + +static int test_fd[2] = { -1, -1 }; + +int icmp6_bind_router_solicitation(int index) { + assert_se(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) >= 0); + return test_fd[0]; +} + +int icmp6_bind_router_advertisement(int index) { + return -ENOSYS; +} + +int icmp6_receive(int fd, void *iov_base, size_t iov_len, + struct in6_addr *dst, triple_timestamp *timestamp) { + assert_se(read(fd, iov_base, iov_len) == (ssize_t) iov_len); + + if (timestamp) + triple_timestamp_get(timestamp); + + return 0; +} + +int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) { + return 0; +} + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + struct ether_addr mac_addr = { + .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'} + }; + _cleanup_(sd_event_unrefp) sd_event *e = NULL; + _cleanup_(sd_ndisc_unrefp) sd_ndisc *nd = NULL; + + if (size > 2048) + return 0; + + assert_se(sd_event_new(&e) >= 0); + assert_se(sd_ndisc_new(&nd) >= 0); + assert_se(sd_ndisc_attach_event(nd, e, 0) >= 0); + assert_se(sd_ndisc_set_ifindex(nd, 42) >= 0); + assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0); + assert_se(sd_ndisc_start(nd) >= 0); + assert_se(write(test_fd[1], data, size) == (ssize_t) size); + (void) sd_event_run(e, (uint64_t) -1); + assert_se(sd_ndisc_stop(nd) >= 0); + close(test_fd[1]); + + return 0; +} diff --git a/src/libsystemd-network/fuzz-ndisc-rs.options b/src/libsystemd-network/fuzz-ndisc-rs.options new file mode 100644 index 0000000000..60bd9b0b2f --- /dev/null +++ b/src/libsystemd-network/fuzz-ndisc-rs.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 2048 |