diff --git a/src/counters.c b/src/counters.c index cf4f9f3e9e..53e9c9cace 100644 --- a/src/counters.c +++ b/src/counters.c @@ -433,6 +433,12 @@ static void SCPerfReleaseOPCtx() */ static void *SCPerfMgmtThread(void *arg) { + /* block usr2. usr2 to be handled by the main thread only */ + sigset_t x; + sigemptyset(&x); + sigaddset(&x, SIGUSR2); + sigprocmask(SIG_BLOCK, &x, NULL); + ThreadVars *tv_local = (ThreadVars *)arg; uint8_t run = 1; struct timespec cond_time; @@ -487,6 +493,12 @@ static void *SCPerfMgmtThread(void *arg) */ static void *SCPerfWakeupThread(void *arg) { + /* block usr2. usr2 to be handled by the main thread only */ + sigset_t x; + sigemptyset(&x); + sigaddset(&x, SIGUSR2); + sigprocmask(SIG_BLOCK, &x, NULL); + ThreadVars *tv_local = (ThreadVars *)arg; uint8_t run = 1; ThreadVars *tv = NULL; diff --git a/src/detect-engine-state.c b/src/detect-engine-state.c index 3cdf0d7444..3e714d720b 100644 --- a/src/detect-engine-state.c +++ b/src/detect-engine-state.c @@ -366,7 +366,7 @@ void DeStateStoreFileNoMatch(DetectEngineState *de_state, uint8_t direction, * \retval 1 has state * \retval 0 has no state */ -int DeStateFlowHasState(Flow *f, uint8_t flags, uint16_t alversion) { +int DeStateFlowHasState(DetectEngineCtx *de_ctx, Flow *f, uint8_t flags, uint16_t alversion) { SCEnter(); int r = 0; @@ -679,7 +679,15 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, * the last SigMatch that didn't match */ if (f->de_state == NULL) { f->de_state = DetectEngineStateAlloc(); + f->de_state->de_ctx_id = de_ctx->id; + } else { + if (f->de_state->de_ctx_id != de_ctx->id) { + DetectEngineStateReset(f->de_state); + f->de_state = DetectEngineStateAlloc(); + f->de_state->de_ctx_id = de_ctx->id; + } } + if (f->de_state != NULL) { /* \todo shift to an array to transfer these match values*/ DeStateSignatureAppend(f->de_state, s, sm, match_flags); @@ -727,6 +735,13 @@ int DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, Dete if (f->de_state == NULL || f->de_state->cnt == 0) goto end; + if (f->de_state->de_ctx_id != de_ctx->id) { + DetectEngineStateReset(f->de_state); + f->de_state = NULL; + SCMutexUnlock(&f->de_state_m); + SCReturnInt(0); + } + DeStateResetFileInspection(f, alproto, alstate); /* loop through the stores */ diff --git a/src/detect-engine-state.h b/src/detect-engine-state.h index ad717be3ee..1602dc1ad1 100644 --- a/src/detect-engine-state.h +++ b/src/detect-engine-state.h @@ -125,6 +125,10 @@ typedef struct DetectEngineState_ { * cannot match in to client direction. */ uint16_t toserver_filestore_cnt;/**< number of sigs with filestore that * cannot match in to server direction. */ + + /* the de_ctx id that the state belongs to */ + uint32_t de_ctx_id; + uint16_t flags; } DetectEngineState; @@ -137,7 +141,7 @@ void DetectEngineStateReset(DetectEngineState *state); DetectEngineState *DetectEngineStateAlloc(void); void DetectEngineStateFree(DetectEngineState *); -int DeStateFlowHasState(Flow *, uint8_t, uint16_t); +int DeStateFlowHasState(DetectEngineCtx *, Flow *, uint8_t, uint16_t); int DeStateDetectStartDetection(ThreadVars *, DetectEngineCtx *, DetectEngineThreadCtx *, Signature *, Flow *, uint8_t, void *, diff --git a/src/detect-engine.c b/src/detect-engine.c index 46cea5db28..669294ea61 100644 --- a/src/detect-engine.c +++ b/src/detect-engine.c @@ -22,6 +22,7 @@ */ #include "suricata-common.h" +#include "suricata.h" #include "debug.h" #include "detect.h" #include "flow.h" @@ -49,11 +50,14 @@ //#include "util-mpm.h" #include "util-classification-config.h" #include "util-reference-config.h" +#include "util-threshold-config.h" #include "util-error.h" #include "util-hash.h" #include "util-byte.h" #include "util-debug.h" #include "util-unittest.h" +#include "util-action.h" +#include "util-magic.h" #include "util-var-name.h" @@ -61,8 +65,236 @@ #define DETECT_ENGINE_DEFAULT_INSPECTION_RECURSION_LIMIT 3000 +static uint32_t detect_engine_ctx_id = 0; + +static TmEcode DetectEngineThreadCtxInitForLiveRuleSwap(ThreadVars *, void *, void **); + static uint8_t DetectEngineCtxLoadConf(DetectEngineCtx *); +static void *DetectEngineLiveRuleSwap(void *arg) +{ + SCEnter(); + + SCLogInfo("===== Starting live rule swap triggered by user signal USR2 ====="); + + ThreadVars *tv_local = (ThreadVars *)arg; + + /* block usr2. usr2 to be handled by the main thread only */ + sigset_t x; + sigemptyset(&x); + sigaddset(&x, SIGUSR2); + sigprocmask(SIG_BLOCK, &x, NULL); + + ConfDeInit(); + ConfInit(); + + /* re-load the yaml file */ + if (conf_filename != NULL) { + if (ConfYamlLoadFile(conf_filename) != 0) { + /* Error already displayed. */ + exit(EXIT_FAILURE); + } + + ConfNode *file; + ConfNode *includes = ConfGetNode("include"); + if (includes != NULL) { + TAILQ_FOREACH(file, &includes->head, next) { + char *ifile = ConfLoadCompleteIncludePath(file->val); + SCLogInfo("Live Rule Swap: Including: %s", ifile); + + if (ConfYamlLoadFile(ifile) != 0) { + /* Error already displayed. */ + exit(EXIT_FAILURE); + } + } + } + } /* if (conf_filename != NULL) */ + +#if 0 + ConfDump(); +#endif + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + + SCClassConfLoadClassficationConfigFile(de_ctx); + SCRConfLoadReferenceConfigFile(de_ctx); + + if (ActionInitConfig() < 0) { + exit(EXIT_FAILURE); + } + + //if (MagicInit() != 0) + // exit(EXIT_FAILURE); + + if (SigLoadSignatures(de_ctx, NULL, FALSE) < 0) { + SCLogError(SC_ERR_NO_RULES_LOADED, "Loading signatures failed."); + if (de_ctx->failure_fatal) + exit(EXIT_FAILURE); + } + + SCThresholdConfInitContext(de_ctx, NULL); + + + /* start the process of swapping detect threads ctxs */ + + SCMutexLock(&tv_root_lock); + + int no_of_detect_tvs = 0; + ThreadVars *tv = tv_root[TVT_PPT]; + while (tv) { + /* obtain the slots for this TV */ + TmSlot *slots = tv->tm_slots; + while (slots != NULL) { + TmModule *tm = TmModuleGetById(slots->tm_id); + + if (suricata_ctl_flags != 0) { + TmThreadsSetFlag(tv_local, THV_CLOSED); + + SCLogInfo("===== Live rule swap premature exit, since " + "suricta_ctl_flags != 0 ====="); + + SignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2EngineShutdown); + + pthread_exit(NULL); + } + + if (!(tm->flags & TM_FLAG_DETECT_TM)) { + slots = slots->slot_next; + continue; + } + + no_of_detect_tvs++; + + slots = slots->slot_next; + } + + tv = tv->next; + } + + DetectEngineThreadCtx *old_det_ctx[no_of_detect_tvs]; + DetectEngineThreadCtx *new_det_ctx[no_of_detect_tvs]; + + /* all receive threads are part of packet processing threads */ + tv = tv_root[TVT_PPT]; + int i = 0; + while (tv) { + /* obtain the slots for this TV */ + TmSlot *slots = tv->tm_slots; + while (slots != NULL) { + TmModule *tm = TmModuleGetById(slots->tm_id); + + if (!(tm->flags & TM_FLAG_DETECT_TM)) { + slots = slots->slot_next; + continue; + } + + old_det_ctx[i] = SC_ATOMIC_GET(slots->slot_data); + + DetectEngineThreadCtx *det_ctx = NULL; + DetectEngineThreadCtxInitForLiveRuleSwap(tv, (void *)de_ctx, + (void **)&det_ctx); + SCLogDebug("live rule swap done with new det_ctx - %p and de_ctx " + "- %p\n", det_ctx, de_ctx); + + new_det_ctx[i] = det_ctx; + i++; + + if (suricata_ctl_flags != 0) { + TmThreadsSetFlag(tv_local, THV_CLOSED); + + SCLogInfo("===== Live rule swap premature exit between " + "swapping det_ctxs, since " + "suricta_ctl_flags != 0 ====="); + + SignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2EngineShutdown); + + pthread_exit(NULL); + } + + + SC_ATOMIC_CAS(&slots->slot_data, SC_ATOMIC_GET(slots->slot_data), + det_ctx); + SCLogDebug("swapping new det_ctx with older one"); + + slots = slots->slot_next; + } + + tv = tv->next; + } + + SCMutexUnlock(&tv_root_lock); + + SCLogInfo("Live rule swap has swapped %d old det_ctx's with new ones, " + "along with the new de_ctx", no_of_detect_tvs); + + for (i = 0; i < no_of_detect_tvs; i++) { + while (new_det_ctx[i]->so_far_used_by_detect != 1) { + SCLogDebug("new_det_ctx - %p used by detect", new_det_ctx[i]); + if (suricata_ctl_flags != 0) { + TmThreadsSetFlag(tv_local, THV_CLOSED); + + SCLogInfo("===== Live rule swap done, but premature exit at " + "de-init phase, since suricta_ctl_flags != 0 ====="); + + SignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2EngineShutdown); + + pthread_exit(NULL); + } + + usleep(1000); + } + } + + DetectEngineCtx *old_de_ctx = old_det_ctx[0]->de_ctx; + for (i = 0; i < no_of_detect_tvs; i++) { + SCLogDebug("Freeing old_det_ctx - %p used by detect", + old_det_ctx[i]); + if (suricata_ctl_flags != 0) { + TmThreadsSetFlag(tv_local, THV_CLOSED); + + SCLogInfo("===== Live rule swap done, but premature exit at " + "de-init phase, since suricta_ctl_flags != 0 ====="); + + SignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2EngineShutdown); + + pthread_exit(NULL); + } + + + DetectEngineThreadCtxDeinit(NULL, old_det_ctx[i]); + } + DetectEngineCtxFree(old_de_ctx); + + SignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2); + + TmThreadsSetFlag(tv_local, THV_CLOSED); + + SCLogInfo("===== Live rule swap DONE ====="); + + pthread_exit(NULL); +} + +void DetectEngineSpawnLiveRuleSwapMgmtThread(void) +{ + SCEnter(); + + SCLogDebug("Spawning mgmt thread for live rule swap"); + + ThreadVars *tv = TmThreadCreateMgmtThread("DetectEngineLiveRuleSwap", + DetectEngineLiveRuleSwap, 0); + if (tv == NULL) { + SCLogError(SC_ERR_THREAD_CREATE, "Live rule swap thread spawn failed"); + exit(EXIT_FAILURE); + } + if (TmThreadSpawn(tv) != 0) { + SCLogError(SC_ERR_THREAD_SPAWN, "TmThreadSpawn failed for " + "DetectEngineLiveRuleSwap"); + exit(EXIT_FAILURE); + } + + SCReturn; +} + DetectEngineCtx *DetectEngineCtxInit(void) { DetectEngineCtx *de_ctx; @@ -133,6 +365,8 @@ DetectEngineCtx *DetectEngineCtxInit(void) { goto error; } + de_ctx->id = detect_engine_ctx_id++; + return de_ctx; error: return NULL; @@ -168,6 +402,8 @@ void DetectEngineCtxFree(DetectEngineCtx *de_ctx) { SCClassConfDeInitContext(de_ctx); SCRConfDeInitContext(de_ctx); + SigGroupCleanup(de_ctx); + SCFree(de_ctx); //DetectAddressGroupPrintMemory(); //DetectSigGroupPrintMemory(); @@ -453,7 +689,79 @@ TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data) { /* this detection engine context belongs to this thread instance */ det_ctx->tv = tv; - det_ctx->bj_values = SCMalloc(sizeof(*det_ctx->bj_values) * de_ctx->byte_extract_max_local_id); + det_ctx->bj_values = SCMalloc(sizeof(*det_ctx->bj_values) * + (de_ctx->byte_extract_max_local_id + 1)); + if (det_ctx->bj_values == NULL) { + return TM_ECODE_FAILED; + } + + *data = (void *)det_ctx; + + return TM_ECODE_OK; +} + +static TmEcode DetectEngineThreadCtxInitForLiveRuleSwap(ThreadVars *tv, void *initdata, void **data) +{ + DetectEngineCtx *de_ctx = (DetectEngineCtx *)initdata; + if (de_ctx == NULL) + return TM_ECODE_FAILED; + + DetectEngineThreadCtx *det_ctx = SCMalloc(sizeof(DetectEngineThreadCtx)); + if (det_ctx == NULL) + return TM_ECODE_FAILED; + memset(det_ctx, 0, sizeof(DetectEngineThreadCtx)); + + det_ctx->de_ctx = de_ctx; + + /** \todo we still depend on the global mpm_ctx here + * + * Initialize the thread pattern match ctx with the max size + * of the content and uricontent id's so our match lookup + * table is always big enough + */ + PatternMatchThreadPrepare(&det_ctx->mtc, de_ctx->mpm_matcher, DetectContentMaxId(de_ctx)); + PatternMatchThreadPrepare(&det_ctx->mtcs, de_ctx->mpm_matcher, DetectContentMaxId(de_ctx)); + PatternMatchThreadPrepare(&det_ctx->mtcu, de_ctx->mpm_matcher, DetectUricontentMaxId(de_ctx)); + + //PmqSetup(&det_ctx->pmq, DetectEngineGetMaxSigId(de_ctx), DetectContentMaxId(de_ctx)); + PmqSetup(&det_ctx->pmq, 0, DetectContentMaxId(de_ctx)); + int i; + for (i = 0; i < 256; i++) { + PmqSetup(&det_ctx->smsg_pmq[i], 0, DetectContentMaxId(de_ctx)); + } + + /* IP-ONLY */ + DetectEngineIPOnlyThreadInit(de_ctx,&det_ctx->io_ctx); + + /* DeState */ + if (de_ctx->sig_array_len > 0) { + det_ctx->de_state_sig_array_len = de_ctx->sig_array_len; + det_ctx->de_state_sig_array = SCMalloc(det_ctx->de_state_sig_array_len * sizeof(uint8_t)); + if (det_ctx->de_state_sig_array == NULL) { + return TM_ECODE_FAILED; + } + memset(det_ctx->de_state_sig_array, 0, + det_ctx->de_state_sig_array_len * sizeof(uint8_t)); + + det_ctx->match_array_len = de_ctx->sig_array_len; + det_ctx->match_array = SCMalloc(det_ctx->match_array_len * sizeof(Signature *)); + if (det_ctx->match_array == NULL) { + return TM_ECODE_FAILED; + } + memset(det_ctx->match_array, 0, + det_ctx->match_array_len * sizeof(Signature *)); + } + + /** alert counter setup */ + det_ctx->counter_alerts = SCPerfTVRegisterCounter("detect.alert", tv, + SC_PERF_TYPE_UINT64, "NULL"); + //tv->sc_perf_pca = SCPerfGetAllCountersArray(&tv->sc_perf_pctx); + //SCPerfAddToClubbedTMTable((tv->thread_group_name != NULL) ? tv->thread_group_name : tv->name, &tv->sc_perf_pctx); + + /* this detection engine context belongs to this thread instance */ + det_ctx->tv = tv; + + det_ctx->bj_values = SCMalloc(sizeof(*det_ctx->bj_values) * (de_ctx->byte_extract_max_local_id + 1)); if (det_ctx->bj_values == NULL) { return TM_ECODE_FAILED; } diff --git a/src/detect-engine.h b/src/detect-engine.h index 42c4bb8e09..e04f6a5a6e 100644 --- a/src/detect-engine.h +++ b/src/detect-engine.h @@ -28,6 +28,7 @@ #include "tm-threads.h" /* prototypes */ +void DetectEngineSpawnLiveRuleSwapMgmtThread(void); DetectEngineCtx *DetectEngineCtxInit(void); void DetectEngineCtxFree(DetectEngineCtx *); diff --git a/src/detect.c b/src/detect.c index fbd597a344..e50e2b0cb3 100644 --- a/src/detect.c +++ b/src/detect.c @@ -208,6 +208,7 @@ void TmModuleDetectRegister (void) { tmm_modules[TMM_DETECT].ThreadDeinit = DetectThreadDeinit; tmm_modules[TMM_DETECT].RegisterTests = SigRegisterTests; tmm_modules[TMM_DETECT].cap_flags = 0; + tmm_modules[TMM_DETECT].flags = TM_FLAG_DETECT_TM; PacketAlertTagInit(); } @@ -1338,11 +1339,19 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh if (IP_GET_IPPROTO(p) == p->flow->proto) { /* filter out icmp */ PACKET_PROFILING_DETECT_START(p, PROF_DETECT_GETSGH); if (p->flowflags & FLOW_PKT_TOSERVER && p->flow->flags & FLOW_SGH_TOSERVER) { - det_ctx->sgh = p->flow->sgh_toserver; - sms_runflags |= SMS_USE_FLOW_SGH; + if (p->flow->sgh_toserver_de_ctx_id != de_ctx->id) { + p->flow->flags &= ~FLOW_SGH_TOSERVER; + } else { + det_ctx->sgh = p->flow->sgh_toserver; + sms_runflags |= SMS_USE_FLOW_SGH; + } } else if (p->flowflags & FLOW_PKT_TOCLIENT && p->flow->flags & FLOW_SGH_TOCLIENT) { - det_ctx->sgh = p->flow->sgh_toclient; - sms_runflags |= SMS_USE_FLOW_SGH; + if (p->flow->sgh_toclient_de_ctx_id != de_ctx->id) { + p->flow->flags &= ~FLOW_SGH_TOCLIENT; + } else { + det_ctx->sgh = p->flow->sgh_toclient; + sms_runflags |= SMS_USE_FLOW_SGH; + } } PACKET_PROFILING_DETECT_END(p, PROF_DETECT_GETSGH); @@ -1479,7 +1488,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh memset(det_ctx->de_state_sig_array, 0x00, det_ctx->de_state_sig_array_len); /* if applicable, continue stateful detection */ - int state = DeStateFlowHasState(p->flow, flags, alversion); + int state = DeStateFlowHasState(de_ctx, p->flow, flags, alversion); if (state == 1) { DeStateDetectContinueDetection(th_v, de_ctx, det_ctx, p->flow, flags, alstate, alproto, alversion); @@ -1767,6 +1776,7 @@ end: if (p->flowflags & FLOW_PKT_TOSERVER && !(p->flow->flags & FLOW_SGH_TOSERVER)) { /* first time we see this toserver sgh, store it */ p->flow->sgh_toserver = det_ctx->sgh; + p->flow->sgh_toserver_de_ctx_id = de_ctx->id; p->flow->flags |= FLOW_SGH_TOSERVER; /* see if this sgh requires us to consider file storing */ @@ -1783,6 +1793,7 @@ end: } } else if (p->flowflags & FLOW_PKT_TOCLIENT && !(p->flow->flags & FLOW_SGH_TOCLIENT)) { p->flow->sgh_toclient = det_ctx->sgh; + p->flow->sgh_toclient_de_ctx_id = de_ctx->id; p->flow->flags |= FLOW_SGH_TOCLIENT; if (p->flow->sgh_toclient == NULL || p->flow->sgh_toclient->filestore_cnt == 0) { @@ -1842,6 +1853,12 @@ TmEcode Detect(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQue goto error; } + if (det_ctx->so_far_used_by_detect == 0) { + det_ctx->so_far_used_by_detect = 1; + SCLogDebug("Detect Engine using new det_ctx - %p and de_ctx - %p", + det_ctx, de_ctx); + } + /* see if the packet matches one or more of the sigs */ int r = SigMatchSignatures(tv,de_ctx,det_ctx,p); if (r >= 0) { diff --git a/src/detect.h b/src/detect.h index eb425947c3..53635ecc75 100644 --- a/src/detect.h +++ b/src/detect.h @@ -659,6 +659,9 @@ typedef struct DetectEngineCtx_ { /* the max local id used amongst all sigs */ int32_t byte_extract_max_local_id; + /* id used by every detect engine ctx instance */ + uint32_t id; + /** sgh for signatures that match against invalid packets. In those cases * we can't lookup by proto, address, port as we don't have these */ struct SigGroupHead_ *decoder_event_sgh; @@ -733,6 +736,8 @@ typedef struct DetectionEngineThreadCtx_ { /** ID of the transaction currently being inspected. */ uint16_t tx_id; + uint16_t so_far_used_by_detect; + /* holds the current recursion depth on content inspection */ int inspection_recursion_counter; diff --git a/src/flow-manager.c b/src/flow-manager.c index 0e3dbe2d50..36dd467db4 100644 --- a/src/flow-manager.c +++ b/src/flow-manager.c @@ -371,6 +371,12 @@ next: */ void *FlowManagerThread(void *td) { + /* block usr1. usr1 to be handled by the main thread only */ + sigset_t x; + sigemptyset(&x); + sigaddset(&x, SIGUSR2); + sigprocmask(SIG_BLOCK, &x, NULL); + ThreadVars *th_v = (ThreadVars *)td; struct timeval ts; uint32_t established_cnt = 0, new_cnt = 0, closing_cnt = 0; diff --git a/src/flow.h b/src/flow.h index 45a32edf57..46b4c8101d 100644 --- a/src/flow.h +++ b/src/flow.h @@ -327,9 +327,11 @@ typedef struct Flow_ /** toclient sgh for this flow. Only use when FLOW_SGH_TOCLIENT flow flag * has been set. */ struct SigGroupHead_ *sgh_toclient; + uint32_t sgh_toclient_de_ctx_id; /** toserver sgh for this flow. Only use when FLOW_SGH_TOSERVER flow flag * has been set. */ struct SigGroupHead_ *sgh_toserver; + uint32_t sgh_toserver_de_ctx_id; /** List of tags of this flow (from "tag" keyword of type "session") */ void *tag_list; diff --git a/src/suricata.c b/src/suricata.c index d4e270c333..f29161e36a 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -222,6 +222,8 @@ intmax_t max_pending_packets; /** set caps or not */ int sc_set_caps; +char *conf_filename = NULL; + int RunmodeIsUnittests(void) { if (run_mode == RUNMODE_UNITTEST) return 1; @@ -237,6 +239,41 @@ static void SignalHandlerSigterm(/*@unused@*/ int sig) { sigterm_count = 1; suricata_ctl_flags |= SURICATA_KILL; } + +void SignalHandlerSigusr2EngineShutdown(int sig) +{ + SCLogInfo("Live rule swap no longer possible. Engine in shutdown mode."); + + return; +} + +static void SignalHandlerSigusr2Idle(int sig) +{ + if (run_mode == RUNMODE_UNKNOWN || run_mode == RUNMODE_UNITTEST) { + SCLogInfo("Ruleset load signal USR2 triggered for wrong runmode"); + return; + } + + SCLogInfo("Hang on buddy! Ruleset load in progress. New ruleset load " + "allowed after current is done"); + + return; +} + +void SignalHandlerSigusr2(int sig) +{ + if (run_mode == RUNMODE_UNKNOWN || run_mode == RUNMODE_UNITTEST) { + SCLogInfo("Ruleset load signal USR2 triggered for wrong runmode"); + return; + } + + SignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2Idle); + + DetectEngineSpawnLiveRuleSwapMgmtThread(); + + return; +} + #if 0 static void SignalHandlerSighup(/*@unused@*/ int sig) { sighup_count = 1; @@ -258,8 +295,7 @@ uint8_t print_mem_flag = 1; #endif #endif -static void -SignalHandlerSetup(int sig, void (*handler)()) +void SignalHandlerSetup(int sig, void (*handler)()) { #if defined (OS_WIN32) signal(sig, handler); @@ -630,7 +666,6 @@ int main(int argc, char **argv) char *sig_file = NULL; int sig_file_exclusive = FALSE; int conf_test = 0; - char *conf_filename = NULL; char *pid_filename = NULL; #ifdef UNITTESTS char *regex_arg = NULL; @@ -1435,6 +1470,8 @@ int main(int argc, char **argv) AppLayerHtpNeedFileInspection(); + SignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2Idle); + #ifdef UNITTESTS if (run_mode == RUNMODE_UNITTEST) { @@ -1671,6 +1708,10 @@ int main(int argc, char **argv) exit(EXIT_SUCCESS); } + /* registering singal handlers we use. We register usr2 here, so that one + * can't call it during the first sig load phase */ + SignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2); + #ifdef PROFILING SCProfilingInitRuleCounters(de_ctx); #endif /* PROFILING */ @@ -1838,6 +1879,8 @@ int main(int argc, char **argv) usleep(10* 1000); } + SignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2EngineShutdown); + /* Update the engine stage/status flag */ SC_ATOMIC_CAS(&engine_stage, SURICATA_RUNTIME, SURICATA_DEINIT); @@ -1887,7 +1930,10 @@ int main(int argc, char **argv) } } #endif + /* updated by AS. Don't clean up de_ctx. Necessiated by live rule swap */ +#if 0 SigGroupCleanup(de_ctx); +#endif #ifdef __SC_CUDA_SUPPORT__ if (PatternMatchDefaultMatcher() == MPM_B2G_CUDA) { /* pop the cuda context we just pushed before the call to SigGroupCleanup() */ @@ -1902,11 +1948,17 @@ int main(int argc, char **argv) AppLayerHtpPrintStats(); + /* updated by AS. Don't clean up de_ctx. Necessiated by live rule swap */ +#if 0 SigCleanSignatures(de_ctx); +#endif if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) { MpmFactoryDeRegisterAllMpmCtxProfiles(de_ctx); } + /* updated by AS. Don't clean up de_ctx. Necessiated by live rule swap */ +#if 0 DetectEngineCtxFree(de_ctx); +#endif AlpProtoDestroy(); TagDestroyCtx(); diff --git a/src/suricata.h b/src/suricata.h index 673e863732..c100a6fc47 100644 --- a/src/suricata.h +++ b/src/suricata.h @@ -125,6 +125,8 @@ extern uint8_t suricata_ctl_flags; /* uppercase to lowercase conversion lookup table */ uint8_t g_u8_lowercasetable[256]; +extern char *conf_filename; + /* marco to do the actual lookup */ //#define u8_tolower(c) g_u8_lowercasetable[(c)] // these 2 are slower: @@ -138,6 +140,11 @@ uint8_t g_u8_lowercasetable[256]; void EngineStop(void); void EngineKill(void); +/* live rule swap required this to be made static */ +void SignalHandlerSetup(int, void (*handler)()); +void SignalHandlerSigusr2(int); +void SignalHandlerSigusr2EngineShutdown(int); + int RunmodeIsUnittests(void); #endif /* __SURICATA_H__ */ diff --git a/src/tm-modules.h b/src/tm-modules.h index b547ab3b57..3e35f70862 100644 --- a/src/tm-modules.h +++ b/src/tm-modules.h @@ -30,6 +30,7 @@ /* thread flags */ #define TM_FLAG_RECEIVE_TM 0x01 #define TM_FLAG_DECODE_TM 0x02 +#define TM_FLAG_DETECT_TM 0x04 typedef struct TmModule_ { char *name; diff --git a/src/tm-threads.c b/src/tm-threads.c index fdf65b46ad..3864e88d5d 100644 --- a/src/tm-threads.c +++ b/src/tm-threads.c @@ -121,6 +121,12 @@ void TmThreadsUnsetFlag(ThreadVars *tv, uint8_t flag) /* 1 slot functions */ void *TmThreadsSlot1NoIn(void *td) { + /* block usr2. usr2 to be handled by the main thread only */ + sigset_t x; + sigemptyset(&x); + sigaddset(&x, SIGUSR2); + sigprocmask(SIG_BLOCK, &x, NULL); + ThreadVars *tv = (ThreadVars *)td; TmSlot *s = (TmSlot *)tv->tm_slots; char run = 1; @@ -213,6 +219,12 @@ void *TmThreadsSlot1NoIn(void *td) void *TmThreadsSlot1NoOut(void *td) { + /* block usr2. usr2 to be handled by the main thread only */ + sigset_t x; + sigemptyset(&x); + sigaddset(&x, SIGUSR2); + sigprocmask(SIG_BLOCK, &x, NULL); + ThreadVars *tv = (ThreadVars *)td; TmSlot *s = (TmSlot *)tv->tm_slots; Packet *p = NULL; @@ -288,6 +300,12 @@ void *TmThreadsSlot1NoOut(void *td) void *TmThreadsSlot1NoInOut(void *td) { + /* block usr2. usr2 to be handled by the main thread only */ + sigset_t x; + sigemptyset(&x); + sigaddset(&x, SIGUSR2); + sigprocmask(SIG_BLOCK, &x, NULL); + ThreadVars *tv = (ThreadVars *)td; TmSlot *s = (TmSlot *)tv->tm_slots; char run = 1; @@ -358,6 +376,12 @@ void *TmThreadsSlot1NoInOut(void *td) void *TmThreadsSlot1(void *td) { + /* block usr2. usr2 to be handled by the main thread only */ + sigset_t x; + sigemptyset(&x); + sigaddset(&x, SIGUSR2); + sigprocmask(SIG_BLOCK, &x, NULL); + ThreadVars *tv = (ThreadVars *)td; TmSlot *s = (TmSlot *)tv->tm_slots; Packet *p = NULL; @@ -558,6 +582,12 @@ TmEcode TmThreadsSlotVarRun(ThreadVars *tv, Packet *p, */ void *TmThreadsSlotPktAcqLoop(void *td) { + /* block usr2. usr2 to be handled by the main thread only */ + sigset_t x; + sigemptyset(&x); + sigaddset(&x, SIGUSR2); + sigprocmask(SIG_BLOCK, &x, NULL); + ThreadVars *tv = (ThreadVars *)td; TmSlot *s = tv->tm_slots; char run = 1; @@ -645,6 +675,12 @@ void *TmThreadsSlotPktAcqLoop(void *td) { */ void *TmThreadsSlotVar(void *td) { + /* block usr2. usr2 to be handled by the main thread only */ + sigset_t x; + sigemptyset(&x); + sigaddset(&x, SIGUSR2); + sigprocmask(SIG_BLOCK, &x, NULL); + ThreadVars *tv = (ThreadVars *)td; TmSlot *s = (TmSlot *)tv->tm_slots; Packet *p = NULL;