From 9e72f717e039e0416299454cf234210ca61f2a16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren=20Tempel?= Date: Tue, 13 Aug 2019 14:53:30 +0200 Subject: [PATCH] sys/fuzzing: Initialize This adds a utility module which is used to write applications for fuzzing RIOT network modules. The module provides a dummy network interface which is configured with a static IPv6 addresses for modules which perform operations on the underlying network interface. Besides, it contains a utility function for transforming data received on standard input into a `gnrc_pktsnip_t`. --- Makefile.dep | 6 +++ sys/fuzzing/Makefile | 1 + sys/fuzzing/fuzzing.c | 89 +++++++++++++++++++++++++++++++++++++++++++ sys/fuzzing/netdev.c | 52 +++++++++++++++++++++++++ sys/include/fuzzing.h | 57 +++++++++++++++++++++++++++ 5 files changed, 205 insertions(+) create mode 100644 sys/fuzzing/Makefile create mode 100644 sys/fuzzing/fuzzing.c create mode 100644 sys/fuzzing/netdev.c create mode 100644 sys/include/fuzzing.h diff --git a/Makefile.dep b/Makefile.dep index 6151775a9b..5040a3a6d1 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -690,6 +690,12 @@ ifneq (,$(filter evtimer,$(USEMODULE))) USEMODULE += xtimer endif +ifneq (,$(filter fuzzing,$(USEMODULE))) + USEMODULE += netdev_test + USEMODULE += gnrc_netif + USEMODULE += gnrc_pktbuf_malloc +endif + ifneq (,$(filter can_linux,$(USEMODULE))) LINKFLAGS += -lsocketcan endif diff --git a/sys/fuzzing/Makefile b/sys/fuzzing/Makefile new file mode 100644 index 0000000000..48422e909a --- /dev/null +++ b/sys/fuzzing/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/sys/fuzzing/fuzzing.c b/sys/fuzzing/fuzzing.c new file mode 100644 index 0000000000..3f7f1e5794 --- /dev/null +++ b/sys/fuzzing/fuzzing.c @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2019 Sören Tempel + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +#include +#include +#include + +#include "assert.h" +#include "fuzzing.h" + +#include "net/ipv6/addr.h" +#include "net/gnrc/netif.h" +#include "net/gnrc/pktbuf.h" +#include "net/gnrc/pkt.h" + +extern int fuzzing_netdev(gnrc_netif_t *); +extern void fuzzing_netdev_wait(void); + +/* used by gnrc_pktbuf_malloc to exit on free */ +gnrc_pktsnip_t *gnrc_pktbuf_fuzzptr = NULL; + +/* buffer sizes for reading from an fd */ +#define FUZZING_BSIZE 1024 +#define FUZZING_BSTEP 128 + +int +fuzzing_init(ipv6_addr_t *addr, unsigned pfx_len) +{ + static gnrc_netif_t netif; + + if (fuzzing_netdev(&netif)) { + return -ENXIO; + } + + fuzzing_netdev_wait(); + if (addr != NULL) { + if (gnrc_netif_ipv6_addr_add(&netif, addr, pfx_len, 0) != sizeof(ipv6_addr_t)) { + return -EINVAL; + } + } + + return 0; +} + +int +fuzzing_read_packet(int fd, gnrc_pktsnip_t *pkt) +{ + ssize_t r; + size_t csiz, rsiz; + + /* can only be called once currently */ + assert(gnrc_pktbuf_fuzzptr == NULL); + + csiz = 0; + rsiz = FUZZING_BSIZE; + if (gnrc_pktbuf_realloc_data(pkt, rsiz)) { + return -ENOMEM; + } + + while ((r = read(fd, &((char *)pkt->data)[csiz], rsiz)) > 0) { + assert((size_t)r <= rsiz); + + csiz += r; + rsiz -= r; + + if (rsiz == 0) { + if (gnrc_pktbuf_realloc_data(pkt, csiz + FUZZING_BSTEP)) { + return -ENOMEM; + } + rsiz += FUZZING_BSTEP; + } + } + if (r == -1) { + return -errno; + } + + /* shrink packet to actual size */ + if (gnrc_pktbuf_realloc_data(pkt, csiz)) { + return -ENOMEM; + } + + gnrc_pktbuf_fuzzptr = pkt; + return 0; +} diff --git a/sys/fuzzing/netdev.c b/sys/fuzzing/netdev.c new file mode 100644 index 0000000000..a079e6698d --- /dev/null +++ b/sys/fuzzing/netdev.c @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2019 Sören Tempel + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +#include + +#include "mutex.h" +#include "thread.h" +#include "fuzzing.h" + +#include "net/netdev_test.h" +#include "net/gnrc/netif/raw.h" +#include "net/gnrc/netif.h" + +/* unlocked once the device is initialized. */ +static mutex_t initmtx = MUTEX_INIT_LOCKED; + +static int _dev_init(netdev_t *netdev) +{ + (void)netdev; + mutex_unlock(&initmtx); + return 0; +} + +static int _dev_get_device_type(netdev_t *netdev, void *value, size_t max_len) +{ + assert(max_len == sizeof(uint16_t)); + (void)netdev; + + *((uint16_t *)value) = NETDEV_TYPE_SLIP; + return sizeof(uint16_t); +} + +int fuzzing_netdev(gnrc_netif_t *netif) { + static netdev_test_t dev; + static char _netif_stack[THREAD_STACKSIZE_DEFAULT]; + + netdev_test_setup(&dev, NULL); + netdev_test_set_init_cb(&dev, _dev_init); + netdev_test_set_get_cb(&dev, NETOPT_DEVICE_TYPE, _dev_get_device_type); + + return gnrc_netif_raw_create(netif, _netif_stack, THREAD_STACKSIZE_DEFAULT, + GNRC_NETIF_PRIO, "dummy_netif", (netdev_t *)&dev); +} + +void fuzzing_netdev_wait(void) { + mutex_lock(&initmtx); +} diff --git a/sys/include/fuzzing.h b/sys/include/fuzzing.h new file mode 100644 index 0000000000..f5e8e4c93d --- /dev/null +++ b/sys/include/fuzzing.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2019 Sören Tempel + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @defgroup sys_fuzzing FUZZING utilities + * @ingroup sys + * + * @brief Various utilities for fuzzing network applications. + * + * @{ + * @file + * + * @author Sören Tempel + */ + +#ifndef FUZZING_H +#define FUZZING_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "net/ipv6/addr.h" +#include "net/gnrc/pkt.h" + +/** + * @brief Initialize dummy network interface with given address. + * + * @param addr IPv6 address to use for interface, can be NULL. + * @param pfx_len The prefix length of @p addr, ignored if @p addr is NULL. + * + * @return 0 on success, non-zero otherwise. + */ +int fuzzing_init(ipv6_addr_t *addr, unsigned pfx_len); + +/** + * @brief Read a network packet from the given file descriptor. + * + * @param fd File descriptor to read packet from. + * @param pkt Allocated packet structure to write packet to, + * will be resized accordingly. + * + * @return 0 on success, non-zero otherwise. + */ +int fuzzing_read_packet(int fd, gnrc_pktsnip_t *pkt); + +#ifdef __cplusplus +} +#endif + +/** @} */ +#endif /* FUZZING_H */