tests: New style fuzzing tool for wpa_supplicant WNM handling

This is a newer version of tests/wnm-fuzzer tool as the initial step in
creating a more uniform set of fuzzing tools that can be used with both
libFuzzer and afl-fuzz.

Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2019-06-01 14:53:24 +03:00
parent 867f1c466d
commit 065e6e7010
11 changed files with 337 additions and 0 deletions

View file

@ -27,6 +27,11 @@ cd build
Fuzz testing Fuzz testing
------------ ------------
Newer fuzz testing tools are under the fuzzing directory. See
fuzzing/README for more details on them. The following text describes
the older fuzz testing tools that are subject to removal once the same
newer tools have the same coverage available.
Number of the test tools here can be used for fuzz testing with tools Number of the test tools here can be used for fuzz testing with tools
like American fuzzy lop (afl-fuzz) that are designed to modify an like American fuzzy lop (afl-fuzz) that are designed to modify an
external file for program input. ap-mgmt-fuzzer, eapol-fuzzer, external file for program input. ap-mgmt-fuzzer, eapol-fuzzer,

23
tests/fuzzing/README Normal file
View file

@ -0,0 +1,23 @@
hostap.git fuzz testing
-----------------------
These tools can be used for fuzz testing of various components used
within wpa_supplicant and hostapd. Each directory contains a fuzzing
tool that focuses on one input handler. Each tool can be compiled either
to work with the libFuzzer or as a separate tool that reads the input
from a file specified on the command line, e.g., for American fuzzy lop
(afl-fuzz). Example test corpus is included in */corpus directory.
Example fuzzing with libFuzzer
cd @TOOL@
make clean
make LIBFUZZER=y
./@TOOL@ corpus
Example fuzzing with afl-fuzz
cd @TOOL@
make clean
CC=afl-gcc make
afl-fuzz -i corpus -o findings -- $PWD/@TOOL@ @@

View file

@ -0,0 +1,56 @@
/*
* Common helper functions for fuzzing tools
* Copyright (c) 2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
#include "utils/common.h"
void wpa_fuzzer_set_debug_level(void)
{
static int first = 1;
if (first) {
char *env;
first = 0;
env = getenv("WPADEBUG");
if (env)
wpa_debug_level = atoi(env);
else
wpa_debug_level = MSG_ERROR + 1;
wpa_debug_show_keys = 1;
}
}
#ifndef TEST_LIBFUZZER
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
int main(int argc, char *argv[])
{
char *data;
size_t len;
if (argc < 2) {
printf("usage: %s <file>\n", argv[0]);
return -1;
}
data = os_readfile(argv[1], &len);
if (!data) {
printf("Could not read '%s'\n", argv[1]);
return -1;
}
LLVMFuzzerTestOneInput((const uint8_t *) data, len);
os_free(data);
return 0;
}
#endif /* !TEST_LIBFUZZER */

View file

@ -0,0 +1,14 @@
/*
* Common helper functions for fuzzing tools
* Copyright (c) 2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef FUZZER_COMMON_H
#define FUZZER_COMMON_H
void wpa_fuzzer_set_debug_level(void);
#endif /* FUZZER_COMMON_H */

View file

@ -0,0 +1,88 @@
ifdef LIBFUZZER
CC=clang
CFLAGS = -MMD -O2 -Wall -g
CFLAGS += -fsanitize=fuzzer,address,signed-integer-overflow,unsigned-integer-overflow
CFLAGS += -DTEST_LIBFUZZER
LDFLAGS += -fsanitize=fuzzer,address,signed-integer-overflow,unsigned-integer-overflow
endif
ifndef CC
CC=gcc
endif
ifndef LDO
LDO=$(CC)
endif
ifndef CFLAGS
CFLAGS = -MMD -O2 -Wall -g
endif
CFLAGS += -DCONFIG_NO_RANDOM_POOL
CFLAGS += -DTEST_FUZZ
WPAS_SRC=../../../wpa_supplicant
SRC=../../../src
CFLAGS += -I$(SRC) -I$(SRC)/utils -I$(WPAS_SRC)
OBJS += ../fuzzer-common.o
$(SRC)/ap/libap.a:
$(MAKE) -C $(SRC)/ap TEST_FUZZ=y
$(SRC)/common/libcommon.a:
$(MAKE) -C $(SRC)/common
$(SRC)/crypto/libcrypto.a:
$(MAKE) -C $(SRC)/crypto
$(SRC)/eapol_auth/libeapol_auth.a:
$(MAKE) -C $(SRC)/eapol_auth
$(SRC)/eapol_supp/libeapol_supp.a:
$(MAKE) -C $(SRC)/eapol_supp
$(SRC)/eap_common/libeap_common.a:
$(MAKE) -C $(SRC)/eap_common
$(SRC)/eap_peer/libeap_peer.a:
$(MAKE) -C $(SRC)/eap_peer
$(SRC)/eap_server/libeap_server.a:
$(MAKE) -C $(SRC)/eap_server
$(SRC)/l2_packet/libl2_packet.a:
$(MAKE) -C $(SRC)/l2_packet
$(SRC)/p2p/libp2p.a:
$(MAKE) -C $(SRC)/p2p
$(SRC)/radius/libradius.a:
$(MAKE) -C $(SRC)/radius
$(SRC)/rsn_supp/librsn_supp.a:
$(MAKE) -C $(SRC)/rsn_supp TEST_FUZZ=y
$(SRC)/tls/libtls.a:
$(MAKE) -C $(SRC)/tls TEST_FUZZ=y
$(SRC)/utils/libutils.a:
$(MAKE) -C $(SRC)/utils TEST_FUZZ=y
$(SRC)/wps/libwps.a:
$(MAKE) -C $(SRC)/wps
Q=@
E=echo
ifeq ($(V), 1)
Q=
E=true
endif
ifeq ($(QUIET), 1)
Q=@
E=true
endif
%.o: %.c
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
@$(E) " CC " $<

