core: misadressing when writing disk queue files

when writing disk queue files during shutdown, access to freed
memory can occur under these circumstances:

- action A is processing data, but could not complete it
  most importantly, the current in-process batch needs not to
  be totally completed. Most probable cause for this scenario
  is a suspended action in retry mode.
- action A is called from a ruleset RA which
  - does not have a queue assigned
  - where RA is called from a ruleset RO which is bound
    to the input from which the message originated
  - RO must be defined before RA inside the expanded config
- Disk queues (or the disk part of a DA queue) must be utilized
  by A

When re-injecting the unprocessed messages from A into the disk queue, the
name of ruleset RO is accessed (for persisting to disk). However, RO is
already destructed at this point in time.

The patch changes the shutdown processing of rulesets, so that all
shutdown processing is done before any ruleset data is destructed. This
ensures that all data items which potentially need to be accessed
remain valid as long as some part may potentially try to access them.

This follows a the approach used in
   https://github.com/rsyslog/rsyslog/pull/1857
where obviously that part of the problem was not noticed.

see also https://github.com/rsyslog/rsyslog/issues/1122
closes https://github.com/rsyslog/rsyslog/issues/2742
This commit is contained in:
Rainer Gerhards 2018-06-05 09:08:42 +02:00
parent 428fa434b1
commit f4d6a593bb
No known key found for this signature in database
GPG Key ID: 0CB6B2A8BE80B499

View File

@ -832,7 +832,6 @@ CODESTARTobjDestruct(ruleset)
parser.DestructParserList(&pThis->pParserLst);
}
free(pThis->pszName);
cnfstmtDestructLst(pThis->root);
ENDobjDestruct(ruleset)
@ -849,6 +848,17 @@ DEFFUNC_llExecFunc(doShutdownQueueWorkers)
}
RETiRet;
}
/* helper for Destructor, shut down actions (cnfstmt's in general) */
DEFFUNC_llExecFunc(doDestructCnfStmt)
{
DEFiRet;
ruleset_t *const pThis = (ruleset_t*) pData;
DBGPRINTF("shutting down actions and conf stmts for ruleset %p, name %s\n",
pThis, pThis->pszName);
ISOBJ_TYPE_assert(pThis, ruleset);
cnfstmtDestructLst(pThis->root);
RETiRet;
}
/* destruct ALL rule sets that reside in the system. This must
* be callable before unloading this module as the module may
* not be unloaded before unload of the actions is required. This is
@ -860,17 +870,20 @@ destructAllActions(rsconf_t *conf)
{
DEFiRet;
DBGPRINTF("rulesetDestructAllActions\n");
DBGPRINTF("rulesetDestructAllActions\n");
/* we first need to stop all queue workers, else we
* may run into trouble with "call" statements calling
* into then-destroyed rulesets.
* see: https://github.com/rsyslog/rsyslog/issues/1122
*/
DBGPRINTF("RRRRRR: rsconfDestruct - queue shutdown\n");
DBGPRINTF("destructAllActions: queue shutdown\n");
llExecFunc(&(conf->rulesets.llRulesets), doShutdownQueueWorkers, NULL);
DBGPRINTF("destructAllActions: action and conf stmt shutdown\n");
llExecFunc(&(conf->rulesets.llRulesets), doDestructCnfStmt, NULL);
CHKiRet(llDestroy(&(conf->rulesets.llRulesets)));
CHKiRet(llInit(&(conf->rulesets.llRulesets), rulesetDestructForLinkedList, rulesetKeyDestruct, strcasecmp));
CHKiRet(llInit(&(conf->rulesets.llRulesets), rulesetDestructForLinkedList,
rulesetKeyDestruct, strcasecmp));
conf->rulesets.pDflt = NULL;
finalize_it:
@ -1166,6 +1179,3 @@ BEGINObjClassInit(ruleset, 1, OBJ_IS_CORE_MODULE) /* class, version */
CHKiRet(regCfSysLineHdlr((uchar *)"rulesetcreatemainqueue", 0, eCmdHdlrBinary, rulesetCreateQueue,
NULL, NULL));
ENDObjClassInit(ruleset)
/* vi:set ai:
*/