summaryrefslogtreecommitdiffstats
path: root/zebra
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
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')
-rw-r--r--zebra/kernel_netlink.c99
-rw-r--r--zebra/kernel_netlink.h4
-rw-r--r--zebra/main.c49
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);