mirror of https://github.com/OISF/suricata
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
171 lines
4.9 KiB
C
171 lines
4.9 KiB
C
/**
|
|
* @file
|
|
* @author Philippe Antoine <contact@catenacyber.fr>
|
|
* fuzz target for predefined signatures and pcap (aware)
|
|
*/
|
|
|
|
#include "suricata-common.h"
|
|
#include "source-pcap-file.h"
|
|
#include "detect-engine.h"
|
|
#include "util-classification-config.h"
|
|
#include "util-reference-config.h"
|
|
#include "app-layer.h"
|
|
#include "tm-queuehandlers.h"
|
|
#include "util-cidr.h"
|
|
#include "util-profiling.h"
|
|
#include "util-proto-name.h"
|
|
#include "detect-engine-tag.h"
|
|
#include "detect-engine-threshold.h"
|
|
#include "host-bit.h"
|
|
#include "ippair-bit.h"
|
|
#include "app-layer-htp.h"
|
|
#include "detect-fast-pattern.h"
|
|
#include "util-unittest-helper.h"
|
|
#include "conf-yaml-loader.h"
|
|
#include "pkt-var.h"
|
|
#include "flow-util.h"
|
|
#include "tm-modules.h"
|
|
#include "tmqh-packetpool.h"
|
|
#include "util-conf.h"
|
|
#include "packet.h"
|
|
#include "nallocinc.c"
|
|
|
|
#include <fuzz_pcap.h>
|
|
|
|
int LLVMFuzzerInitialize(const int *argc, char ***argv);
|
|
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
|
|
|
|
static int initialized = 0;
|
|
ThreadVars *tv = NULL;
|
|
DecodeThreadVars *dtv;
|
|
// FlowWorkerThreadData
|
|
void *fwd;
|
|
SCInstance surifuzz;
|
|
SC_ATOMIC_EXTERN(unsigned int, engine_stage);
|
|
|
|
extern const char *configNoChecksum;
|
|
|
|
char *filepath = NULL;
|
|
|
|
int LLVMFuzzerInitialize(const int *argc, char ***argv)
|
|
{
|
|
filepath = dirname(strdup((*argv)[0]));
|
|
nalloc_init((*argv)[0]);
|
|
nalloc_restrict_file_prefix(3);
|
|
return 0;
|
|
}
|
|
|
|
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
|
{
|
|
FPC_buffer_t pkts;
|
|
const u_char *pkt;
|
|
struct pcap_pkthdr header;
|
|
int r;
|
|
Packet *p;
|
|
size_t pcap_cnt = 0;
|
|
|
|
if (initialized == 0) {
|
|
// Redirects logs to /dev/null
|
|
setenv("SC_LOG_OP_IFACE", "file", 0);
|
|
setenv("SC_LOG_FILE", "/dev/null", 0);
|
|
|
|
InitGlobal();
|
|
|
|
GlobalsInitPreConfig();
|
|
SCRunmodeSet(RUNMODE_PCAP_FILE);
|
|
// redirect logs to /tmp
|
|
ConfigSetLogDirectory("/tmp/");
|
|
// disables checksums validation for fuzzing
|
|
if (SCConfYamlLoadString(configNoChecksum, strlen(configNoChecksum)) != 0) {
|
|
abort();
|
|
}
|
|
surifuzz.sig_file = malloc(strlen(filepath) + strlen("/fuzz.rules") + 1);
|
|
memcpy(surifuzz.sig_file, filepath, strlen(filepath));
|
|
memcpy(surifuzz.sig_file + strlen(filepath), "/fuzz.rules", strlen("/fuzz.rules"));
|
|
surifuzz.sig_file[strlen(filepath) + strlen("/fuzz.rules")] = 0;
|
|
surifuzz.sig_file_exclusive = 1;
|
|
// loads rules after init
|
|
surifuzz.delayed_detect = 1;
|
|
|
|
PostConfLoadedSetup(&surifuzz);
|
|
PreRunPostPrivsDropInit(SCRunmodeGet());
|
|
PostConfLoadedDetectSetup(&surifuzz);
|
|
|
|
tv = ThreadVarsAlloc();
|
|
tv->flow_queue = FlowQueueNew();
|
|
if (tv->flow_queue == NULL)
|
|
abort();
|
|
dtv = DecodeThreadVarsAlloc(tv);
|
|
DecodeRegisterPerfCounters(dtv, tv);
|
|
tmm_modules[TMM_FLOWWORKER].ThreadInit(tv, NULL, &fwd);
|
|
StatsSetupPrivate(&tv->stats, NULL);
|
|
|
|
extern uint32_t max_pending_packets;
|
|
max_pending_packets = 128;
|
|
PacketPoolInit();
|
|
if (DetectEngineReload(&surifuzz) < 0) {
|
|
return 0;
|
|
}
|
|
|
|
SC_ATOMIC_SET(engine_stage, SURICATA_RUNTIME);
|
|
initialized = 1;
|
|
}
|
|
|
|
if (size < FPC0_HEADER_LEN) {
|
|
return 0;
|
|
}
|
|
// initialize FPC with the buffer
|
|
if (FPC_init(&pkts, data, size) < 0) {
|
|
return 0;
|
|
}
|
|
|
|
nalloc_start(data, size);
|
|
// loop over packets
|
|
r = FPC_next(&pkts, &header, &pkt);
|
|
p = PacketGetFromAlloc();
|
|
if (p == NULL || r <= 0 || header.ts.tv_sec >= INT_MAX - 3600) {
|
|
goto bail;
|
|
}
|
|
p->ts = SCTIME_FROM_TIMEVAL(&header.ts);
|
|
p->datalink = pkts.datalink;
|
|
p->pkt_src = PKT_SRC_WIRE;
|
|
while (r > 0) {
|
|
if (PacketCopyData(p, pkt, header.caplen) == 0) {
|
|
// DecodePcapFile
|
|
TmEcode ecode = tmm_modules[TMM_DECODEPCAPFILE].Func(tv, p, dtv);
|
|
if (ecode == TM_ECODE_FAILED) {
|
|
break;
|
|
}
|
|
Packet *extra_p = PacketDequeueNoLock(&tv->decode_pq);
|
|
while (extra_p != NULL) {
|
|
PacketFreeOrRelease(extra_p);
|
|
extra_p = PacketDequeueNoLock(&tv->decode_pq);
|
|
}
|
|
tmm_modules[TMM_FLOWWORKER].Func(tv, p, fwd);
|
|
extra_p = PacketDequeueNoLock(&tv->decode_pq);
|
|
while (extra_p != NULL) {
|
|
PacketFreeOrRelease(extra_p);
|
|
extra_p = PacketDequeueNoLock(&tv->decode_pq);
|
|
}
|
|
}
|
|
r = FPC_next(&pkts, &header, &pkt);
|
|
if (r <= 0 || header.ts.tv_sec >= INT_MAX - 3600) {
|
|
goto bail;
|
|
}
|
|
PacketRecycle(p);
|
|
p->ts = SCTIME_FROM_TIMEVAL(&header.ts);
|
|
p->datalink = pkts.datalink;
|
|
pcap_cnt++;
|
|
PcapPacketCntSet(p, pcap_cnt);
|
|
p->pkt_src = PKT_SRC_WIRE;
|
|
}
|
|
bail:
|
|
if (p != NULL) {
|
|
PacketFree(p);
|
|
}
|
|
FlowReset();
|
|
nalloc_end();
|
|
|
|
return 0;
|
|
}
|