]> granicus.if.org Git - esp-idf/commitdiff
DnsFuzzer: Added fuzzer test for exercising lwip/dns receiving DNS responses
authorDavid Cermak <david@Davids-MacBook-Pro.local>
Fri, 18 May 2018 13:54:08 +0000 (15:54 +0200)
committerDavid Cermak <david@Davids-MacBook-Pro.local>
Fri, 18 May 2018 13:54:08 +0000 (15:54 +0200)
35 files changed:
components/lwip/test_afl_host/Makefile
components/lwip/test_afl_host/dns_di.h [new file with mode: 0644]
components/lwip/test_afl_host/in_dhcp_client/data0.bin [moved from components/lwip/test_afl_host/in_client/data0.bin with 100% similarity]
components/lwip/test_afl_host/in_dhcp_client/data1.bin [moved from components/lwip/test_afl_host/in_client/data1.bin with 100% similarity]
components/lwip/test_afl_host/in_dhcp_client/data2.bin [moved from components/lwip/test_afl_host/in_client/data2.bin with 100% similarity]
components/lwip/test_afl_host/in_dhcp_client/data3.bin [moved from components/lwip/test_afl_host/in_client/data3.bin with 100% similarity]
components/lwip/test_afl_host/in_dhcp_client/data4.bin [moved from components/lwip/test_afl_host/in_client/data4.bin with 100% similarity]
components/lwip/test_afl_host/in_dhcp_client/data5.bin [moved from components/lwip/test_afl_host/in_client/data5.bin with 100% similarity]
components/lwip/test_afl_host/in_dhcp_client/data6.bin [moved from components/lwip/test_afl_host/in_client/data6.bin with 100% similarity]
components/lwip/test_afl_host/in_dhcp_client/data7.bin [moved from components/lwip/test_afl_host/in_client/data7.bin with 100% similarity]
components/lwip/test_afl_host/in_dhcp_client/data8.bin [moved from components/lwip/test_afl_host/in_client/data8.bin with 100% similarity]
components/lwip/test_afl_host/in_dhcp_server/data0.bin [moved from components/lwip/test_afl_host/in_server/data0.bin with 100% similarity]
components/lwip/test_afl_host/in_dhcp_server/data1.bin [moved from components/lwip/test_afl_host/in_server/data1.bin with 100% similarity]
components/lwip/test_afl_host/in_dhcp_server/data2.bin [moved from components/lwip/test_afl_host/in_server/data2.bin with 100% similarity]
components/lwip/test_afl_host/in_dhcp_server/data3.bin [moved from components/lwip/test_afl_host/in_server/data3.bin with 100% similarity]
components/lwip/test_afl_host/in_dhcp_server/data4.bin [moved from components/lwip/test_afl_host/in_server/data4.bin with 100% similarity]
components/lwip/test_afl_host/in_dhcp_server/data5.bin [moved from components/lwip/test_afl_host/in_server/data5.bin with 100% similarity]
components/lwip/test_afl_host/in_dhcp_server/data6.bin [moved from components/lwip/test_afl_host/in_server/data6.bin with 100% similarity]
components/lwip/test_afl_host/in_dns/out0.bin [new file with mode: 0644]
components/lwip/test_afl_host/in_dns/out10.bin [new file with mode: 0644]
components/lwip/test_afl_host/in_dns/out28.bin [new file with mode: 0644]
components/lwip/test_afl_host/in_dns/out29.bin [new file with mode: 0644]
components/lwip/test_afl_host/in_dns/out30.bin [new file with mode: 0644]
components/lwip/test_afl_host/in_dns/out31.bin [new file with mode: 0644]
components/lwip/test_afl_host/in_dns/out32.bin [new file with mode: 0644]
components/lwip/test_afl_host/in_dns/out33.bin [new file with mode: 0644]
components/lwip/test_afl_host/in_dns/out34.bin [new file with mode: 0644]
components/lwip/test_afl_host/in_dns/out35.bin [new file with mode: 0644]
components/lwip/test_afl_host/in_dns/out36.bin [new file with mode: 0644]
components/lwip/test_afl_host/in_dns/out37.bin [new file with mode: 0644]
components/lwip/test_afl_host/in_dns/out38.bin [new file with mode: 0644]
components/lwip/test_afl_host/network_mock.c
components/lwip/test_afl_host/test_dhcp_client.c [moved from components/lwip/test_afl_host/test_client.c with 100% similarity]
components/lwip/test_afl_host/test_dhcp_server.c [moved from components/lwip/test_afl_host/test_server.c with 100% similarity]
components/lwip/test_afl_host/test_dns.c [new file with mode: 0644]

