added fuzz tests (moved from contrib/ports/unix/fuzz to get them to a more prominent place, even if afl-fuzz still needs *nix to run)

This commit is contained in:
sg 2016-12-15 21:39:46 +01:00
parent 62e340067e
commit 844c201702
12 changed files with 321 additions and 0 deletions

52
test/fuzz/Makefile Normal file
View File

@ -0,0 +1,52 @@
#
# Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# 3. The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
# SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
# OF SUCH DAMAGE.
#
# This file is part of the lwIP TCP/IP stack.
#
# Author: Adam Dunkels <adam@sics.se>
#
all compile: lwip_fuzz
.PHONY: all clean
include ../Common.mk
CC=afl-gcc
LDFLAGS:=$(LDFLAGS) -lm
CFLAGS:=$(CFLAGS) -O0
clean:
rm -f *.o $(LWIPLIBCOMMON) lwip_fuzz *.s .depend* *.core core
depend dep: .depend
include .depend
.depend: fuzz.c $(LWIPFILES) $(APPFILES)
$(CCDEP) $(CFLAGS) -MM $^ > .depend || rm -f .depend
lwip_fuzz: .depend $(LWIPLIBCOMMON) fuzz.o
$(CC) $(CFLAGS) -o lwip_fuzz fuzz.o $(LWIPLIBCOMMON) $(LDFLAGS)

34
test/fuzz/README Normal file
View File

