Counters: fix delayed-detect counter registration

Make sure we register the detect.alerts counter before packet runtime starts
even in delayed detect mode. The registration of new counters at packet
runtime is not supported by the counters api and might lead to crashes as there
is no proper locking to allow for this operation.

This changes how delayed detect works a bit. Now we call the ThreadInit
callback twice. The first call will only register the counter. The 2nd call
will do all the other setup. This way the counter is registered before the
counters api starts operating in the packet runtime.

Fixes the segv reported in ticket #1018.
pull/605/merge
Victor Julien 12 years ago
parent 9e88c51e24
commit 7ebd1e6433

@ -1210,12 +1210,38 @@ static TmEcode ThreadCtxDoInit (DetectEngineCtx *de_ctx, DetectEngineThreadCtx *
return TM_ECODE_OK;
}
/** \brief initialize thread specific detection engine context
*
* \note there is a special case when using delayed detect. In this case the
* function is called twice per thread. The first time the rules are not
* yet loaded. de_ctx->delayed_detect_initialized will be 0. The 2nd
* time they will be loaded. de_ctx->delayed_detect_initialized will be 1.
* This is needed to do the per thread counter registration before the
* packet runtime starts. In delayed detect mode, the first call will
* return a NULL ptr through the data ptr.
*
* \param tv ThreadVars for this thread
* \param initdata pointer to de_ctx
* \param data[out] pointer to store our thread detection ctx
*
* \retval TM_ECODE_OK if all went well
* \retval TM_ECODE_FAILED on serious erro
*/
TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data)
{
DetectEngineCtx *de_ctx = (DetectEngineCtx *)initdata;
if (de_ctx == NULL)
return TM_ECODE_FAILED;
/* first register the counter. In delayed detect mode we exit right after if the
* rules haven't been loaded yet. */
uint16_t counter_alerts = SCPerfTVRegisterCounter("detect.alert", tv,
SC_PERF_TYPE_UINT64, "NULL");
if (de_ctx->delayed_detect == 1 && de_ctx->delayed_detect_initialized == 0) {
*data = NULL;
return TM_ECODE_OK;
}
DetectEngineThreadCtx *det_ctx = SCMalloc(sizeof(DetectEngineThreadCtx));
if (unlikely(det_ctx == NULL))
return TM_ECODE_FAILED;
@ -1228,8 +1254,7 @@ TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data)
return TM_ECODE_FAILED;
/** alert counter setup */
det_ctx->counter_alerts = SCPerfTVRegisterCounter("detect.alert", tv,
SC_PERF_TYPE_UINT64, "NULL");
det_ctx->counter_alerts = counter_alerts;
/* pass thread data back to caller */
*data = (void *)det_ctx;

@ -719,6 +719,8 @@ typedef struct DetectEngineCtx_ {
/** Is detect engine using a delayed init */
int delayed_detect;
/** Did we load the signatures? */
int delayed_detect_initialized;
/** list of keywords that need thread local ctxs */
DetectEngineThreadKeywordCtxItem *keyword_list;

@ -2139,6 +2139,7 @@ int main(int argc, char **argv)
if (suri.delayed_detect) {
if (LoadSignatures(de_ctx, &suri) != TM_ECODE_OK)
exit(EXIT_FAILURE);
de_ctx->delayed_detect_initialized = 1;
TmThreadActivateDummySlot();
SCLogNotice("Signature(s) loaded, Detect thread(s) activated.");
}

@ -1063,7 +1063,6 @@ void TmSlotSetFuncAppendDelayed(ThreadVars *tv, TmModule *tm, void *data,
dslot->SlotFunc = SC_ATOMIC_GET(slot->SlotFunc);
(void)SC_ATOMIC_SET(slot->SlotFunc, TmDummyFunc);
dslot->SlotThreadInit = slot->SlotThreadInit;
slot->SlotThreadInit = NULL;
dslot->slot = slot;
TAILQ_INSERT_TAIL(&dummy_slots, dslot, next);

Loading…
Cancel
Save