index a3da02e11e48374900a18cf0de2e1af412e7c816..d20537977deee62cd0d902267f99d6906830cf14 100644 (file)
@@ -5,14 +5,21 @@ INC_DIRS=-I . -I $(COMPONENTS_DIR)/lwip/include/lwip -I $(COMPONENTS_DIR)/lwip/i
 TEST_NAME=test
 FUZZ=afl-fuzz
 LD=$(CC)
-ifeq ($(MODE),client)
-    DHCP_C_DEPENDENCY_INJECTION=-include dhcp_di.h
-    OBJECTS=dhcp.o network_mock.o test_client.o
-    SAMPLE_PACKETS=in_client
-else 
-    DHCP_C_DEPENDENCY_INJECTION=-include dhcpserver_di.h
-    OBJECTS=dhcpserver.o test_server.o network_mock.o
-    SAMPLE_PACKETS=in_server
+ifeq ($(MODE),dhcp_client)
+    DEPENDENCY_INJECTION=-include dhcp_di.h
+    OBJECTS=dhcp.o network_mock.o test_dhcp_client.o
+    SAMPLE_PACKETS=in_dhcp_client
+else ifeq ($(MODE),dhcp_server)
+    DEPENDENCY_INJECTION=-include dhcpserver_di.h
+    OBJECTS=dhcpserver.o test_dhcp_server.o network_mock.o
+    SAMPLE_PACKETS=in_dhcp_server
+else ifeq ($(MODE),dns)
+    CFLAGS+=-DNOT_MOCK_DNS
+    DEPENDENCY_INJECTION=-include dns_di.h
+    OBJECTS=dns.o test_dns.o network_mock.o
+    SAMPLE_PACKETS=in_dns
+else
+    $(error Please specify MODE: dhcp_server, dhcp_client, dns)
 endif
 
 ifeq ($(INSTR),off)
@@ -27,13 +34,17 @@ CFLAGS+=$(INC_DIRS)
 
 all: $(TEST_NAME)
 
+dns.o: ../core/dns.c
+       @echo "[CC] $<"
+       @$(CC) $(CFLAGS) $(DEPENDENCY_INJECTION) -c $< -o $@
+
 dhcp.o: ../core/ipv4/dhcp.c
        @echo "[CC] $<"
-       @$(CC) $(CFLAGS) $(DHCP_C_DEPENDENCY_INJECTION) -c $< -o $@
+       @$(CC) $(CFLAGS) $(DEPENDENCY_INJECTION) -c $< -o $@
 
 dhcpserver.o: ../apps/dhcpserver.c
        @echo "[CC] $<"
-       @$(CC) $(CFLAGS) $(DHCP_C_DEPENDENCY_INJECTION) -c $< -o $@
+       @$(CC) $(CFLAGS) $(DEPENDENCY_INJECTION) -c $< -o $@
 
 %.o: %.c
        @echo "[CC] $<"
