aboutsummaryrefslogtreecommitdiff
path: root/testprogs/fuzz
diff options
context:
space:
mode:
authorJoseph Mingrone <jrm@FreeBSD.org>2023-03-27 18:45:17 +0000
committerJoseph Mingrone <jrm@FreeBSD.org>2023-03-27 18:45:17 +0000
commit35af88c96350eb786f1198dfb6b29a171016e6bf (patch)
treee883c1f8391d5ca1afd57abd8ed9d2cd7c274b0b /testprogs/fuzz
parent20616273d52132557e786a8aea1637be4c218a08 (diff)
Diffstat (limited to 'testprogs/fuzz')
-rw-r--r--testprogs/fuzz/CMakeLists.txt43
-rw-r--r--testprogs/fuzz/fuzz_both.c101
-rw-r--r--testprogs/fuzz/fuzz_both.options2
-rw-r--r--testprogs/fuzz/fuzz_filter.c43
-rw-r--r--testprogs/fuzz/fuzz_filter.options2
-rw-r--r--testprogs/fuzz/fuzz_pcap.c80
-rw-r--r--testprogs/fuzz/fuzz_pcap.options2
-rw-r--r--testprogs/fuzz/onefile.c54
8 files changed, 327 insertions, 0 deletions
diff --git a/testprogs/fuzz/CMakeLists.txt b/testprogs/fuzz/CMakeLists.txt
new file mode 100644
index 000000000000..67250cca4349
--- /dev/null
+++ b/testprogs/fuzz/CMakeLists.txt
@@ -0,0 +1,43 @@
+add_executable(fuzz_pcap onefile.c fuzz_pcap.c)
+target_link_libraries(fuzz_pcap ${ARGN} ${LIBRARY_NAME}_static ${PCAP_LINK_LIBRARIES})
+if(NOT "${SANITIZER_FLAGS}" STREQUAL "")
+ set_target_properties(fuzz_pcap PROPERTIES
+ LINK_FLAGS "${SANITIZER_FLAGS}")
+endif()
+
+add_executable(fuzz_filter onefile.c fuzz_filter.c)
+target_link_libraries(fuzz_filter ${ARGN} ${LIBRARY_NAME}_static ${PCAP_LINK_LIBRARIES})
+if(NOT "${SANITIZER_FLAGS}" STREQUAL "")
+ set_target_properties(fuzz_filter PROPERTIES
+ LINK_FLAGS "${SANITIZER_FLAGS}")
+endif()
+
+add_executable(fuzz_both onefile.c fuzz_both.c)
+target_link_libraries(fuzz_both ${ARGN} ${LIBRARY_NAME}_static ${PCAP_LINK_LIBRARIES})
+if(NOT "${SANITIZER_FLAGS}" STREQUAL "")
+ set_target_properties(fuzz_both PROPERTIES
+ LINK_FLAGS "${SANITIZER_FLAGS}")
+endif()
+
+if(ENABLE_REMOTE AND "$ENV{CFLAGS}" MATCHES "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION")
+add_executable(fuzz_rclient onefile.c fuzz_rclient.c)
+target_link_libraries(fuzz_rclient ${ARGN} ${LIBRARY_NAME}_static ${PCAP_LINK_LIBRARIES})
+if(NOT "${SANITIZER_FLAGS}" STREQUAL "")
+ set_target_properties(fuzz_rclient PROPERTIES
+ LINK_FLAGS "${SANITIZER_FLAGS}")
+endif()
+
+add_executable(fuzz_rserver onefile.c fuzz_rserver.c ../../rpcapd/daemon.c)
+check_function_exists(crypt HAVE_CRYPT_IN_SYSTEM_LIBRARIES)
+if(HAVE_CRYPT_IN_SYSTEM_LIBRARIES)
+ set(HAVE_CRYPT TRUE)
+else(HAVE_CRYPT_IN_SYSTEM_LIBRARIES)
+ set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} crypt)
+endif(HAVE_CRYPT_IN_SYSTEM_LIBRARIES)
+target_link_libraries(fuzz_rserver ${ARGN} ${LIBRARY_NAME}_static ${PCAP_LINK_LIBRARIES})
+
+if(NOT "${SANITIZER_FLAGS}" STREQUAL "")
+ set_target_properties(fuzz_rserver PROPERTIES
+ LINK_FLAGS "${SANITIZER_FLAGS}")
+endif()
+endif(ENABLE_REMOTE AND "$ENV{CFLAGS}" MATCHES "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION")
diff --git a/testprogs/fuzz/fuzz_both.c b/testprogs/fuzz/fuzz_both.c
new file mode 100644
index 000000000000..59e3d404103d
--- /dev/null
+++ b/testprogs/fuzz/fuzz_both.c
@@ -0,0 +1,101 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+
+#include <pcap/pcap.h>
+
+FILE * outfile = NULL;
+
+static int bufferToFile(const char * name, const uint8_t *Data, size_t Size) {
+ FILE * fd;
+ if (remove(name) != 0) {
+ if (errno != ENOENT) {
+ printf("failed remove, errno=%d\n", errno);
+ return -1;
+ }
+ }
+ fd = fopen(name, "wb");
+ if (fd == NULL) {
+ printf("failed open, errno=%d\n", errno);
+ return -2;
+ }
+ if (fwrite (Data, 1, Size, fd) != Size) {
+ fclose(fd);
+ return -3;
+ }
+ fclose(fd);
+ return 0;
+}
+
+void fuzz_openFile(const char * name) {
+ if (outfile != NULL) {
+ fclose(outfile);
+ }
+ outfile = fopen(name, "w");
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ pcap_t * pkts;
+ char errbuf[PCAP_ERRBUF_SIZE];
+ const u_char *pkt;
+ struct pcap_pkthdr *header;
+ int r;
+ size_t filterSize;
+ char * filter;
+ struct bpf_program bpf;
+
+
+ //initialize output file
+ if (outfile == NULL) {
+ outfile = fopen("/dev/null", "w");
+ if (outfile == NULL) {
+ return 0;
+ }
+ }
+
+ if (Size < 1) {
+ return 0;
+ }
+ filterSize = Data[0];
+ if (Size < 1+filterSize || filterSize == 0) {
+ return 0;
+ }
+
+ //rewrite buffer to a file as libpcap does not have buffer inputs
+ if (bufferToFile("/tmp/fuzz.pcap", Data+1+filterSize, Size-(1+filterSize)) < 0) {
+ return 0;
+ }
+
+ //initialize structure
+ pkts = pcap_open_offline("/tmp/fuzz.pcap", errbuf);
+ if (pkts == NULL) {
+ fprintf(outfile, "Couldn't open pcap file %s\n", errbuf);
+ return 0;
+ }
+
+ filter = malloc(filterSize);
+ memcpy(filter, Data+1, filterSize);
+ //null terminate string
+ filter[filterSize-1] = 0;
+
+ if (pcap_compile(pkts, &bpf, filter, 1, PCAP_NETMASK_UNKNOWN) == 0) {
+ //loop over packets
+ r = pcap_next_ex(pkts, &header, &pkt);
+ while (r > 0) {
+ //checks filter
+ fprintf(outfile, "packet length=%d/%d filter=%d\n",header->caplen, header->len, pcap_offline_filter(&bpf, header, pkt));
+ r = pcap_next_ex(pkts, &header, &pkt);
+ }
+ //close structure
+ pcap_close(pkts);
+ pcap_freecode(&bpf);
+ }
+ else {
+ pcap_close(pkts);
+ }
+ free(filter);
+
+ return 0;
+}
diff --git a/testprogs/fuzz/fuzz_both.options b/testprogs/fuzz/fuzz_both.options
new file mode 100644
index 000000000000..0824b19fab47
--- /dev/null
+++ b/testprogs/fuzz/fuzz_both.options
@@ -0,0 +1,2 @@
+[libfuzzer]
+max_len = 65535
diff --git a/testprogs/fuzz/fuzz_filter.c b/testprogs/fuzz/fuzz_filter.c
new file mode 100644
index 000000000000..de350672797f
--- /dev/null
+++ b/testprogs/fuzz/fuzz_filter.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <pcap/pcap.h>
+
+void fuzz_openFile(const char * name){
+ //do nothing
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ pcap_t * pkts;
+ struct bpf_program bpf;
+ char * filter;
+
+ //we need at least 1 byte for linktype
+ if (Size < 1) {
+ return 0;
+ }
+
+ //initialize structure snaplen = 65535
+ pkts = pcap_open_dead(Data[Size-1], 0xFFFF);
+ if (pkts == NULL) {
+ printf("pcap_open_dead failed\n");
+ return 0;
+ }
+ filter = malloc(Size);
+ memcpy(filter, Data, Size);
+ //null terminate string
+ filter[Size-1] = 0;
+
+ if (pcap_compile(pkts, &bpf, filter, 1, PCAP_NETMASK_UNKNOWN) == 0) {
+ pcap_setfilter(pkts, &bpf);
+ pcap_close(pkts);
+ pcap_freecode(&bpf);
+ }
+ else {
+ pcap_close(pkts);
+ }
+ free(filter);
+
+ return 0;
+}
diff --git a/testprogs/fuzz/fuzz_filter.options b/testprogs/fuzz/fuzz_filter.options
new file mode 100644
index 000000000000..9fda93fcb340
--- /dev/null
+++ b/testprogs/fuzz/fuzz_filter.options
@@ -0,0 +1,2 @@
+[libfuzzer]
+max_len = 4096
diff --git a/testprogs/fuzz/fuzz_pcap.c b/testprogs/fuzz/fuzz_pcap.c
new file mode 100644
index 000000000000..fba5312fcaf2
--- /dev/null
+++ b/testprogs/fuzz/fuzz_pcap.c
@@ -0,0 +1,80 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <pcap/pcap.h>
+
+FILE * outfile = NULL;
+
+static int bufferToFile(const char * name, const uint8_t *Data, size_t Size) {
+ FILE * fd;
+ if (remove(name) != 0) {
+ if (errno != ENOENT) {
+ printf("failed remove, errno=%d\n", errno);
+ return -1;
+ }
+ }
+ fd = fopen(name, "wb");
+ if (fd == NULL) {
+ printf("failed open, errno=%d\n", errno);
+ return -2;
+ }
+ if (fwrite (Data, 1, Size, fd) != Size) {
+ fclose(fd);
+ return -3;
+ }
+ fclose(fd);
+ return 0;
+}
+
+void fuzz_openFile(const char * name) {
+ if (outfile != NULL) {
+ fclose(outfile);
+ }
+ outfile = fopen(name, "w");
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ pcap_t * pkts;
+ char errbuf[PCAP_ERRBUF_SIZE];
+ const u_char *pkt;
+ struct pcap_pkthdr *header;
+ struct pcap_stat stats;
+ int r;
+
+ //initialize output file
+ if (outfile == NULL) {
+ outfile = fopen("/dev/null", "w");
+ if (outfile == NULL) {
+ return 0;
+ }
+ }
+
+ //rewrite buffer to a file as libpcap does not have buffer inputs
+ if (bufferToFile("/tmp/fuzz.pcap", Data, Size) < 0) {
+ return 0;
+ }
+
+ //initialize structure
+ pkts = pcap_open_offline("/tmp/fuzz.pcap", errbuf);
+ if (pkts == NULL) {
+ fprintf(outfile, "Couldn't open pcap file %s\n", errbuf);
+ return 0;
+ }
+
+ //loop over packets
+ r = pcap_next_ex(pkts, &header, &pkt);
+ while (r > 0) {
+ //TODO pcap_offline_filter
+ fprintf(outfile, "packet length=%d/%d\n",header->caplen, header->len);
+ r = pcap_next_ex(pkts, &header, &pkt);
+ }
+ if (pcap_stats(pkts, &stats) == 0) {
+ fprintf(outfile, "number of packets=%d\n", stats.ps_recv);
+ }
+ //close structure
+ pcap_close(pkts);
+
+ return 0;
+}
diff --git a/testprogs/fuzz/fuzz_pcap.options b/testprogs/fuzz/fuzz_pcap.options
new file mode 100644
index 000000000000..0824b19fab47
--- /dev/null
+++ b/testprogs/fuzz/fuzz_pcap.options
@@ -0,0 +1,2 @@
+[libfuzzer]
+max_len = 65535
diff --git a/testprogs/fuzz/onefile.c b/testprogs/fuzz/onefile.c
new file mode 100644
index 000000000000..690a63bdc433
--- /dev/null
+++ b/testprogs/fuzz/onefile.c
@@ -0,0 +1,54 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
+void fuzz_openFile(const char * name);
+
+int main(int argc, char** argv)
+{
+ FILE * fp;
+ uint8_t *Data;
+ size_t Size;
+
+ if (argc == 3) {
+ fuzz_openFile(argv[2]);
+ } else if (argc != 2) {
+ return 1;
+ }
+ //opens the file, get its size, and reads it into a buffer
+ fp = fopen(argv[1], "rb");
+ if (fp == NULL) {
+ return 2;
+ }
+ if (fseek(fp, 0L, SEEK_END) != 0) {
+ fclose(fp);
+ return 2;
+ }
+ Size = ftell(fp);
+ if (Size == (size_t) -1) {
+ fclose(fp);
+ return 2;
+ }
+ if (fseek(fp, 0L, SEEK_SET) != 0) {
+ fclose(fp);
+ return 2;
+ }
+ Data = malloc(Size);
+ if (Data == NULL) {
+ fclose(fp);
+ return 2;
+ }
+ if (fread(Data, Size, 1, fp) != 1) {
+ fclose(fp);
+ free(Data);
+ return 2;
+ }
+
+ //launch fuzzer
+ LLVMFuzzerTestOneInput(Data, Size);
+ free(Data);
+ fclose(fp);
+ return 0;
+}
+