diff options
Diffstat (limited to 'src/tests/fuzz/fuzz_sigpcap_aware.c')
-rw-r--r-- | src/tests/fuzz/fuzz_sigpcap_aware.c | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/src/tests/fuzz/fuzz_sigpcap_aware.c b/src/tests/fuzz/fuzz_sigpcap_aware.c new file mode 100644 index 0000000..d245476 --- /dev/null +++ b/src/tests/fuzz/fuzz_sigpcap_aware.c @@ -0,0 +1,203 @@ +/** + * @file + * @author Philippe Antoine <contact@catenacyber.fr> + * fuzz target for AppLayerProtoDetectGetProto + */ + +#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 "flow-worker.h" +#include "tm-modules.h" +#include "tmqh-packetpool.h" +#include "util-conf.h" +#include "packet.h" + +#include <fuzz_pcap.h> + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); + +static int initialized = 0; +ThreadVars tv; +DecodeThreadVars *dtv; +// FlowWorkerThreadData +void *fwd; +SCInstance surifuzz; +SC_ATOMIC_EXTERN(unsigned int, engine_stage); + +#include "confyaml.c" + +static void SigGenerateAware(const uint8_t *data, size_t size, char *r, size_t *len) +{ + *len = snprintf(r, 511, "alert ip any any -> any any ("); + for (size_t i = 0; i + 1 < size && *len < 511; i++) { + if (data[i] & 0x80) { + size_t off = (data[i] & 0x7F + ((data[i + 1] & 0xF) << 7)) % + (sizeof(sigmatch_table) / sizeof(SigTableElmt)); + if (sigmatch_table[off].flags & SIGMATCH_NOOPT || + ((data[i + 1] & 0x80) && sigmatch_table[off].flags & SIGMATCH_OPTIONAL_OPT)) { + *len += snprintf(r + *len, 511 - *len, "; %s;", sigmatch_table[off].name); + } else { + *len += snprintf(r + *len, 511 - *len, "; %s:", sigmatch_table[off].name); + } + i++; + } else { + r[*len] = data[i]; + *len = *len + 1; + } + } + if (*len < 511) { + *len += snprintf(r + *len, 511 - *len, ")"); + } else { + r[511] = 0; + *len = 511; + } +} + +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 pos; + 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(); + run_mode = RUNMODE_PCAP_FILE; + // redirect logs to /tmp + ConfigSetLogDirectory("/tmp/"); + // disables checksums validation for fuzzing + if (ConfYamlLoadString(configNoChecksum, strlen(configNoChecksum)) != 0) { + abort(); + } + // do not load rules before reproducible DetectEngineReload + remove("/tmp/fuzz.rules"); + surifuzz.sig_file = strdup("/tmp/fuzz.rules"); + surifuzz.sig_file_exclusive = 1; + // loads rules after init + surifuzz.delayed_detect = 1; + + PostConfLoadedSetup(&surifuzz); + PreRunPostPrivsDropInit(run_mode); + PostConfLoadedDetectSetup(&surifuzz); + + memset(&tv, 0, sizeof(tv)); + 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); + + extern uint16_t max_pending_packets; + max_pending_packets = 128; + PacketPoolInit(); + SC_ATOMIC_SET(engine_stage, SURICATA_RUNTIME); + initialized = 1; + } + + if (size < 1 + FPC0_HEADER_LEN) { + return 0; + } + for (pos = 0; pos < size - FPC0_HEADER_LEN; pos++) { + if (data[pos] == 0) { + break; + } + } + // initialize FPC with the buffer + if (FPC_init(&pkts, data + pos + 1, size - pos - 1) < 0) { + return 0; + } + + // dump signatures to a file so as to reuse SigLoadSignatures + char sigaware[512]; + size_t len; + SigGenerateAware(data, pos + 1, sigaware, &len); + if (TestHelperBufferToFile(surifuzz.sig_file, (uint8_t *)sigaware, len) < 0) { + return 0; + } + + if (DetectEngineReload(&surifuzz) < 0) { + return 0; + } + DetectEngineThreadCtx *old_det_ctx = FlowWorkerGetDetectCtxPtr(fwd); + + DetectEngineCtx *de_ctx = DetectEngineGetCurrent(); + de_ctx->ref_cnt--; + DetectEngineThreadCtx *new_det_ctx = DetectEngineThreadCtxInitForReload(&tv, de_ctx, 1); + FlowWorkerReplaceDetectCtx(fwd, new_det_ctx); + + DetectEngineThreadCtxDeinit(NULL, old_det_ctx); + + // loop over packets + r = FPC_next(&pkts, &header, &pkt); + p = PacketGetFromAlloc(); + if (r <= 0 || header.ts.tv_sec >= INT_MAX - 3600) { + goto bail; + } + p->pkt_src = PKT_SRC_WIRE; + p->ts = SCTIME_FROM_TIMEVAL(&header.ts); + p->datalink = pkts.datalink; + 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->pkt_src = PKT_SRC_WIRE; + p->ts = SCTIME_FROM_TIMEVAL(&header.ts); + p->datalink = pkts.datalink; + pcap_cnt++; + p->pcap_cnt = pcap_cnt; + } +bail: + PacketFree(p); + FlowReset(); + + return 0; +} |