diff --git a/components/lwip/test_afl_host/dns_di.h b/components/lwip/test_afl_host/dns_di.h
new file mode 100644 (file)
index 0000000..4cb0b71
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * dns.c dependecy injection -- preincluded to inject interface test functions into static variables
+ * 
+ */
+#include "no_warn_host.h"
+
+#include "lwip/opt.h"
+#include "lwip/udp.h"
+#include "lwip/mem.h"
+#include "lwip/memp.h"
+#include "lwip/dns.h"
+#include "lwip/ip_addr.h"
+
+#define ipaddr_aton(cp, addr)                   ip4addr_aton(cp, addr)
+
+extern uint32_t g_random_numbers[8];
+extern uint32_t g_random_numbers_cnt;
+
+void __assert_func(const char *file, int line, const char *func, const char *expr)
+{
+    printf("Assert failed in %s, %s:%d (%s)", func, file, line, expr);
+    abort();
+}
+
+int ip4addr_aton(const char *cp, ip4_addr_t *addr)
+{
+    return 0;
+}
+
+static err_t dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found, void *callback_arg, u8_t dns_addrtype);
+static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);
+
+void (*dns_test_static_dns_recv)(void *s, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) = NULL;
+err_t (*dns_test_static_dns_enqueue)(const char *name, size_t hostnamelen, dns_found_callback found, void *callback_arg, u8_t dns_addrtype) = NULL;
+
+
+void dns_test_init_di()
+{
+    dns_test_static_dns_recv = dns_recv;
+    dns_test_static_dns_enqueue = dns_enqueue;
+}
+
+err_t dns_test_dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found, void *callback_arg, u8_t dns_addrtype)
+{
+    return dns_test_static_dns_enqueue(name, hostnamelen, found, callback_arg, dns_addrtype);
+}
+
+void dns_test_dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
+{
+    dns_test_static_dns_recv(s, pcb, p, addr, port);
+}
+
+void dns_test_inject_port_and_txid(int port, int txid)
+{
+    // inject random numbers 
+    g_random_numbers[0] = port; //for port
+    g_random_numbers[1] = txid; //for txid
+    g_random_numbers_cnt = 0;   // let's start with the port
+}
\ No newline at end of file
diff --git a/components/lwip/test_afl_host/in_dns/out0.bin b/components/lwip/test_afl_host/in_dns/out0.bin
new file mode 100644 (file)
index 0000000..8a68ce6
Binary files /dev/null and b/components/lwip/test_afl_host/in_dns/out0.bin differ
diff --git a/components/lwip/test_afl_host/in_dns/out10.bin b/components/lwip/test_afl_host/in_dns/out10.bin
new file mode 100644 (file)
index 0000000..e9f8c73
Binary files /dev/null and b/components/lwip/test_afl_host/in_dns/out10.bin differ
diff --git a/components/lwip/test_afl_host/in_dns/out28.bin b/components/lwip/test_afl_host/in_dns/out28.bin
new file mode 100644 (file)
index 0000000..92ed4c5
Binary files /dev/null and b/components/lwip/test_afl_host/in_dns/out28.bin differ
diff --git a/components/lwip/test_afl_host/in_dns/out29.bin b/components/lwip/test_afl_host/in_dns/out29.bin
new file mode 100644 (file)
index 0000000..40dc982
Binary files /dev/null and b/components/lwip/test_afl_host/in_dns/out29.bin differ
diff --git a/components/lwip/test_afl_host/in_dns/out30.bin b/components/lwip/test_afl_host/in_dns/out30.bin
new file mode 100644 (file)
index 0000000..d7eff8b
Binary files /dev/null and b/components/lwip/test_afl_host/in_dns/out30.bin differ
diff --git a/components/lwip/test_afl_host/in_dns/out31.bin b/components/lwip/test_afl_host/in_dns/out31.bin
new file mode 100644 (file)
index 0000000..4ed67b7
Binary files /dev/null and b/components/lwip/test_afl_host/in_dns/out31.bin differ
diff --git a/components/lwip/test_afl_host/in_dns/out32.bin b/components/lwip/test_afl_host/in_dns/out32.bin
new file mode 100644 (file)
index 0000000..84afda7
Binary files /dev/null and b/components/lwip/test_afl_host/in_dns/out32.bin differ
diff --git a/components/lwip/test_afl_host/in_dns/out33.bin b/components/lwip/test_afl_host/in_dns/out33.bin
new file mode 100644 (file)
index 0000000..dc5b666
Binary files /dev/null and b/components/lwip/test_afl_host/in_dns/out33.bin differ
diff --git a/components/lwip/test_afl_host/in_dns/out34.bin b/components/lwip/test_afl_host/in_dns/out34.bin
new file mode 100644 (file)
index 0000000..55e9f0c
Binary files /dev/null and b/components/lwip/test_afl_host/in_dns/out34.bin differ
diff --git a/components/lwip/test_afl_host/in_dns/out35.bin b/components/lwip/test_afl_host/in_dns/out35.bin
new file mode 100644 (file)
index 0000000..8d7c652
Binary files /dev/null and b/components/lwip/test_afl_host/in_dns/out35.bin differ
diff --git a/components/lwip/test_afl_host/in_dns/out36.bin b/components/lwip/test_afl_host/in_dns/out36.bin
new file mode 100644 (file)
index 0000000..0b6580f
Binary files /dev/null and b/components/lwip/test_afl_host/in_dns/out36.bin differ
diff --git a/components/lwip/test_afl_host/in_dns/out37.bin b/components/lwip/test_afl_host/in_dns/out37.bin
new file mode 100644 (file)
index 0000000..9c06a7b
Binary files /dev/null and b/components/lwip/test_afl_host/in_dns/out37.bin differ
diff --git a/components/lwip/test_afl_host/in_dns/out38.bin b/components/lwip/test_afl_host/in_dns/out38.bin
new file mode 100644 (file)
index 0000000..31bf8c2
Binary files /dev/null and b/components/lwip/test_afl_host/in_dns/out38.bin differ
index 9e9ae4829956b3030c7b80d4149949dc7743094f..cf35fdb63dcdf2d04643784425e118ff8193b70d 100644 (file)
@@ -9,23 +9,84 @@
 
 const ip_addr_t ip_addr_any;
 const ip_addr_t ip_addr_broadcast;
