diff options
author | Russ White <russ@riw.us> | 2018-07-29 14:33:43 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-29 14:33:43 +0200 |
commit | 155d6d4415cb9428450fe43ff71d756c47cf5ee0 (patch) | |
tree | 67610f775ae50422660dc484a7d3390ed91585f7 /zebra | |
parent | Merge pull request #2700 from sworleys/Netlink-Prefix-Len-Check (diff) | |
parent | Style, don't initialize netlink_read flag (diff) | |
download | frr-155d6d4415cb9428450fe43ff71d756c47cf5ee0.tar.xz frr-155d6d4415cb9428450fe43ff71d756c47cf5ee0.zip |
Merge pull request #2696 from sworleys/Netlink-Fuzz
zebra: Add code for fuzzing netlink
Diffstat (limited to 'zebra')
-rw-r--r-- | zebra/kernel_netlink.c | 99 | ||||
-rw-r--r-- | zebra/kernel_netlink.h | 4 | ||||
-rw-r--r-- | zebra/main.c | 49 |
3 files changed, 142 insertions, 10 deletions
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index cd881dcc2..c627bda4f 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -20,6 +20,11 @@ #include <zebra.h> +#if defined(HANDLE_NETLINK_FUZZING) +#include <stdio.h> +#include <string.h> +#endif /* HANDLE_NETLINK_FUZZING */ + #ifdef HAVE_NETLINK #include "linklist.h" @@ -293,6 +298,81 @@ static int netlink_information_fetch(struct nlmsghdr *h, ns_id_t ns_id, return 0; } +#if defined(HANDLE_NETLINK_FUZZING) +/* Using globals here to avoid adding function parameters */ + +/* Keep distinct filenames for netlink fuzzy collection */ +static unsigned int netlink_file_counter = 1; + +/* File name to read fuzzed netlink from */ +static char netlink_fuzz_file[MAXPATHLEN] = ""; + +/* Flag for whether to read from file or not */ +bool netlink_read; + +/** + * netlink_read_init() - Starts the message parser + * @fname: Filename to read. + */ +void netlink_read_init(const char *fname) +{ + snprintf(netlink_fuzz_file, MAXPATHLEN, "%s", fname); + /* Creating this fake socket for testing purposes */ + struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); + + netlink_parse_info(netlink_information_fetch, &zns->netlink, zns, 1, 0); +} + +/** + * netlink_write_incoming() - Writes all data received from netlink to a file + * @buf: Data from netlink. + * @size: Size of data. + * @counter: Counter for keeping filenames distinct. + */ +static void netlink_write_incoming(const char *buf, const unsigned int size, + unsigned int counter) +{ + char fname[MAXPATHLEN]; + FILE *f; + + zserv_privs.change(ZPRIVS_RAISE); + snprintf(fname, MAXPATHLEN, "%s/%s_%u", DAEMON_VTY_DIR, "netlink", + counter); + f = fopen(fname, "w"); + if (f) { + fwrite(buf, 1, size, f); + fclose(f); + } + zserv_privs.change(ZPRIVS_LOWER); +} + +/** + * netlink_read_file() - Reads netlink data from file + * @buf: Netlink buffer being overwritten. + * @fname: File name to read from. + * + * Return: Size of file. + */ +static long netlink_read_file(char *buf, const char *fname) +{ + FILE *f; + long file_bytes = -1; + + zserv_privs.change(ZPRIVS_RAISE); + f = fopen(fname, "r"); + if (f) { + fseek(f, 0, SEEK_END); + file_bytes = ftell(f); + rewind(f); + fread(buf, NL_RCV_PKT_BUF_SIZE, 1, f); + fclose(f); + } + zserv_privs.change(ZPRIVS_LOWER); + return file_bytes; +} + +#endif /* HANDLE_NETLINK_FUZZING */ + static int kernel_read(struct thread *thread) { struct zebra_ns *zns = (struct zebra_ns *)THREAD_ARG(thread); @@ -602,7 +682,18 @@ int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int), if (count && read_in >= count) return 0; +#if defined(HANDLE_NETLINK_FUZZING) + /* Check if reading and filename is set */ + if (netlink_read && '\0' != netlink_fuzz_file[0]) { + zlog_debug("Reading netlink fuzz file"); + status = netlink_read_file(buf, netlink_fuzz_file); + snl.nl_pid = 0; + } else { + status = recvmsg(nl->sock, &msg, 0); + } +#else status = recvmsg(nl->sock, &msg, 0); +#endif /* HANDLE_NETLINK_FUZZING */ if (status < 0) { if (errno == EINTR) continue; @@ -636,6 +727,14 @@ int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int), zlog_hexdump(buf, status); } +#if defined(HANDLE_NETLINK_FUZZING) + if (!netlink_read) { + zlog_debug("Writing incoming netlink message"); + netlink_write_incoming(buf, status, + netlink_file_counter++); + } +#endif /* HANDLE_NETLINK_FUZZING */ + read_in++; for (h = (struct nlmsghdr *)buf; (status >= 0 && NLMSG_OK(h, (unsigned int)status)); diff --git a/zebra/kernel_netlink.h b/zebra/kernel_netlink.h index 80bb876e0..65df15599 100644 --- a/zebra/kernel_netlink.h +++ b/zebra/kernel_netlink.h @@ -45,6 +45,10 @@ extern const char *nl_rtproto_to_str(uint8_t rtproto); extern const char *nl_family_to_str(uint8_t family); extern const char *nl_rttype_to_str(uint8_t rttype); +#if defined(HANDLE_NETLINK_FUZZING) +extern bool netlink_read; +extern void netlink_read_init(const char *fname); +#endif /* HANDLE_NETLINK_FUZZING */ extern int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int), struct nlsock *nl, struct zebra_ns *zns, int count, int startup); diff --git a/zebra/main.c b/zebra/main.c index 3e44a4170..0b8bc6a0a 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -54,6 +54,10 @@ #include "zebra/zebra_rnh.h" #include "zebra/zebra_pbr.h" +#if defined(HANDLE_NETLINK_FUZZING) +#include "zebra/kernel_netlink.h" +#endif /* HANDLE_NETLINK_FUZZING */ + #define ZEBRA_PTM_SUPPORT /* Zebra instance */ @@ -213,8 +217,11 @@ int main(int argc, char **argv) struct sockaddr_storage dummy; socklen_t dummylen; #if defined(HANDLE_ZAPI_FUZZING) - char *fuzzing = NULL; -#endif + char *zapi_fuzzing = NULL; +#endif /* HANDLE_ZAPI_FUZZING */ +#if defined(HANDLE_NETLINK_FUZZING) + char *netlink_fuzzing = NULL; +#endif /* HANDLE_NETLINK_FUZZING */ vrf_configure_backend(VRF_BACKEND_VRF_LITE); logicalrouter_configure_backend(LOGICALROUTER_BACKEND_NETNS); @@ -228,7 +235,10 @@ int main(int argc, char **argv) #endif #if defined(HANDLE_ZAPI_FUZZING) "c:" -#endif +#endif /* HANDLE_ZAPI_FUZZING */ +#if defined(HANDLE_NETLINK_FUZZING) + "w:" +#endif /* HANDLE_NETLINK_FUZZING */ , longopts, " -b, --batch Runs in batch mode\n" @@ -244,8 +254,11 @@ int main(int argc, char **argv) " --v6-rr-semantics Use v6 RR semantics\n" #endif /* HAVE_NETLINK */ #if defined(HANDLE_ZAPI_FUZZING) - " -c <file> Bypass normal startup and use this file for testing of zapi" -#endif + " -c <file> Bypass normal startup and use this file for testing of zapi\n" +#endif /* HANDLE_ZAPI_FUZZING */ +#if defined(HANDLE_NETLINK_FUZZING) + " -w <file> Bypass normal startup and use this file for testing of netlink input\n" +#endif /* HANDLE_NETLINK_FUZZING */ ); while (1) { @@ -306,9 +319,19 @@ int main(int argc, char **argv) #endif /* HAVE_NETLINK */ #if defined(HANDLE_ZAPI_FUZZING) case 'c': - fuzzing = optarg; + zapi_fuzzing = optarg; break; -#endif +#endif /* HANDLE_ZAPI_FUZZING */ +#if defined(HANDLE_NETLINK_FUZZING) + case 'w': + netlink_fuzzing = optarg; + /* This ensures we are aren't writing any of the + * startup netlink messages that happen when we + * just want to read. + */ + netlink_read = true; + break; +#endif /* HANDLE_NETLINK_FUZZING */ default: frr_help_exit(1); break; @@ -385,11 +408,17 @@ int main(int argc, char **argv) zebra_rnh_init(); #if defined(HANDLE_ZAPI_FUZZING) - if (fuzzing) { - zserv_read_file(fuzzing); + if (zapi_fuzzing) { + zserv_read_file(zapi_fuzzing); exit(0); } -#endif +#endif /* HANDLE_ZAPI_FUZZING */ +#if defined(HANDLE_NETLINK_FUZZING) + if (netlink_fuzzing) { + netlink_read_init(netlink_fuzzing); + exit(0); + } +#endif /* HANDLE_NETLINK_FUZZING */ frr_run(zebrad.master); |