core/ratelimit bugfix: race can lead to segfault

There was a race in iminternalAddMsg(), where the mutex is
released and after that the passed message object is accessed.
If the mainloop iterates in between, the msg may have already
been deleted by this time, resulting in a segfault.

Most importantly, there is no need to release the mutex lock
early, as suggested by current code. Inside mainloop the mutex
is acquired when it is time to do so, so at worst we'll have a
very slight wait there (which really does not matter at all).

This only happens if a large number of internal messages are emitted.

closes https://github.com/rsyslog/rsyslog/issues/1828
This commit is contained in:
Rainer Gerhards 2017-10-10 16:38:53 +02:00
parent 6d064cd507
commit ba5784b635

View File

@ -99,11 +99,11 @@ rsRetVal iminternalAddMsg(smsg_t *pMsg)
*/
to.tv_sec = time(NULL) + 1;
to.tv_nsec = 0;
#if !defined(__APPLE__)
r = pthread_mutex_timedlock(&mutList, &to);
#else
r = pthread_mutex_trylock(&mutList); // must check
#endif
#if !defined(__APPLE__)
r = pthread_mutex_timedlock(&mutList, &to);
#else
r = pthread_mutex_trylock(&mutList); // must check
#endif
is_locked = 1;
if(r != 0) {
dbgprintf("iminternalAddMsg: timedlock for mutex failed with %d, msg %s\n",
@ -116,9 +116,6 @@ rsRetVal iminternalAddMsg(smsg_t *pMsg)
pThis->pMsg = pMsg;
CHKiRet(llAppend(&llMsgs, NULL, (void*) pThis));
/* awake mainloop to emit message ASAP */
pthread_mutex_unlock(&mutList);
is_locked = 0;
if(bHaveMainQueue) {
DBGPRINTF("signaling new internal message via SIGTTOU: '%s'\n",
pThis->pMsg->pszRawMsg);