+const ip_addr_t ip_addr_any_type;
 struct ip_globals ip_data;
 struct netif *netif_list;
+struct udp_pcb mock_pcb;
+uint32_t g_random_numbers[8] = {0};
+uint32_t g_random_numbers_cnt = 0;
 
 
+struct pbuf* pbuf_skip(struct pbuf* in, u16_t in_offset, u16_t* out_offset)
+{
+  u16_t offset_left = in_offset;
+  struct pbuf* q = in;
+
+  /* get the correct pbuf */
+  while ((q != NULL) && (q->len <= offset_left)) {
+    offset_left -= q->len;
+    q = q->next;
+  }
+  if (out_offset != NULL) {
+    *out_offset = offset_left;
+  }
+  return q;
+}
+
+void pbuf_put_at(struct pbuf* p, u16_t offset, u8_t data)
+{
+  u16_t q_idx;
+  struct pbuf* q = pbuf_skip(p, offset, &q_idx);
+
+  /* write requested data if pbuf is OK */
+  if ((q != NULL) && (q->len > q_idx)) {
+    ((u8_t*)q->payload)[q_idx] = data;
+  }
+}
+
+u8_t pbuf_get_at(struct pbuf* p, u16_t offset)
+{
+  u16_t q_idx;
+  struct pbuf* q = pbuf_skip(p, offset, &q_idx);
+
+  /* return requested data if pbuf is OK */
+  if ((q != NULL) && (q->len > q_idx)) {
+    return ((u8_t*)q->payload)[q_idx];
+  }
+  return 0;
+}
+
+err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len)
+{
+  return ERR_OK;
+}
+
+err_t pbuf_take_at(struct pbuf *buf, const void *dataptr, u16_t len, u16_t offset)
+{
+  return ERR_OK;
+}
+
+struct udp_pcb * udp_new_ip_type(u8_t type)
+{
+ return &mock_pcb;
+}
+
 u16_t lwip_htons(u16_t n)
 {
-    return 0;
+    return ((n & 0xff) << 8) | ((n & 0xff00) >> 8);
 }
 
 u32_t lwip_htonl(u32_t n)
 {
-    return 0;
+return ((n & 0xff) << 24) |
+    ((n & 0xff00) << 8) |
+    ((n & 0xff0000UL) >> 8) |
+    ((n & 0xff000000UL) >> 24);
 }
 
 esp_err_t tcpip_adapter_get_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_ip_info_t *ip_info)
 {
- return ESP_OK;
   return ESP_OK;
 }
 
 struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
@@ -84,13 +145,16 @@ void udp_disconnect(struct udp_pcb *pcb)
 {
 }
 
+#ifndef NOT_MOCK_DNS
 void dns_setserver(u8_t numdns, const ip_addr_t *dnsserver)
 {
 }
+#endif
 
 uint32_t esp_random(void)
 {
-    return 0;
+    // Preparation for injecting favorable random numbers 
+    return g_random_numbers[g_random_numbers_cnt++ % 8];
 }
 
 err_t etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q)
