Bug #3435
closedafl: Compile/make fails on openSUSE Leap-15.1
Description
I am trying to compile suricata-5.0.1 on openSUSE Leap-15.1 but the build fails with error -
CC threads.o CC tm-modules.o CC tmqh-flow.o CC tmqh-packetpool.o CC tmqh-simple.o CC tm-queuehandlers.o CC tm-queues.o CC tm-threads.o tm-threads.c: In function ‘TmThreadsSlotPktAcqLoopAFL’: tm-threads.c:509:9: error: implicit declaration of function ‘CheckSlot’ [-Werror=implicit-function-declaration] CheckSlot(slot); ^~~~~~~~~ cc1: some warnings being treated as errors make[2]: *** [Makefile:1813: tm-threads.o] Error 1 make[2]: Leaving directory '/usr/local/src/suricata/src' make[1]: *** [Makefile:498: all-recursive] Error 1 make[1]: Leaving directory '/usr/local/src/suricata' make: *** [Makefile:424: all] Error 2
My configure arguments are -
LIBS="-lrt -lnuma" CPPFLAGS="-I/usr/include/libnetfilter_queue/ -I/usr/include/libnfnetlink/" \
./configure --prefix=/usr/local --localstatedir=/var \
--disable-gccmarch-native --enable-gccprotect \
--enable-python --enable-afl --enable-unittests \
--enable-profiling --enable-coccinelle --enable-nflog \
--enable-nfqueue --enable-pfring --enable-prelude \
--enable-af-packet --enable-netmap --enable-libmagic \
--enable-non-bundled-htp \
--enable-luajit --enable-geoip --enable-hiredis \
--with-libpfring-libraries=/usr/local/lib64 \
--with-libpfring-includes=/usr/local/include \
--with-libpcap-libraries=/usr/local/lib64 \
--with-libpcap-includes=/usr/local/include/pcap \
--with-libhs-includes=/usr/include/hs \
--with-libhs-libraries=/usr/lib64 \
--with-libnss-libraries=/usr/lib64 \
--with-libnss-includes=/usr/include/nss3 \
--with-libnetfilter_queue-includes=/usr/include/libnetfilter_queue \
--with-libnetfilter_queue-libraries=/usr/lib64 \
--with-libnetfilter_log-includes=/usr/include/libnetfilter_log \
--with-libnetfilter_log-libraries=/usr/lib64 \
--with-netmap-includes=/usr/include/net
Please let me know how to fix this.
Files
Updated by Dave Peters almost 5 years ago
Dave Peters wrote:
I am trying to compile suricata-5.0.1 on openSUSE Leap-15.1 but the build fails with error -
[...]
My configure arguments are -
[...]Please let me know how to fix this.
I modified src/tm-thread.c and the compile/install went fine. I am not sure of the outcome though. Patch here -
--- src/tm-threads.c 2020-01-04 08:51:52.879568330 -0800
+++ src/tm-threads.c-orig 2020-01-04 08:52:08.863294255 -0800
@@ -70,24 +70,8 @@
#define cpu_set_t cpuset_t
#endif /* OS_FREEBSD */
-#ifdef OS_WIN32
-static inline void SleepUsec(uint64_t usec)
-{
- uint64_t msec = 1;
- if (usec > 1000) {
- msec = usec / 1000;
- }
- Sleep(msec);
-}
-#define SleepMsec(msec) Sleep((msec))
-#else
-#define SleepUsec(usec) usleep((usec))
-#define SleepMsec(msec) usleep((msec) * 1000)
-#endif
-
/* prototypes */
static int SetCPUAffinity(uint16_t cpu);
-
static void TmThreadDeinitMC(ThreadVars *tv);
/* root of the threadvars list */
@@ -200,49 +184,72 @@
*/
static int TmThreadTimeoutLoop(ThreadVars *tv, TmSlot *s)
{
- TmSlot *stream_slot = NULL, *slot = NULL;
- int run = 1;
+ TmSlot *fw_slot = NULL;
int r = TM_ECODE_OK;
- for (slot = s; slot != NULL; slot = slot->slot_next) {
- if (slot->tm_id == TMM_FLOWWORKER)
- {
- stream_slot = slot;
+ for (TmSlot *slot = s; slot != NULL; slot = slot->slot_next) {
+ if (slot->tm_id == TMM_FLOWWORKER) {
+ fw_slot = slot;
break;
}
}
- if (tv->stream_pq == NULL || stream_slot == NULL) {
- SCLogDebug("not running TmThreadTimeoutLoop %p/%p", tv->stream_pq, stream_slot);
+ if (tv->stream_pq == NULL || fw_slot == NULL) {
+ SCLogDebug("not running TmThreadTimeoutLoop %p/%p", tv->stream_pq, fw_slot);
return r;
}
SCLogDebug("flow end loop starting");
- while(run) {
- Packet *p;
- if (tv->stream_pq->len != 0) {
- SCMutexLock(&tv->stream_pq->mutex_q);
- p = PacketDequeue(tv->stream_pq);
- SCMutexUnlock(&tv->stream_pq->mutex_q);
- BUG_ON(p == NULL);
-
- if ((r = TmThreadsSlotProcessPkt(tv, stream_slot, p) != TM_ECODE_OK)) {
- if (r == TM_ECODE_FAILED)
- run = 0;
+ while (1) {
+ SCMutexLock(&tv->stream_pq->mutex_q);
+ uint32_t len = tv->stream_pq->len;
+ SCMutexUnlock(&tv->stream_pq->mutex_q);
+ if (len > 0) {
+ while (len--) {
+ SCMutexLock(&tv->stream_pq->mutex_q);
+ Packet *p = PacketDequeue(tv->stream_pq);
+ SCMutexUnlock(&tv->stream_pq->mutex_q);
+ if (likely(p)) {
+ if ((r = TmThreadsSlotProcessPkt(tv, fw_slot, p) != TM_ECODE_OK)) {
+ if (r == TM_ECODE_FAILED)
+ break;
+ }
+ }
}
} else {
+ if (TmThreadsCheckFlag(tv, THV_KILL)) {
+ break;
+ }
SleepUsec(1);
}
-
- if (tv->stream_pq->len == 0 && TmThreadsCheckFlag(tv, THV_KILL)) {
- run = 0;
- }
}
SCLogDebug("flow end loop complete");
+ StatsSyncCounters(tv);
return r;
}
+/** \internal
+ * \brief check 'slot' pre_pq and post_pq at thread cleanup
+ * and dump detailed info about the state of the packets
+ * and threads if in a unexpected state.
+ */
+static void CheckSlot(const TmSlot *slot)
+{
+ if (slot->slot_pre_pq.len || slot->slot_post_pq.len) {
+ for (Packet *xp = slot->slot_pre_pq.top; xp != NULL; xp = xp->next) {
+ SCLogNotice("pre_pq: slot id %u slot tm_id %u pre_pq.len %u packet src %s",
+ slot->id, slot->tm_id, slot->slot_pre_pq.len, PktSrcToString(xp->pkt_src));
+ }
+ for (Packet *xp = slot->slot_post_pq.top; xp != NULL; xp = xp->next) {
+ SCLogNotice("post_pq: slot id %u slot tm_id %u post_pq.len %u packet src %s",
+ slot->id, slot->tm_id, slot->slot_post_pq.len, PktSrcToString(xp->pkt_src));
+ }
+ TmThreadDumpThreads();
+ abort();
+ }
+}
+
/*
pcap/nfq
@@ -382,9 +389,7 @@
goto error;
}
}
-
- BUG_ON(slot->slot_pre_pq.len);
- BUG_ON(slot->slot_post_pq.len);
+ CheckSlot(slot);
}
tv->stream_pq = NULL;
@@ -501,8 +506,7 @@
}
}
- BUG_ON(slot->slot_pre_pq.len);
- BUG_ON(slot->slot_post_pq.len);
+ CheckSlot(slot);
}
tv->stream_pq = NULL;
@@ -662,8 +666,7 @@
goto error;
}
}
- BUG_ON(s->slot_pre_pq.len);
- BUG_ON(s->slot_post_pq.len);
+ CheckSlot(s);
}
SCLogDebug("%s ending", tv->name);
@@ -798,14 +801,9 @@
ThreadVars *TmThreadsGetTVContainingSlot(TmSlot *tm_slot)
{
- ThreadVars *tv;
- int i;
-
SCMutexLock(&tv_root_lock);
-
- for (i = 0; i < TVT_MAX; i++) {
- tv = tv_root[i];
-
+ for (int i = 0; i < TVT_MAX; i++) {
+ ThreadVars *tv = tv_root[i];
while (tv) {
TmSlot *slots = tv->tm_slots;
while (slots != NULL) {
@@ -818,9 +816,7 @@
tv = tv->next;
}
}
-
SCMutexUnlock(&tv_root_lock);
-
return NULL;
}
@@ -884,16 +880,11 @@
*/
TmSlot *TmSlotGetSlotForTM(int tm_id)
{
- ThreadVars *tv = NULL;
- TmSlot *slots;
- int i;
-
SCMutexLock(&tv_root_lock);
-
- for (i = 0; i < TVT_MAX; i++) {
- tv = tv_root[i];
+ for (int i = 0; i < TVT_MAX; i++) {
+ ThreadVars *tv = tv_root[i];
while (tv) {
- slots = tv->tm_slots;
+ TmSlot *slots = tv->tm_slots;
while (slots != NULL) {
if (slots->tm_id == tm_id) {
SCMutexUnlock(&tv_root_lock);
@@ -904,9 +895,7 @@
tv = tv->next;
}
}
-
SCMutexUnlock(&tv_root_lock);
-
return NULL;
}
@@ -1434,6 +1423,36 @@
return;
}
+static bool ThreadStillHasPackets(ThreadVars *tv)
+{
+ if (tv->inq != NULL) {
+ /* we wait till we dry out all the inq packets, before we
+ * kill this thread. Do note that you should have disabled
+ * packet acquire by now using TmThreadDisableReceiveThreads()*/
+ if (!(strlen(tv->inq->name) == strlen("packetpool") &&
+ strcasecmp(tv->inq->name, "packetpool") == 0)) {
+ PacketQueue *q = &trans_q[tv->inq->id];
+ SCMutexLock(&q->mutex_q);
+ uint32_t len = q->len;
+ SCMutexUnlock(&q->mutex_q);
+ if (len != 0) {
+ return true;
+ }
+ }
+ }
+
+ if (tv->stream_pq != NULL) {
+ SCMutexLock(&tv->stream_pq->mutex_q);
+ uint32_t len = tv->stream_pq->len;
+ SCMutexUnlock(&tv->stream_pq->mutex_q);
+
+ if (len != 0) {
+ return true;
+ }
+ }
+ return false;
+}
+
/**
* \brief Kill a thread.
*
@@ -1454,19 +1473,6 @@
return 1;
}
- if (tv->inq != NULL) {
- /* we wait till we dry out all the inq packets, before we
- * kill this thread. Do note that you should have disabled
- * packet acquire by now using TmThreadDisableReceiveThreads()*/
- if (!(strlen(tv->inq->name) == strlen("packetpool") &&
- strcasecmp(tv->inq->name, "packetpool") == 0)) {
- PacketQueue *q = &trans_q[tv->inq->id];
- if (q->len != 0) {
- return 0;
- }
- }
- }
-
/* set the thread flag informing the thread that it needs to be
* terminated */
TmThreadsSetFlag(tv, THV_KILL);
@@ -1511,7 +1517,7 @@
/** \internal
*
* \brief make sure that all packet threads are done processing their
- * in-flight packets
+ * in-flight packets, including 'injected' flow packets.
*/
static void TmThreadDrainPacketThreads(void)
{
@@ -1533,23 +1539,16 @@
/* all receive threads are part of packet processing threads */
tv = tv_root[TVT_PPT];
while (tv) {
- if (tv->inq != NULL) {
+ if (ThreadStillHasPackets(tv)) {
/* we wait till we dry out all the inq packets, before we
* kill this thread. Do note that you should have disabled
* packet acquire by now using TmThreadDisableReceiveThreads()*/
- if (!(strlen(tv->inq->name) == strlen("packetpool") &&
- strcasecmp(tv->inq->name, "packetpool") == 0)) {
- PacketQueue *q = &trans_q[tv->inq->id];
- if (q->len != 0) {
- SCMutexUnlock(&tv_root_lock);
+ SCMutexUnlock(&tv_root_lock);
- /* sleep outside lock */
- SleepMsec(1);
- goto again;
- }
- }
+ /* sleep outside lock */
+ SleepMsec(1);
+ goto again;
}
-
tv = tv->next;
}
@@ -1605,20 +1604,14 @@
}
if (disable) {
- if (tv->inq != NULL) {
+ if (ThreadStillHasPackets(tv)) {
/* we wait till we dry out all the inq packets, before we
* kill this thread. Do note that you should have disabled
* packet acquire by now using TmThreadDisableReceiveThreads()*/
- if (!(strlen(tv->inq->name) == strlen("packetpool") &&
- strcasecmp(tv->inq->name, "packetpool") == 0)) {
- PacketQueue *q = &trans_q[tv->inq->id];
- if (q->len != 0) {
- SCMutexUnlock(&tv_root_lock);
- /* don't sleep while holding a lock */
- SleepMsec(1);
- goto again;
- }
- }
+ SCMutexUnlock(&tv_root_lock);
+ /* don't sleep while holding a lock */
+ SleepMsec(1);
+ goto again;
}
/* we found a receive TV. Send it a KILL_PKTACQ signal. */
@@ -1657,6 +1650,21 @@
return;
}
+static void TmThreadDebugValidateNoMorePackets(void)
+{
+#ifdef DEBUG_VALIDATION
+ SCMutexLock(&tv_root_lock);
+ for (ThreadVars *tv = tv_root[TVT_PPT]; tv != NULL; tv = tv->next) {
+ if (ThreadStillHasPackets(tv)) {
+ SCMutexUnlock(&tv_root_lock);
+ TmThreadDumpThreads();
+ abort();
+ }
+ }
+ SCMutexUnlock(&tv_root_lock);
+#endif
+}
+
/**
* \brief Disable all threads having the specified TMs.
*/
@@ -1668,6 +1676,7 @@
/* first drain all packet threads of their packets */
TmThreadDrainPacketThreads();
+ TmThreadDebugValidateNoMorePackets();
gettimeofday(&start_ts, NULL);
again:
@@ -1688,22 +1697,6 @@
* receive TM amongst the slots in a tv, it indicates we are done
* with all receive threads */
while (tv) {
- if (tv->inq != NULL) {
- /* we wait till we dry out all the inq packets, before we
- * kill this thread. Do note that you should have disabled
- * packet acquire by now using TmThreadDisableReceiveThreads()*/
- if (!(strlen(tv->inq->name) == strlen("packetpool") &&
- strcasecmp(tv->inq->name, "packetpool") == 0)) {
- PacketQueue *q = &trans_q[tv->inq->id];
- if (q->len != 0) {
- SCMutexUnlock(&tv_root_lock);
- /* don't sleep while holding a lock */
- SleepMsec(1);
- goto again;
- }
- }
- }
-
/* we found our receive TV. Send it a KILL signal. This is all
* we need to do to kill receive threads */
TmThreadsSetFlag(tv, THV_KILL);
@@ -2227,6 +2220,46 @@
return cnt;
}
+static void TmThreadDoDumpSlots(const ThreadVars *tv)
+{
+ for (TmSlot *s = tv->tm_slots; s != NULL; s = s->slot_next) {
+ TmModule *m = TmModuleGetById(s->tm_id);
+ SCLogNotice("tv %p: -> slot %p id %d tm_id %d name %s %s",
+ tv, s, s->id, s->tm_id, m->name, (tv->type == 0 && tv->stream_pq == &s->slot_post_pq) ? "<==== stream_pq" : "");
+ if (tv->type == 0 && tv->stream_pq == &s->slot_pre_pq) {
+ SCLogNotice("tv %p: -> slot %p/%d holds stream_pq %p IN PRE_PQ SUPER WEIRD", tv, s, s->id, tv->stream_pq);
+ }
+ for (Packet *xp = s->slot_pre_pq.top; xp != NULL; xp = xp->next) {
+ SCLogNotice("tv %p: ==> pre_pq: slot id %u slot tm_id %u pre_pq.len %u packet src %s",
+ tv, s->id, s->tm_id, s->slot_pre_pq.len, PktSrcToString(xp->pkt_src));
+ }
+ for (Packet *xp = s->slot_post_pq.top; xp != NULL; xp = xp->next) {
+ SCLogNotice("tv %p: ==> post_pq: slot id %u slot tm_id %u post_pq.len %u packet src %s",
+ tv, s->id, s->tm_id, s->slot_post_pq.len, PktSrcToString(xp->pkt_src));
+ }
+ }
+}
+
+void TmThreadDumpThreads(void)
+{
+ SCMutexLock(&tv_root_lock);
+ for (int i = 0; i < TVT_MAX; i++) {
+ ThreadVars *tv = tv_root[i];
+ while (tv != NULL) {
+ const uint32_t flags = SC_ATOMIC_GET(tv->flags);
+ SCLogNotice("tv %p: type %u name %s tmm_flags %02X flags %X stream_pq %p",
+ tv, tv->type, tv->name, tv->tmm_flags, flags, tv->stream_pq);
+ if (tv->inq && tv->stream_pq == &trans_q[tv->inq->id]) {
+ SCLogNotice("tv %p: stream_pq at tv->inq %u", tv, tv->inq->id);
+ }
+ TmThreadDoDumpSlots(tv);
+ tv = tv->next;
+ }
+ }
+ SCMutexUnlock(&tv_root_lock);
+ TmThreadsListThreads();
+}
+
typedef struct Thread_ {
ThreadVars *tv; /**< threadvars structure */
const char *name;
@@ -2256,7 +2289,15 @@
t = &thread_store.threads[s];
if (t == NULL || t->in_use == 0)
continue;
- SCLogInfo("Thread %"PRIuMAX", %s type %d, tv %p", (uintmax_t)s+1, t->name, t->type, t->tv);
+
+ SCLogNotice("Thread %"PRIuMAX", %s type %d, tv %p in_use %d",
+ (uintmax_t)s+1, t->name, t->type, t->tv, t->in_use);
+ if (t->tv) {
+ ThreadVars *tv = t->tv;
+ const uint32_t flags = SC_ATOMIC_GET(tv->flags);
+ SCLogNotice("tv %p type %u name %s tmm_flags %02X flags %X",
+ tv, tv->type, tv->name, tv->tmm_flags, flags);
+ }
}
SCMutexUnlock(&thread_store_lock);
Please let me know whether this is legit or my binary will break/die.
Updated by Dave Peters almost 5 years ago
The error is gone after removing --enable-afl. Thanks to Jason Ish for suggesting this on irc.
# suricata --build-info
This is Suricata version 5.0.1 RELEASE
Features: UNITTESTS NFQ PCAP_SET_BUFF PF_RING AF_PACKET NETMAP HAVE_PACKET_FANOUT LIBCAP_NG LIBNET1.1 HAVE_HTP_URI_NORMALIZE_HOOK PCRE_JIT HAVE_NSS HAVE_LUA HAVE_LUAJIT HAVE_LIBJANSSON PROFILING TLS MAGIC RUST
SIMD support: none
Atomic intrinsics: 1 2 4 8 byte(s)
64-bits, Little-endian architecture
GCC version 7.4.0, C version 199901
compiled with -fstack-protector
compiled with _FORTIFY_SOURCE=2
L1 cache line size (CLS)=64
thread local storage method: __thread
compiled with LibHTP v0.5.32, linked against LibHTP v0.5.32
Suricata Configuration:
AF_PACKET support: yes
eBPF support: no
XDP support: no
PF_RING support: yes
NFQueue support: yes
NFLOG support: yes
IPFW support: no
Netmap support: yes v13
DAG enabled: no
Napatech enabled: no
WinDivert enabled: no
Unix socket enabled: yes
Detection enabled: yes
Libmagic support: yes
libnss support: yes
libnspr support: yes
libjansson support: yes
hiredis support: yes
hiredis async with libevent: yes
Prelude support: yes
PCRE jit: yes
LUA support: yes, through luajit
libluajit: yes
GeoIP2 support: yes
Non-bundled htp: yes
Old barnyard2 support: no
Hyperscan support: yes
Libnet support: yes
liblz4 support: yes
Rust support: yes
Rust strict mode: no
Rust compiler path: /usr/bin/rustc
Rust compiler version: rustc 1.36.0
Cargo path: /usr/bin/cargo
Cargo version: cargo 1.36.0
Cargo vendor: no
Python support: yes
Python path: /usr/bin/python3
Python distutils yes
Python yaml yes
Install suricatactl: yes
Install suricatasc: yes
Install suricata-update: yes
Profiling enabled: yes
Profiling locks enabled: no
Development settings:
Coccinelle / spatch: yes
Unit tests enabled: yes
Debug output enabled: no
Debug validation enabled: no
Generic build parameters:
Installation prefix: /usr
Configuration directory: /etc/suricata/
Log directory: /var/log/suricata/
--prefix /usr
--sysconfdir /etc
--localstatedir /var
--datarootdir /usr/share
Host: x86_64-pc-linux-gnu
Compiler: gcc (exec name) / gcc (real)
GCC Protect enabled: yes
GCC march native enabled: no
GCC Profile enabled: no
Position Independent Executable enabled: yes
CFLAGS -g -O2 -I${srcdir}/../rust/gen/c-headers
PCAP_CFLAGS -I/usr/local/include
SECCFLAGS -fstack-protector -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security
Updated by Victor Julien almost 5 years ago
- Subject changed from Compile/make fails on openSUSE Leap-15.1 to afl: Compile/make fails on openSUSE Leap-15.1
- Effort deleted (
medium) - Difficulty deleted (
medium) - Label deleted (
Beginner)
It seems the issue here is that --enable-afl was used. This is meant only for fuzz testing certain Suricata internals.
Updated by Zackeus Bengtsson almost 5 years ago
Victor Julien wrote:
It seems the issue here is that --enable-afl was used. This is meant only for fuzz testing certain Suricata internals.
I had the same issue. By using git bisect between a known good version (suricata-4.1.5) and known bad (suricata-4.1.6) I found that commit "166b2a8216f0c7d8e4b52f990f319fe3aee9f6ef - threading: improve thread queues checking by dumping more info" introduced the issue, and has been present since.
The issue is that CheckSlot is declared within the scope of "#ifndef AFLFUZZ_PCAP_RUNMODE" (line 250 tm-threads.c), but is also used outside the scope, within #ifdef AFLFUZZ_PCAP_RUNMODE (line 582 & 682).
Hope this helps and that you'll get a fix out :)
Updated by Victor Julien almost 5 years ago
- Status changed from New to Closed
- Assignee set to Victor Julien
- Target version set to 6.0.0beta1