Support for initial fuzzing through oss-fuzz
parent
7c8af215ad
commit
5fb4b05d8f
@ -0,0 +1,9 @@
|
|||||||
|
.PHONY: all clean
|
||||||
|
|
||||||
|
all:
|
||||||
|
./generate_packet_corpora.py
|
||||||
|
$(MAKE) -C broker $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-rm -rf corpora/broker corpora/client corpora/broker_packet_seed_corpus.zip corpora/client_packet_seed_corpus.zip
|
||||||
|
$(MAKE) -C broker $@
|
@ -0,0 +1,26 @@
|
|||||||
|
R=../..
|
||||||
|
.PHONY: all clean
|
||||||
|
|
||||||
|
FUZZERS:= \
|
||||||
|
broker_fuzz_initial_packet \
|
||||||
|
broker_fuzz_second_packet
|
||||||
|
|
||||||
|
LOCAL_CPPFLAGS:=$(CPPFLAGS) -I${R}/include/
|
||||||
|
LOCAL_CXXFLAGS:=$(CXXFLAGS) -g -Wall -Werror -pthread
|
||||||
|
LOCAL_LDFLAGS:=$(LDFLAGS)
|
||||||
|
LOCAL_LIBADD:=$(LIBADD) $(LIB_FUZZING_ENGINE) ${R}/src/mosquitto_broker.a -lssl -lcrypto -lcjson
|
||||||
|
|
||||||
|
all: $(FUZZERS)
|
||||||
|
|
||||||
|
broker_fuzz_initial_packet : broker_fuzz_initial_packet.cpp broker_fuzz.cpp
|
||||||
|
$(CXX) $(LOCAL_CXXFLAGS) $(LOCAL_CPPFLAGS) $(LOCAL_LDFLAGS) -o $@ $^ $(LOCAL_LIBADD)
|
||||||
|
install $@ ${OUT}/$@
|
||||||
|
cp ${R}/fuzzing/corpora/broker_packet_seed_corpus.zip $@_seed_corpus.zip
|
||||||
|
|
||||||
|
broker_fuzz_second_packet : broker_fuzz_second_packet.cpp broker_fuzz.cpp
|
||||||
|
$(CXX) $(LOCAL_CXXFLAGS) $(LOCAL_CPPFLAGS) $(LOCAL_LDFLAGS) -o $@ $^ $(LOCAL_LIBADD)
|
||||||
|
install $@ ${OUT}/$@
|
||||||
|
cp ${R}/fuzzing/corpora/broker_packet_seed_corpus.zip $@_seed_corpus.zip
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.o $(FUZZERS)
|
@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2023 Cedalo GmbH
|
||||||
|
|
||||||
|
All rights reserved. This program and the accompanying materials
|
||||||
|
are made available under the terms of the Eclipse Public License 2.0
|
||||||
|
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
|
||||||
|
The Eclipse Public License is available at
|
||||||
|
https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
and the Eclipse Distribution License is available at
|
||||||
|
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||||
|
|
||||||
|
Contributors:
|
||||||
|
Roger Light - initial implementation and documentation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include "broker_fuzz.h"
|
||||||
|
|
||||||
|
/* The broker fuzz-only main function. */
|
||||||
|
extern "C" int mosquitto_fuzz_main(int argc, char *argv[]);
|
||||||
|
|
||||||
|
void *run_broker(void *args)
|
||||||
|
{
|
||||||
|
struct fuzz_data *fuzz = (struct fuzz_data *)args;
|
||||||
|
char *argv[4];
|
||||||
|
int argc = 4;
|
||||||
|
char buf[20];
|
||||||
|
|
||||||
|
argv[0] = strdup("mosquitto");
|
||||||
|
argv[1] = strdup("-q");
|
||||||
|
argv[2] = strdup("-p");
|
||||||
|
snprintf(buf, sizeof(buf), "%d", fuzz->port);
|
||||||
|
argv[3] = buf;
|
||||||
|
|
||||||
|
mosquitto_fuzz_main(argc, argv);
|
||||||
|
|
||||||
|
for(int i=0; i<3; i++){
|
||||||
|
free(argv[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_exit(NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void recv_timeout(int sock, void *buf, size_t len, int timeout_us)
|
||||||
|
{
|
||||||
|
struct timeval tv = {0, timeout_us};
|
||||||
|
|
||||||
|
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof(tv));
|
||||||
|
(void)recv(sock, buf, len, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int connect_retrying(int port)
|
||||||
|
{
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
int sock;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(port);
|
||||||
|
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||||
|
|
||||||
|
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
for(int i=0; i<500; i++){ /* 500x10ms = 5 seconds max wait */
|
||||||
|
errno = 0;
|
||||||
|
rc = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
|
||||||
|
if(rc < 0 && errno == ECONNREFUSED){
|
||||||
|
struct timespec ts;
|
||||||
|
ts.tv_sec = 0;
|
||||||
|
ts.tv_nsec = 10000000; /* 10ms */
|
||||||
|
nanosleep(&ts, NULL);
|
||||||
|
}else if(rc < 0){
|
||||||
|
return -1;
|
||||||
|
}else{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||||
|
{
|
||||||
|
struct fuzz_data fuzz;
|
||||||
|
pthread_t thread;
|
||||||
|
|
||||||
|
if(size < kMinInputLength || size > kMaxInputLength){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
signal(SIGPIPE, SIG_IGN);
|
||||||
|
|
||||||
|
memset(&fuzz, 0, sizeof(fuzz));
|
||||||
|
fuzz.port = 1883;
|
||||||
|
fuzz.size = size;
|
||||||
|
fuzz.data = (uint8_t *)data;
|
||||||
|
|
||||||
|
pthread_create(&thread, NULL, run_broker, &fuzz);
|
||||||
|
run_client(&fuzz);
|
||||||
|
pthread_join(thread, NULL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2023 Cedalo GmbH
|
||||||
|
|
||||||
|
All rights reserved. This program and the accompanying materials
|
||||||
|
are made available under the terms of the Eclipse Public License 2.0
|
||||||
|
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
|
||||||
|
The Eclipse Public License is available at
|
||||||
|
https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
and the Eclipse Distribution License is available at
|
||||||
|
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||||
|
|
||||||
|
Contributors:
|
||||||
|
Roger Light - initial implementation and documentation.
|
||||||
|
*/
|
||||||
|
#ifndef BROKER_FUZZ_H
|
||||||
|
#define BROKER_FUZZ_H
|
||||||
|
|
||||||
|
#define kMinInputLength 5
|
||||||
|
#define kMaxInputLength 10000
|
||||||
|
|
||||||
|
struct fuzz_data{
|
||||||
|
uint8_t *data;
|
||||||
|
size_t size;
|
||||||
|
uint16_t port;
|
||||||
|
};
|
||||||
|
|
||||||
|
void *run_broker(void *args);
|
||||||
|
void recv_timeout(int sock, void *buf, size_t len, int timeout_us);
|
||||||
|
int connect_retrying(int port);
|
||||||
|
void run_client(struct fuzz_data *fuzz);
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2023 Cedalo GmbH
|
||||||
|
|
||||||
|
All rights reserved. This program and the accompanying materials
|
||||||
|
are made available under the terms of the Eclipse Public License 2.0
|
||||||
|
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
|
||||||
|
The Eclipse Public License is available at
|
||||||
|
https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
and the Eclipse Distribution License is available at
|
||||||
|
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||||
|
|
||||||
|
Contributors:
|
||||||
|
Roger Light - initial implementation and documentation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cerrno>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "broker_fuzz.h"
|
||||||
|
|
||||||
|
/* Set to 0 to cause the broker to exit */
|
||||||
|
extern int g_run;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This tests the first packet being sent to the broker only, with no authentication.
|
||||||
|
*/
|
||||||
|
void run_client(struct fuzz_data *fuzz)
|
||||||
|
{
|
||||||
|
int sock;
|
||||||
|
uint8_t data[20];
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
sock = connect_retrying(fuzz->port);
|
||||||
|
if(sock < 0){
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
len = send(sock, fuzz->data, fuzz->size, 0);
|
||||||
|
if(len < fuzz->size){
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
recv_timeout(sock, data, sizeof(data), 100000);
|
||||||
|
close(sock);
|
||||||
|
|
||||||
|
g_run = 0;
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2023 Cedalo GmbH
|
||||||
|
|
||||||
|
All rights reserved. This program and the accompanying materials
|
||||||
|
are made available under the terms of the Eclipse Public License 2.0
|
||||||
|
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
|
||||||
|
The Eclipse Public License is available at
|
||||||
|
https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
and the Eclipse Distribution License is available at
|
||||||
|
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||||
|
|
||||||
|
Contributors:
|
||||||
|
Roger Light - initial implementation and documentation.
|
||||||
|
*/
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cerrno>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "broker_fuzz.h"
|
||||||
|
|
||||||
|
extern int g_run;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This tests the second packet sent to the broker after the client has already
|
||||||
|
* connected, with no authentication.
|
||||||
|
*/
|
||||||
|
void run_client(struct fuzz_data *fuzz)
|
||||||
|
{
|
||||||
|
int sock;
|
||||||
|
const uint8_t connect_packet[] = {0x10, 0x0D, 0x00, 0x04, 0x4D, 0x51, 0x54, 0x54, 0x04, 0x02, 0x00, 0x0A, 0x00, 0x01, 0x70};
|
||||||
|
const uint8_t connack_packet[] = {0x20, 0x02, 0x00, 0x00};
|
||||||
|
uint8_t data[20];
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
sock = connect_retrying(fuzz->port);
|
||||||
|
if(sock < 0){
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do initial connect */
|
||||||
|
errno = 0;
|
||||||
|
len = send(sock, connect_packet, sizeof(connect_packet), 0);
|
||||||
|
if(len < 0){
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And receive the CONNACK */
|
||||||
|
recv_timeout(sock, data, sizeof(connack_packet), 100000);
|
||||||
|
if(memcmp(data, connack_packet, sizeof(connack_packet))){
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
len = send(sock, fuzz->data, fuzz->size, 0);
|
||||||
|
if(len < fuzz->size){
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
recv_timeout(sock, data, sizeof(data), 100000);
|
||||||
|
close(sock);
|
||||||
|
|
||||||
|
g_run = 0;
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from collections import deque
|
||||||
|
from os import mkdir,walk
|
||||||
|
from pathlib import Path
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
def gen_packet_corpus(packet_type, input_path):
|
||||||
|
try:
|
||||||
|
mkdir("corpora")
|
||||||
|
except FileExistsError:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
mkdir(f"corpora/{packet_type}")
|
||||||
|
except FileExistsError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
data_path=Path(input_path)
|
||||||
|
rc = 0
|
||||||
|
sequences = []
|
||||||
|
for (_, _, filenames) in walk(data_path):
|
||||||
|
sequences.extend(filenames)
|
||||||
|
break
|
||||||
|
|
||||||
|
written_packets = {}
|
||||||
|
for seq in sorted(sequences):
|
||||||
|
if seq[-5:] != ".json":
|
||||||
|
continue
|
||||||
|
|
||||||
|
with open(data_path/seq, "r") as f:
|
||||||
|
test_file = json.load(f)
|
||||||
|
|
||||||
|
for g in test_file:
|
||||||
|
group_name = g["group"]
|
||||||
|
tests = g["tests"]
|
||||||
|
|
||||||
|
for t in tests:
|
||||||
|
tname = group_name + " " + t["name"]
|
||||||
|
|
||||||
|
fuzzi = 1
|
||||||
|
for m in t["msgs"]:
|
||||||
|
if m["type"] == "send" or m["type"] == "recv":
|
||||||
|
fname = re.sub(r'[ \[\]\(\)]+', '-', tname) + str(fuzzi) + ".raw"
|
||||||
|
payload = m["payload"].replace(" ", "")
|
||||||
|
|
||||||
|
# No duplicates please
|
||||||
|
if payload not in written_packets:
|
||||||
|
written_packets[payload] = 1
|
||||||
|
with open(f"corpora/{packet_type}/{fname}", "wb") as f:
|
||||||
|
f.write(bytes.fromhex(payload))
|
||||||
|
fuzzi += 1
|
||||||
|
shutil.make_archive(f"corpora/{packet_type}_packet_seed_corpus", 'zip', f"corpora/{packet_type}")
|
||||||
|
|
||||||
|
gen_packet_corpus("broker", "../test/broker/data")
|
||||||
|
gen_packet_corpus("client", "../test/lib/data")
|
@ -0,0 +1,30 @@
|
|||||||
|
#!/bin/bash -eu
|
||||||
|
#
|
||||||
|
# Copyright (c) 2023 Cedalo GmbH
|
||||||
|
#
|
||||||
|
# All rights reserved. This program and the accompanying materials
|
||||||
|
# are made available under the terms of the Eclipse Public License 2.0
|
||||||
|
# and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
#
|
||||||
|
# The Eclipse Public License is available at
|
||||||
|
# https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
# and the Eclipse Distribution License is available at
|
||||||
|
# http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||||
|
#
|
||||||
|
# Contributors:
|
||||||
|
# Roger Light - initial implementation and documentation.
|
||||||
|
|
||||||
|
|
||||||
|
# Build direct broker dependency - cJSON
|
||||||
|
# Note that other dependencies, i.e. sqlite are not yet built because they are
|
||||||
|
# only used by plugins and not currently otherwise used.
|
||||||
|
cd ${SRC}/cJSON
|
||||||
|
cmake -DBUILD_SHARED_LIBS=OFF -DENABLE_CJSON_TEST=OFF -DCMAKE_C_FLAGS=-fPIC .
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
|
||||||
|
# Build broker and library static libraries
|
||||||
|
cd ${SRC}/mosquitto
|
||||||
|
make WITH_STATIC_LIBRARIES=yes WITH_DOCS=no WITH_FUZZING=yes
|
@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/bash -eu
|
||||||
|
#
|
||||||
|
# Copyright (c) 2023 Cedalo GmbH
|
||||||
|
#
|
||||||
|
# All rights reserved. This program and the accompanying materials
|
||||||
|
# are made available under the terms of the Eclipse Public License 2.0
|
||||||
|
# and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
#
|
||||||
|
# The Eclipse Public License is available at
|
||||||
|
# https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
# and the Eclipse Distribution License is available at
|
||||||
|
# http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||||
|
#
|
||||||
|
# Contributors:
|
||||||
|
# Roger Light - initial implementation and documentation.
|
||||||
|
|
||||||
|
|
||||||
|
# Note that sqlite3 is required as a build dep of a plugin which is not
|
||||||
|
# currently part of fuzz testing. Once it is part of fuzz testing, sqlite will
|
||||||
|
# need to be built statically.
|
||||||
|
apt-get update && apt-get install -y libtool-bin make libsqlite3-dev
|
||||||
|
git clone https://github.com/DaveGamble/cJSON ${SRC}/cJSON
|
Loading…
Reference in New Issue