@ -0,0 +1,34 @@
Fuzzing the lwIP stack
This directory contains a small app that reads Ethernet frames from stdin and
processes them. It is used together with the 'american fuzzy lop' tool (found
at http://lcamtuf.coredump.cx/afl/) and the sample inputs to test how
unexpected inputs are handled. The afl tool will read the known inputs, and
try to modify them to exercise as many code paths as possible, by instrumenting
the code and keeping track of which code is executed.
Just running make will produce the test program.
Then run afl with:
afl-fuzz -i inputs/<INPUT> -o output ./lwip_fuzz
and it should start working. It will probably complain about CPU scheduler,
set AFL_SKIP_CPUFREQ=1 to ignore it.
If it complains about invalid "/proc/sys/kernel/core_pattern" setting, try
executing "sudo bash -c 'echo core > /proc/sys/kernel/core_pattern'".
The input is split into different subdirectories since they test different
parts of the code, and since you want to run one instance of afl-fuzz on each
core.
When afl finds a crash or a hang, the input that caused it will be placed in
the output directory. If you have hexdump and text2pcap tools installed,
running output_to_pcap.sh <outputdir> will create pcap files for each input
file to simplify viewing in wireshark.
The lwipopts.h file needs to have checksum checking off, otherwise almost every
packet will be discarded because of that. The other options can be tuned to
expose different parts of the code.

0
test/fuzz/config.h Normal file
View File

136
test/fuzz/fuzz.c Normal file
View File

@ -0,0 +1,136 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Erik Ekman <erik@kryo.se>
*
*/
#include "lwip/init.h"
#include "lwip/netif.h"
#include "netif/etharp.h"
#if LWIP_IPV6
#include "lwip/ethip6.h"
#include "lwip/nd6.h"
#endif
#include <string.h>
#include <stdio.h>
/* no-op send function */
static err_t lwip_tx_func(struct netif *netif, struct pbuf *p)
{
LWIP_UNUSED_ARG(netif);
LWIP_UNUSED_ARG(p);
return ERR_OK;
}
static err_t testif_init(struct netif *netif)
{
netif->name[0] = 'f';
netif->name[1] = 'z';
netif->output = etharp_output;
netif->linkoutput = lwip_tx_func;
netif->mtu = 1500;
netif->hwaddr_len = 6;
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
netif->hwaddr[0] = 0x00;
netif->hwaddr[1] = 0x23;
netif->hwaddr[2] = 0xC1;
netif->hwaddr[3] = 0xDE;
netif->hwaddr[4] = 0xD0;
netif->hwaddr[5] = 0x0D;
#if LWIP_IPV6
netif->output_ip6 = ethip6_output;
netif->ip6_autoconfig_enabled = 1;
netif_create_ip6_linklocal_address(netif, 1);
netif->flags |= NETIF_FLAG_MLD6;
#endif
return ERR_OK;
}
static void input_pkt(struct netif *netif, const u8_t *data, size_t len)
{
struct pbuf *p, *q;
err_t err;
LWIP_ASSERT("pkt too big", len <= 0xFFFF);
p = pbuf_alloc(PBUF_RAW, (u16_t)len, PBUF_POOL);
LWIP_ASSERT("alloc failed", p);
for(q = p; q != NULL; q = q->next) {
MEMCPY(q->payload, data, q->len);
data += q->len;
}
err = netif->input(p, netif);
if (err != ERR_OK) {
pbuf_free(p);
}
}
int main(int argc, char** argv)
{
struct netif net_test;
ip4_addr_t addr;
ip4_addr_t netmask;
ip4_addr_t gw;
u8_t pktbuf[2000];
size_t len;
lwip_init();
IP4_ADDR(&addr, 172, 30, 115, 84);
IP4_ADDR(&netmask, 255, 255, 255, 0);
IP4_ADDR(&gw, 172, 30, 115, 1);
netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input);
netif_set_up(&net_test);
#if LWIP_IPV6
nd6_tmr(); /* tick nd to join multicast groups */
#endif
if(argc > 1) {
FILE* f;
const char* filename;
printf("reading input from file... ");
fflush(stdout);
filename = argv[1];
LWIP_ASSERT("invalid filename", filename != NULL);
f = fopen(filename, "rb");
LWIP_ASSERT("open failed", f != NULL);
len = fread(pktbuf, 1, sizeof(pktbuf), f);
fclose(f);
printf("testing file: \"%s\"...\r\n", filename);
} else {
len = fread(pktbuf, 1, sizeof(pktbuf), stdin);
}
input_pkt(&net_test, pktbuf, len);
return 0;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

68
test/fuzz/lwipopts.h Normal file
View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Simon Goldschmidt
*
*/
#ifndef LWIP_HDR_LWIPOPTS_H__
#define LWIP_HDR_LWIPOPTS_H__
/* Prevent having to link sys_arch.c (we don't test the API layers in unit tests) */
#define NO_SYS 1
#define LWIP_NETCONN 0
#define LWIP_SOCKET 0
#define SYS_LIGHTWEIGHT_PROT 0
#define LWIP_IPV6 1
#define IPV6_FRAG_COPYHEADER 1
#define LWIP_IPV6_DUP_DETECT_ATTEMPTS 0
/* Enable DHCP to test it */
#define LWIP_DHCP 1
/* Turn off checksum verification of fuzzed data */
#define CHECKSUM_CHECK_IP 0
#define CHECKSUM_CHECK_UDP 0
#define CHECKSUM_CHECK_TCP 0
#define CHECKSUM_CHECK_ICMP 0
#define CHECKSUM_CHECK_ICMP6 0
/* Minimal changes to opt.h required for tcp unit tests: */
#define MEM_SIZE 16000
#define TCP_SND_QUEUELEN 40
#define MEMP_NUM_TCP_SEG TCP_SND_QUEUELEN
#define TCP_SND_BUF (12 * TCP_MSS)
#define TCP_WND (10 * TCP_MSS)
#define LWIP_WND_SCALE 1
#define TCP_RCV_SCALE 0
#define PBUF_POOL_SIZE 400 /* pbuf tests need ~200KByte */
/* Minimal changes to opt.h required for etharp unit tests: */
#define ETHARP_SUPPORT_STATIC_ENTRIES 1
#endif /* LWIP_HDR_LWIPOPTS_H__ */

View File

@ -0,0 +1,31 @@
#!/bin/bash
if [ -z "$1" ]
then
echo "This script will make pcap files from the afl-fuzz crash/hang files"
echo "It needs hexdump and text2pcap"
echo "Please give output directory as argument"
exit 2
fi
for i in `ls $1/crashes/id*`
do
PCAPNAME=`echo $i | grep pcap`
if [ -z "$PCAPNAME" ]; then
hexdump -C $i > $1/$$.tmp
text2pcap $1/$$.tmp ${i}.pcap
fi
done
for i in `ls $1/hangs/id*`
do
PCAPNAME=`echo $i | grep pcap`
if [ -z "$PCAPNAME" ]; then
hexdump -C $i > $1/$$.tmp
text2pcap $1/$$.tmp ${i}.pcap
fi
done
rm -f $1/$$.tmp
echo
echo "Created pcap files:"
ls $1/*/*.pcap