summaryrefslogtreecommitdiffstats
path: root/zebra/kernel_netlink.c
diff options
context:
space:
mode:
authorRuss White <russ@riw.us>2018-07-29 14:33:43 +0200
committerGitHub <noreply@github.com>2018-07-29 14:33:43 +0200
commit155d6d4415cb9428450fe43ff71d756c47cf5ee0 (patch)
tree67610f775ae50422660dc484a7d3390ed91585f7 /zebra/kernel_netlink.c
parentMerge pull request #2700 from sworleys/Netlink-Prefix-Len-Check (diff)
parentStyle, don't initialize netlink_read flag (diff)
downloadfrr-155d6d4415cb9428450fe43ff71d756c47cf5ee0.tar.xz
frr-155d6d4415cb9428450fe43ff71d756c47cf5ee0.zip
Merge pull request #2696 from sworleys/Netlink-Fuzz
zebra: Add code for fuzzing netlink
Diffstat (limited to 'zebra/kernel_netlink.c')
-rw-r--r--zebra/kernel_netlink.c99
1 files changed, 99 insertions, 0 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));