From: Victor Julien Date: Sat, 5 Dec 2015 13:48:05 +0000 (+0100) Subject: afl: special 'single' runmode X-Git-Tag: suricata-3.1RC1~266 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e824a8be763135d70e134f94ac04d7c45b6e7917;p=thirdparty%2Fsuricata.git afl: special 'single' runmode To avoid threading, this 'single' mode doesn't run in it's own thread but instead runs in the main thread. --- diff --git a/src/runmode-pcap-file.c b/src/runmode-pcap-file.c index 62e18c5458..4d44814be7 100644 --- a/src/runmode-pcap-file.c +++ b/src/runmode-pcap-file.c @@ -116,10 +116,16 @@ int RunModeFilePcapSingle(void) TmThreadSetCPU(tv, DETECT_CPU_SET); +#ifndef AFLFUZZ_PCAP_RUNMODE if (TmThreadSpawn(tv) != TM_ECODE_OK) { SCLogError(SC_ERR_RUNMODE, "TmThreadSpawn failed"); exit(EXIT_FAILURE); } +#else + /* in afl mode we don't spawn a new thread, but run the pipeline + * in the main thread */ + tv->tm_func(tv); +#endif return 0; } diff --git a/src/suricata-common.h b/src/suricata-common.h index ff8d514725..da6487e162 100644 --- a/src/suricata-common.h +++ b/src/suricata-common.h @@ -230,6 +230,7 @@ #define AFLFUZZ_NO_RANDOM 1 #define AFLFUZZ_DISABLE_MGTTHREADS 1 +#define AFLFUZZ_PCAP_RUNMODE 1 /* we need this to stringify the defines which are supplied at compiletime see: http://gcc.gnu.org/onlinedocs/gcc-3.4.1/cpp/Stringification.html#Stringification */ diff --git a/src/tm-threads.c b/src/tm-threads.c index 87b424b2e6..a1cf5528fb 100644 --- a/src/tm-threads.c +++ b/src/tm-threads.c @@ -386,6 +386,120 @@ error: return NULL; } +#ifdef AFLFUZZ_PCAP_RUNMODE +/** \brief simplified loop to speed up AFL + * + * The loop runs in the caller's thread. No separate thread. + */ +void *TmThreadsSlotPktAcqLoopAFL(void *td) +{ + SCLogNotice("AFL mode starting"); + + ThreadVars *tv = (ThreadVars *)td; + TmSlot *s = tv->tm_slots; + char run = 1; + TmEcode r = TM_ECODE_OK; + TmSlot *slot = NULL; + + PacketPoolInit(); + + /* check if we are setup properly */ + if (s == NULL || s->PktAcqLoop == NULL || tv->tmqh_in == NULL || tv->tmqh_out == NULL) { + SCLogError(SC_ERR_FATAL, "TmSlot or ThreadVars badly setup: s=%p," + " PktAcqLoop=%p, tmqh_in=%p," + " tmqh_out=%p", + s, s ? s->PktAcqLoop : NULL, tv->tmqh_in, tv->tmqh_out); + EngineKill(); + + TmThreadsSetFlag(tv, THV_CLOSED | THV_RUNNING_DONE); + return NULL; + } + + for (slot = s; slot != NULL; slot = slot->slot_next) { + if (slot->SlotThreadInit != NULL) { + void *slot_data = NULL; + r = slot->SlotThreadInit(tv, slot->slot_initdata, &slot_data); + if (r != TM_ECODE_OK) { + if (r == TM_ECODE_DONE) { + EngineDone(); + TmThreadsSetFlag(tv, THV_CLOSED | THV_INIT_DONE | THV_RUNNING_DONE); + goto error; + } else { + EngineKill(); + TmThreadsSetFlag(tv, THV_CLOSED | THV_RUNNING_DONE); + goto error; + } + } + (void)SC_ATOMIC_SET(slot->slot_data, slot_data); + } + memset(&slot->slot_pre_pq, 0, sizeof(PacketQueue)); + SCMutexInit(&slot->slot_pre_pq.mutex_q, NULL); + memset(&slot->slot_post_pq, 0, sizeof(PacketQueue)); + SCMutexInit(&slot->slot_post_pq.mutex_q, NULL); + + /* get the 'pre qeueue' from module before the stream module */ + if (slot->slot_next != NULL && slot->slot_next->tm_id == TMM_STREAMTCP) { + SCLogDebug("pre-stream packetqueue %p (postq)", &s->slot_post_pq); + tv->stream_pq = &slot->slot_post_pq; + /* if the stream module is the first, get the threads input queue */ + } else if (slot == (TmSlot *)tv->tm_slots && slot->tm_id == TMM_STREAMTCP) { + tv->stream_pq = &trans_q[tv->inq->id]; + SCLogDebug("pre-stream packetqueue %p (inq)", &slot->slot_pre_pq); + } + } + + StatsSetupPrivate(tv); + + TmThreadsSetFlag(tv, THV_INIT_DONE); + + while(run) { + /* run right away */ + + r = s->PktAcqLoop(tv, SC_ATOMIC_GET(s->slot_data), s); + + if (r == TM_ECODE_FAILED || TmThreadsCheckFlag(tv, THV_KILL_PKTACQ) + || suricata_ctl_flags) { + run = 0; + } + if (r == TM_ECODE_DONE) { + run = 0; + } + } + StatsSyncCounters(tv); + + TmThreadsSetFlag(tv, THV_FLOW_LOOP); + + TmThreadsSetFlag(tv, THV_RUNNING_DONE); + + PacketPoolDestroy(); + + for (slot = s; slot != NULL; slot = slot->slot_next) { + if (slot->SlotThreadExitPrintStats != NULL) { + slot->SlotThreadExitPrintStats(tv, SC_ATOMIC_GET(slot->slot_data)); + } + + if (slot->SlotThreadDeinit != NULL) { + r = slot->SlotThreadDeinit(tv, SC_ATOMIC_GET(slot->slot_data)); + if (r != TM_ECODE_OK) { + TmThreadsSetFlag(tv, THV_CLOSED); + goto error; + } + } + + BUG_ON(slot->slot_pre_pq.len); + BUG_ON(slot->slot_post_pq.len); + } + + tv->stream_pq = NULL; + SCLogDebug("%s ending", tv->name); + TmThreadsSetFlag(tv, THV_CLOSED); + return NULL; + +error: + tv->stream_pq = NULL; + return NULL; +} +#endif /** * \todo Only the first "slot" currently makes the "post_pq" available @@ -655,7 +769,11 @@ TmEcode TmThreadSetSlots(ThreadVars *tv, char *name, void *(*fn_p)(void *)) if (strcmp(name, "varslot") == 0) { tv->tm_func = TmThreadsSlotVar; } else if (strcmp(name, "pktacqloop") == 0) { +#ifndef AFLFUZZ_PCAP_RUNMODE tv->tm_func = TmThreadsSlotPktAcqLoop; +#else + tv->tm_func = TmThreadsSlotPktAcqLoopAFL; +#endif } else if (strcmp(name, "management") == 0) { tv->tm_func = TmThreadsManagement; } else if (strcmp(name, "command") == 0) {