|
|
|
@ -647,325 +647,6 @@ static int DetectEngineReloadThreads(DetectEngineCtx *new_de_ctx)
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void *DetectEngineLiveRuleSwap(void *arg)
|
|
|
|
|
{
|
|
|
|
|
SCEnter();
|
|
|
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
|
int no_of_detect_tvs = 0;
|
|
|
|
|
DetectEngineCtx *old_de_ctx = NULL;
|
|
|
|
|
ThreadVars *tv = NULL;
|
|
|
|
|
|
|
|
|
|
if (SCSetThreadName("LiveRuleSwap") < 0) {
|
|
|
|
|
SCLogWarning(SC_ERR_THREAD_INIT, "Unable to set thread name");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SCLogNotice("rule reload starting");
|
|
|
|
|
|
|
|
|
|
ThreadVars *tv_local = (ThreadVars *)arg;
|
|
|
|
|
|
|
|
|
|
/* block usr2. usr2 to be handled by the main thread only */
|
|
|
|
|
UtilSignalBlock(SIGUSR2);
|
|
|
|
|
|
|
|
|
|
if (tv_local->thread_setup_flags != 0)
|
|
|
|
|
TmThreadSetupOptions(tv_local);
|
|
|
|
|
|
|
|
|
|
/* release TmThreadSpawn */
|
|
|
|
|
TmThreadsSetFlag(tv_local, THV_INIT_DONE);
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
SCMutexLock(&tv_root_lock);
|
|
|
|
|
|
|
|
|
|
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("rule reload interupted by engine shutdown");
|
|
|
|
|
|
|
|
|
|
UtilSignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2);
|
|
|
|
|
SCMutexUnlock(&tv_root_lock);
|
|
|
|
|
pthread_exit(NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!(tm->flags & TM_FLAG_DETECT_TM)) {
|
|
|
|
|
slots = slots->slot_next;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
no_of_detect_tvs++;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tv = tv->next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (no_of_detect_tvs == 0) {
|
|
|
|
|
TmThreadsSetFlag(tv_local, THV_CLOSED);
|
|
|
|
|
UtilSignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2);
|
|
|
|
|
SCLogInfo("===== Live rule swap FAILURE =====");
|
|
|
|
|
pthread_exit(NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DetectEngineThreadCtx *old_det_ctx[no_of_detect_tvs];
|
|
|
|
|
DetectEngineThreadCtx *new_det_ctx[no_of_detect_tvs];
|
|
|
|
|
ThreadVars *detect_tvs[no_of_detect_tvs];
|
|
|
|
|
memset(old_det_ctx, 0x00, (no_of_detect_tvs * sizeof(DetectEngineThreadCtx *)));
|
|
|
|
|
memset(new_det_ctx, 0x00, (no_of_detect_tvs * sizeof(DetectEngineThreadCtx *)));
|
|
|
|
|
memset(detect_tvs, 0x00, (no_of_detect_tvs * sizeof(ThreadVars *)));
|
|
|
|
|
|
|
|
|
|
SCMutexUnlock(&tv_root_lock);
|
|
|
|
|
|
|
|
|
|
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
|
|
|
|
if (de_ctx == NULL) {
|
|
|
|
|
SCLogError(SC_ERR_LIVE_RULE_SWAP, "Allocation failure in live "
|
|
|
|
|
"swap. Let's get out of here.");
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (SigLoadSignatures(de_ctx, NULL, FALSE) < 0) {
|
|
|
|
|
SCLogError(SC_ERR_NO_RULES_LOADED, "Loading signatures failed.");
|
|
|
|
|
if (de_ctx->failure_fatal)
|
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
|
|
|
SCLogError(SC_ERR_LIVE_RULE_SWAP, "Failure encountered while "
|
|
|
|
|
"loading new ruleset with live swap.");
|
|
|
|
|
SCLogError(SC_ERR_LIVE_RULE_SWAP, "rule reload failed");
|
|
|
|
|
TmThreadsSetFlag(tv_local, THV_CLOSED);
|
|
|
|
|
UtilSignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2);
|
|
|
|
|
pthread_exit(NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SCThresholdConfInitContext(de_ctx, NULL);
|
|
|
|
|
|
|
|
|
|
/* start the process of swapping detect threads ctxs */
|
|
|
|
|
|
|
|
|
|
SCMutexLock(&tv_root_lock);
|
|
|
|
|
|
|
|
|
|
/* all receive threads are part of packet processing threads */
|
|
|
|
|
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("rule reload interupted by engine shutdown");
|
|
|
|
|
|
|
|
|
|
UtilSignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2);
|
|
|
|
|
SCMutexUnlock(&tv_root_lock);
|
|
|
|
|
pthread_exit(NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!(tm->flags & TM_FLAG_DETECT_TM)) {
|
|
|
|
|
slots = slots->slot_next;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
old_det_ctx[i] = SC_ATOMIC_GET(slots->slot_data);
|
|
|
|
|
detect_tvs[i] = tv;
|
|
|
|
|
TmEcode r = DetectEngineThreadCtxInitForLiveRuleSwap(tv, (void *)de_ctx,
|
|
|
|
|
(void **)&new_det_ctx[i]);
|
|
|
|
|
i++;
|
|
|
|
|
if (r == TM_ECODE_FAILED) {
|
|
|
|
|
SCLogError(SC_ERR_LIVE_RULE_SWAP, "Detect engine thread init "
|
|
|
|
|
"failure in live rule swap. Let's get out of here");
|
|
|
|
|
SCMutexUnlock(&tv_root_lock);
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
SCLogDebug("live rule swap created new det_ctx - %p and de_ctx "
|
|
|
|
|
"- %p\n", new_det_ctx, de_ctx);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tv = tv->next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
tv = tv_root[TVT_PPT];
|
|
|
|
|
while (tv) {
|
|
|
|
|
TmSlot *slots = tv->tm_slots;
|
|
|
|
|
while (slots != NULL) {
|
|
|
|
|
if (suricata_ctl_flags != 0) {
|
|
|
|
|
TmThreadsSetFlag(tv_local, THV_CLOSED);
|
|
|
|
|
|
|
|
|
|
SCLogInfo("rule reload interupted by engine shutdown");
|
|
|
|
|
|
|
|
|
|
UtilSignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2);
|
|
|
|
|
SCMutexUnlock(&tv_root_lock);
|
|
|
|
|
pthread_exit(NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TmModule *tm = TmModuleGetById(slots->tm_id);
|
|
|
|
|
if (!(tm->flags & TM_FLAG_DETECT_TM)) {
|
|
|
|
|
slots = slots->slot_next;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
SCLogDebug("swapping new det_ctx - %p with older one - %p",
|
|
|
|
|
new_det_ctx[i], SC_ATOMIC_GET(slots->slot_data));
|
|
|
|
|
(void)SC_ATOMIC_SET(slots->slot_data, new_det_ctx[i++]);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
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++) {
|
|
|
|
|
int break_out = 0;
|
|
|
|
|
int pseudo_pkt_inserted = 0;
|
|
|
|
|
usleep(1000);
|
|
|
|
|
while (SC_ATOMIC_GET(new_det_ctx[i]->so_far_used_by_detect) != 1) {
|
|
|
|
|
if (suricata_ctl_flags != 0) {
|
|
|
|
|
break_out = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pseudo_pkt_inserted == 0) {
|
|
|
|
|
pseudo_pkt_inserted = 1;
|
|
|
|
|
if (detect_tvs[i]->inq != NULL) {
|
|
|
|
|
Packet *p = PacketGetFromAlloc();
|
|
|
|
|
if (p != NULL) {
|
|
|
|
|
p->flags |= PKT_PSEUDO_STREAM_END;
|
|
|
|
|
PacketQueue *q = &trans_q[detect_tvs[i]->inq->id];
|
|
|
|
|
SCMutexLock(&q->mutex_q);
|
|
|
|
|
|
|
|
|
|
PacketEnqueue(q, p);
|
|
|
|
|
SCCondSignal(&q->cond_q);
|
|
|
|
|
SCMutexUnlock(&q->mutex_q);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
usleep(1000);
|
|
|
|
|
}
|
|
|
|
|
if (break_out)
|
|
|
|
|
break;
|
|
|
|
|
SCLogDebug("new_det_ctx - %p used by detect engine", new_det_ctx[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* this is to make sure that if someone initiated shutdown during a live
|
|
|
|
|
* rule swap, the live rule swap won't clean up the old det_ctx and
|
|
|
|
|
* de_ctx, till all detect threads have stopped working and sitting
|
|
|
|
|
* silently after setting RUNNING_DONE flag and while waiting for
|
|
|
|
|
* THV_DEINIT flag */
|
|
|
|
|
if (i != no_of_detect_tvs) {
|
|
|
|
|
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 (!(tm->flags & TM_FLAG_DETECT_TM)) {
|
|
|
|
|
slots = slots->slot_next;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (!TmThreadsCheckFlag(tv, THV_RUNNING_DONE)) {
|
|
|
|
|
usleep(100);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
slots = slots->slot_next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tv = tv->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* free all the ctxs */
|
|
|
|
|
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]);
|
|
|
|
|
DetectEngineThreadCtxDeinit(NULL, old_det_ctx[i]);
|
|
|
|
|
}
|
|
|
|
|
DetectEngineCtxFree(old_de_ctx);
|
|
|
|
|
|
|
|
|
|
SRepReloadComplete();
|
|
|
|
|
|
|
|
|
|
/* reset the handler */
|
|
|
|
|
UtilSignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2);
|
|
|
|
|
|
|
|
|
|
TmThreadsSetFlag(tv_local, THV_CLOSED);
|
|
|
|
|
|
|
|
|
|
SCLogNotice("rule reload complete");
|
|
|
|
|
|
|
|
|
|
pthread_exit(NULL);
|
|
|
|
|
|
|
|
|
|
error:
|
|
|
|
|
for (i = 0; i < no_of_detect_tvs; i++) {
|
|
|
|
|
if (new_det_ctx[i] != NULL)
|
|
|
|
|
DetectEngineThreadCtxDeinit(NULL, new_det_ctx[i]);
|
|
|
|
|
}
|
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
|
|
|
TmThreadsSetFlag(tv_local, THV_CLOSED);
|
|
|
|
|
UtilSignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2);
|
|
|
|
|
SCLogInfo("===== Live rule swap FAILURE =====");
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TmThreadSetCPU(tv, MANAGEMENT_CPU_SET);
|
|
|
|
|
|
|
|
|
|
if (TmThreadSpawn(tv) != 0) {
|
|
|
|
|
SCLogError(SC_ERR_THREAD_SPAWN, "TmThreadSpawn failed for "
|
|
|
|
|
"DetectEngineLiveRuleSwap");
|
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SCReturn;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static DetectEngineCtx *DetectEngineCtxInitReal(int minimal)
|
|
|
|
|
{
|
|
|
|
|
DetectEngineCtx *de_ctx;
|
|
|
|
|