View file

@ -0,0 +1,52 @@
all: wnm
include ../rules.include
CFLAGS += -DCONFIG_WNM
CFLAGS += -DCONFIG_INTERWORKING
CFLAGS += -DCONFIG_GAS
CFLAGS += -DCONFIG_HS20
CFLAGS += -DIEEE8021X_EAPOL
LIBS += $(SRC)/common/libcommon.a
LIBS += $(SRC)/crypto/libcrypto.a
LIBS += $(SRC)/tls/libtls.a
LIBS += $(SRC)/rsn_supp/librsn_supp.a
LIBS += $(SRC)/eapol_supp/libeapol_supp.a
LIBS += $(SRC)/eap_peer/libeap_peer.a
LIBS += $(SRC)/eap_common/libeap_common.a
LIBS += $(SRC)/l2_packet/libl2_packet.a
LIBS += $(SRC)/utils/libutils.a
ELIBS += $(SRC)/crypto/libcrypto.a
ELIBS += $(SRC)/tls/libtls.a
OBJS += $(WPAS_SRC)/blacklist.o
OBJS += $(WPAS_SRC)/bss.o
OBJS += $(WPAS_SRC)/config.o
OBJS += $(WPAS_SRC)/config_file.o
OBJS += $(WPAS_SRC)/eap_register.o
OBJS += $(WPAS_SRC)/events.o
OBJS += $(WPAS_SRC)/gas_query.o
OBJS += $(WPAS_SRC)/hs20_supplicant.o
OBJS += $(WPAS_SRC)/interworking.o
OBJS += $(WPAS_SRC)/notify.o
OBJS += $(WPAS_SRC)/offchannel.o
OBJS += $(WPAS_SRC)/op_classes.o
OBJS += $(WPAS_SRC)/rrm.o
OBJS += $(WPAS_SRC)/scan.o
OBJS += $(WPAS_SRC)/wmm_ac.o
OBJS += $(WPAS_SRC)/wnm_sta.o
OBJS += $(WPAS_SRC)/wpa_supplicant.o
OBJS += $(WPAS_SRC)/wpas_glue.o
OBJS += $(SRC)/drivers/driver_common.o
OBJS += $(SRC)/drivers/drivers.o
wnm: wnm.o $(OBJS) $(LIBS)
$(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS)
clean:
$(MAKE) -C $(SRC) clean
$(MAKE) -C $(WPAS_SRC) clean
rm -f wnm *~ *.o *.d ../*~ ../*.o ../*.d
-include $(OBJS:%.o=%.d)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

99
tests/fuzzing/wnm/wnm.c Normal file
View file

@ -0,0 +1,99 @@
/*
* wpa_supplicant - WNM fuzzer
* Copyright (c) 2015-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
#include "utils/common.h"
#include "utils/eloop.h"
#include "common/ieee802_11_defs.h"
#include "rsn_supp/wpa.h"
#include "rsn_supp/wpa_i.h"
#include "wpa_supplicant_i.h"
#include "bss.h"
#include "wnm_sta.h"
#include "config.h"
#include "../fuzzer-common.h"
struct arg_ctx {
const u8 *data;
size_t data_len;
struct wpa_supplicant wpa_s;
struct wpa_bss bss;
struct wpa_driver_ops driver;
struct wpa_sm wpa;
struct wpa_config conf;
};
static void test_send_wnm(void *eloop_data, void *user_ctx)
{
struct arg_ctx *ctx = eloop_data;
const struct ieee80211_mgmt *mgmt;
wpa_hexdump(MSG_MSGDUMP, "fuzzer - WNM", ctx->data, ctx->data_len);
mgmt = (const struct ieee80211_mgmt *) ctx->data;
ieee802_11_rx_wnm_action(&ctx->wpa_s, mgmt, ctx->data_len);
eloop_terminate();
}
static int init_wpa(struct arg_ctx *ctx)
{
ctx->wpa_s.wpa_state = WPA_COMPLETED;
os_memcpy(ctx->wpa_s.bssid, "\x02\x00\x00\x00\x03\x00", ETH_ALEN);
ctx->wpa_s.current_bss = &ctx->bss;
ctx->wpa_s.driver = &ctx->driver;
ctx->wpa_s.wpa = &ctx->wpa;
ctx->wpa_s.conf = &ctx->conf;
return 0;
}
static void deinit_wpa(struct arg_ctx *ctx)
{
wnm_deallocate_memory(&ctx->wpa_s);
}
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
struct arg_ctx ctx;
wpa_fuzzer_set_debug_level();
if (os_program_init())
return 0;
if (eloop_init()) {
wpa_printf(MSG_ERROR, "Failed to initialize event loop");
return 0;
}
os_memset(&ctx, 0, sizeof(ctx));
ctx.data = data;
ctx.data_len = size;
if (init_wpa(&ctx))
goto fail;
eloop_register_timeout(0, 0, test_send_wnm, &ctx, NULL);
wpa_printf(MSG_DEBUG, "Starting eloop");
eloop_run();
wpa_printf(MSG_DEBUG, "eloop done");
deinit_wpa(&ctx);
fail:
eloop_destroy();
os_program_deinit();
return 0;
}