]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
afl: special 'single' runmode
authorVictor Julien <victor@inliniac.net>
Sat, 5 Dec 2015 13:48:05 +0000 (14:48 +0100)
committerVictor Julien <victor@inliniac.net>
Tue, 12 Apr 2016 13:19:59 +0000 (15:19 +0200)
To avoid threading, this 'single' mode doesn't run in it's own thread
but instead runs in the main thread.

src/runmode-pcap-file.c
src/suricata-common.h
src/tm-threads.c

index 62e18c54583b3bf602ade8fdf2f04bd10ac29990..4d44814be73b5f4df2e4da086b6425f0aa7cd264 100644 (file)
@@ -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;
 }
index ff8d51472529b10aeef1c8dac5dbda4241091507..da6487e162cc9eb493307dbd5aef7d4c18bc2768 100644 (file)
 
 #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 */
index 87b424b2e6158dd149aee27f0356e7b26995c01e..a1cf5528fb0e16a05a5f1619b9d11ac80845bd72 100644 (file)
@@ -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) {