@@ -100,7 +164,7 @@ err_t etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q
 
 u32_t lwip_ntohl(u32_t x)
 {
-    return 0;
+    return lwip_htonl(x);
 }
 
 void netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask,
@@ -120,10 +184,43 @@ void pbuf_realloc(struct pbuf *p, u16_t size)
     }
 }
 
-u16_t pbuf_copy_partial(struct pbuf *p, void *dataptr, u16_t len, u16_t offset)
+u16_t pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
 {
+  struct pbuf *p;
+  u16_t left;
+  u16_t buf_copy_len;
+  u16_t copied_total = 0;
+
+  LWIP_ERROR("pbuf_copy_partial: invalid buf", (buf != NULL), return 0;);
+  LWIP_ERROR("pbuf_copy_partial: invalid dataptr", (dataptr != NULL), return 0;);
+
+  left = 0;
+
+  if ((buf == NULL) || (dataptr == NULL)) {
     return 0;
+  }
+
+  /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */
+  for (p = buf; len != 0 && p != NULL; p = p->next) {
+    if ((offset != 0) && (offset >= p->len)) {
+      /* don't copy from this buffer -> on to the next */
+      offset -= p->len;
+    } else {
+      /* copy from this buffer. maybe only partially. */
+      buf_copy_len = p->len - offset;
+      if (buf_copy_len > len)
+          buf_copy_len = len;
+      /* copy the necessary parts of the buffer */
+      MEMCPY(&((char*)dataptr)[left], &((char*)p->payload)[offset], buf_copy_len);
+      copied_total += buf_copy_len;
+      left += buf_copy_len;
+      len -= buf_copy_len;
+      offset = 0;
+    }
+  }
+  return copied_total;
 }
+
 err_t udp_connect(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port)
 {
     return ESP_OK;
diff --git a/components/lwip/test_afl_host/test_dns.c b/components/lwip/test_afl_host/test_dns.c
new file mode 100644 (file)
index 0000000..131a8b3
--- /dev/null
@@ -0,0 +1,79 @@
+#include "no_warn_host.h"
+
+#include "lwip/opt.h"
+#include "lwip/udp.h"
+#include "lwip/mem.h"
+#include "lwip/memp.h"
+#include "lwip/dns.h"
+#include "lwip/ip_addr.h"
+
+#include <string.h>
+
+const ip_addr_t ip_addr_any;
+const ip_addr_t ip_addr_broadcast;
+struct ip_globals ip_data;
+struct netif *netif_list;
+struct netif mynetif;
+ip4_addr_t server_ip;
+
+//
+// Dependency injected test functions
+void dns_test_dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);
+void dns_test_inject_port_and_txid(int port, int txid);
+
+void dns_test_init_di();
+err_t dns_test_dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found, void *callback_arg, u8_t dns_addrtype);
+
+//
+// Test starts here
+//
+int main(int argc, char** argv)
+{
+    uint8_t *buf;
+    struct pbuf *p;
+    FILE *file;
+    size_t len = 1460;
+
+    dns_test_init_di();
+    
+#ifdef INSTR_IS_OFF
+    p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
+    buf = p->payload;
+    memset(buf, 0, 1460);
+    if (argc != 2)
+    {
+        printf("Non-instrumentation mode: please supply a file name created by AFL to reproduce crash\n");
+        return 1;
+    }
+    //
+    // Note: parameter1 is a file (mangled packet) which caused the crash
+    file = fopen(argv[1], "r");
+    if (file) {
+    len = fread(buf, 1, 1460, file);
+    }
+    fclose(file);
+    int i;
+    for (i=0; i<1; i++) {
+#else
+    while (__AFL_LOOP(1000)) {
+        p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
+        buf = p->payload;
+        memset(buf, 0, 1460);
+        size_t len = read(0, buf, 1460);
+#endif
+        p->len = len;
+        p->tot_len = len;
+        p->next = NULL;
+
+        // Pretend that the response is from our pending querries
+        dns_test_inject_port_and_txid(1024, (buf[0]<<8) + buf[1]);
+        dns_test_dns_enqueue("test", 4, NULL, NULL, 0);
+
+        // Process the packet
+        dns_test_dns_recv(NULL, NULL, p, &ip_addr_any, 0);        
+    }
+
+
+    
+    return 0;
+}