From e4dc83db31f7f23f68c11a586790abb5434b8171 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 17 Sep 2009 16:46:53 +0200 Subject: preparing for 4.5.3 --- ChangeLog | 2 +- configure.ac | 2 +- doc/manual.html | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index e29e96dc..33c1d9f5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,5 @@ --------------------------------------------------------------------------- -Version 4.5.3 [v4-beta] (rgerhards), 2009-08-?? +Version 4.5.3 [v4-beta] (rgerhards), 2009-09-17 - bugfix: repeated messages were incorrectly processed this could lead to loss of the repeated message content. As a side- effect, it could probably also be possible that some segfault occurs diff --git a/configure.ac b/configure.ac index 9a263128..1fd62ae0 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.61) -AC_INIT([rsyslog],[4.5.2],[rsyslog@lists.adiscon.com]) +AC_INIT([rsyslog],[4.5.3],[rsyslog@lists.adiscon.com]) AM_INIT_AUTOMAKE AC_CONFIG_SRCDIR([ChangeLog]) AC_CONFIG_MACRO_DIR([m4]) diff --git a/doc/manual.html b/doc/manual.html index e1f7480e..d7ed5e98 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -19,7 +19,7 @@ rsyslog support available directly from the source!

Please visit the rsyslog sponsor's page to honor the project sponsors or become one yourself! We are very grateful for any help towards the project goals.

-

This documentation is for version 4.5.2 (v4-beta branch) of rsyslog. +

This documentation is for version 4.5.3 (v4-beta branch) of rsyslog. Visit the rsyslog status page to obtain current version information and project status.

If you like rsyslog, you might -- cgit From 6946b6b7d9c53979826764f66166b501e783cb2a Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 22 Sep 2009 12:48:51 +0200 Subject: bugfix: potential race in object loader during use/release of object interface --- ChangeLog | 4 ++++ runtime/obj.c | 22 +++++++++++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 33c1d9f5..7258310b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,8 @@ --------------------------------------------------------------------------- +Version 4.5.4 [v4-beta] (rgerhards), 2009-09-?? +- bugfix: potential race in object loader (obj.c) during use/release + of object interface +--------------------------------------------------------------------------- Version 4.5.3 [v4-beta] (rgerhards), 2009-09-17 - bugfix: repeated messages were incorrectly processed this could lead to loss of the repeated message content. As a side- diff --git a/runtime/obj.c b/runtime/obj.c index 6ca05cc4..aebea332 100644 --- a/runtime/obj.c +++ b/runtime/obj.c @@ -75,6 +75,7 @@ #include #include #include +#include /* how many objects are supported by rsyslogd? */ #define OBJ_NUM_IDS 100 /* TODO change to a linked list? info: 16 were currently in use 2008-02-29 */ @@ -97,6 +98,7 @@ DEFobjCurrIf(module) DEFobjCurrIf(errmsg) DEFobjCurrIf(strm) static objInfo_t *arrObjInfo[OBJ_NUM_IDS]; /* array with object information pointers */ +static pthread_mutex_t mutObjGlobalOp; /* mutex to guard global operations of the object system */ /* cookies for serialized lines */ @@ -1127,6 +1129,7 @@ UseObj(char *srcFile, uchar *pObjName, uchar *pObjFile, interface_t *pIf) /* DEV debug only: dbgprintf("source file %s requests object '%s', ifIsLoaded %d\n", srcFile, pObjName, pIf->ifIsLoaded); */ + d_pthread_mutex_lock(&mutObjGlobalOp); if(pIf->ifIsLoaded == 1) { ABORT_FINALIZE(RS_RET_OK); /* we are already set */ @@ -1167,6 +1170,8 @@ UseObj(char *srcFile, uchar *pObjName, uchar *pObjFile, interface_t *pIf) pIf->ifIsLoaded = 1; /* we are happy */ finalize_it: + d_pthread_mutex_unlock(&mutObjGlobalOp); + if(pStr != NULL) rsCStrDestruct(&pStr); @@ -1188,15 +1193,16 @@ ReleaseObj(char *srcFile, uchar *pObjName, uchar *pObjFile, interface_t *pIf) /* dev debug only dbgprintf("source file %s releasing object '%s', ifIsLoaded %d\n", srcFile, pObjName, pIf->ifIsLoaded); */ + d_pthread_mutex_lock(&mutObjGlobalOp); if(pObjFile == NULL) FINALIZE; /* if it is not a lodable module, we do not need to do anything... */ if(pIf->ifIsLoaded == 0) { - ABORT_FINALIZE(RS_RET_OK); /* we are not loaded - this is perfectly OK... */ + FINALIZE; /* we are not loaded - this is perfectly OK... */ } else if(pIf->ifIsLoaded == 2) { pIf->ifIsLoaded = 0; /* clean up */ - ABORT_FINALIZE(RS_RET_OK); /* we had a load error and can not continue */ + FINALIZE; /* we had a load error and can not/must not continue */ } CHKiRet(rsCStrConstructFromszStr(&pStr, pObjName)); @@ -1208,6 +1214,8 @@ ReleaseObj(char *srcFile, uchar *pObjName, uchar *pObjFile, interface_t *pIf) pIf->ifIsLoaded = 0; /* indicated "no longer valid" */ finalize_it: + d_pthread_mutex_unlock(&mutObjGlobalOp); + if(pStr != NULL) rsCStrDestruct(&pStr); @@ -1300,8 +1308,9 @@ objClassExit(void) rsRetVal objClassInit(modInfo_t *pModInfo) { - DEFiRet; + pthread_mutexattr_t mutAttr; int i; + DEFiRet; /* first, initialize the object system itself. This must be done * before any other object is created. @@ -1310,6 +1319,13 @@ objClassInit(modInfo_t *pModInfo) arrObjInfo[i] = NULL; } + /* the mutex must be recursive, because objects may call into other + * object identifieres recursively. + */ + pthread_mutexattr_init(&mutAttr); + pthread_mutexattr_settype(&mutAttr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&mutObjGlobalOp, &mutAttr); + /* request objects we use */ CHKiRet(objGetObjInterface(&obj)); /* get ourselves ;) */ -- cgit From 22c32ca5b6e25f40a3731733b3525ced07e1941a Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 22 Sep 2009 12:49:48 +0200 Subject: bumped version number --- configure.ac | 2 +- doc/manual.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 1fd62ae0..eba3d76f 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.61) -AC_INIT([rsyslog],[4.5.3],[rsyslog@lists.adiscon.com]) +AC_INIT([rsyslog],[4.5.4],[rsyslog@lists.adiscon.com]) AM_INIT_AUTOMAKE AC_CONFIG_SRCDIR([ChangeLog]) AC_CONFIG_MACRO_DIR([m4]) diff --git a/doc/manual.html b/doc/manual.html index d7ed5e98..ed0048bb 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -19,7 +19,7 @@ rsyslog support available directly from the source!

Please visit the rsyslog sponsor's page to honor the project sponsors or become one yourself! We are very grateful for any help towards the project goals.

-

This documentation is for version 4.5.3 (v4-beta branch) of rsyslog. +

This documentation is for version 4.5.4 (v4-beta branch) of rsyslog. Visit the rsyslog status page to obtain current version information and project status.

If you like rsyslog, you might -- cgit From 4cc2db490a27e4da95f821bcf5eef5c3b281fe17 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 22 Sep 2009 14:07:25 +0200 Subject: bugfixes: potential problems in out file zip writer. Problems could lead to abort and/or memory leak. The module is now hardened in a very conservative way, which is sub-optimal from a performance point of view. This should be improved if it has proven reliable in practice. --- ChangeLog | 4 ++++ runtime/stream.c | 45 +++++++++++++++++++++++++++++++-------------- 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7258310b..a12f258e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,10 @@ Version 4.5.4 [v4-beta] (rgerhards), 2009-09-?? - bugfix: potential race in object loader (obj.c) during use/release of object interface +- bugfixes: potential problems in out file zip writer. Problems could + lead to abort and/or memory leak. The module is now hardened in a very + conservative way, which is sub-optimal from a performance point of view. + This should be improved if it has proven reliable in practice. --------------------------------------------------------------------------- Version 4.5.3 [v4-beta] (rgerhards), 2009-09-17 - bugfix: repeated messages were incorrectly processed diff --git a/runtime/stream.c b/runtime/stream.c index 8098f778..e8d4a2a0 100644 --- a/runtime/stream.c +++ b/runtime/stream.c @@ -7,6 +7,14 @@ * * File begun on 2008-01-09 by RGerhards * Large modifications in 2009-06 to support using it with omfile, including zip writer. + * Note that this file obtains the zlib wrapper object is needed, but it never frees it + * again. While this sounds like a leak (and one may argue it actually is), there is no + * harm associated with that. The reason is that strm is a core object, so it is terminated + * only when rsyslogd exists. As we could only release on termination (or else bear more + * overhead for keeping track of how many users we have), not releasing zlibw is OK, because + * it will be released when rsyslogd terminates. We may want to revisit this decision if + * it turns out to be problematic. Then, we need to quasi-refcount the number of accesses + * to the object. * * Copyright 2008, 2009 Rainer Gerhards and Adiscon GmbH. * @@ -598,7 +606,7 @@ static rsRetVal strmConstructFinalize(strm_t *pThis) "without zip\n", localRet); } else { /* we use the same size as the original buf, as we would like - * to make sure we can write out everyting with a SINGLE api call! + * to make sure we can write out everything with a SINGLE api call! */ CHKmalloc(pThis->pZipBuf = (Bytef*) malloc(sizeof(uchar) * pThis->sIOBufSize)); } @@ -676,10 +684,6 @@ dbgprintf("XXX: destruct stream %p\n", pThis); if(pThis->fd != -1) strmCloseFile(pThis); - if(pThis->iZipLevel) { /* do we need a zip buf? */ - objRelease(zlibw, LM_ZLIBW_FILENAME); - } - free(pThis->pszDir); free(pThis->pZipBuf); free(pThis->pszCurrFName); @@ -1044,32 +1048,41 @@ finalize_it: * add a config switch so that the user can decide the risk he is ready * to take, but so far this is not yet implemented (not even requested ;)). * rgerhards, 2009-06-04 + * For the time being, we take a very conservative approach and do not run this + * method multithreaded. This is done in an effort to solve a segfault condition + * that seems to be related to the zip code. -- rgerhards, 2009-09-22 + * TODO: make multithreaded again! */ static rsRetVal doZipWrite(strm_t *pThis, uchar *pBuf, size_t lenBuf) { z_stream zstrm; int zRet; /* zlib return state */ + bool bzInitDone = FALSE; + static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; DEFiRet; assert(pThis != NULL); assert(pBuf != NULL); + pthread_mutex_lock(&mut); + /* allocate deflate state */ zstrm.zalloc = Z_NULL; zstrm.zfree = Z_NULL; zstrm.opaque = Z_NULL; + zstrm.next_in = (Bytef*) pBuf; /* as of zlib doc, this must be set BEFORE DeflateInit2 */ /* see note in file header for the params we use with deflateInit2() */ zRet = zlibw.DeflateInit2(&zstrm, pThis->iZipLevel, Z_DEFLATED, 31, 9, Z_DEFAULT_STRATEGY); if(zRet != Z_OK) { DBGPRINTF("error %d returned from zlib/deflateInit2()\n", zRet); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } + bzInitDone = TRUE; /* now doing the compression */ + zstrm.next_in = (Bytef*) pBuf; /* as of zlib doc, this must be set BEFORE DeflateInit2 */ zstrm.avail_in = lenBuf; - zstrm.next_in = (Bytef*) pBuf; - /* run deflate() on input until output buffer not full, finish - compression if all of source has been read in */ + /* run deflate() on buffer until everything has been compressed */ do { DBGPRINTF("in deflate() loop, avail_in %d, total_in %ld\n", zstrm.avail_in, zstrm.total_in); zstrm.avail_out = pThis->sIOBufSize; @@ -1077,18 +1090,22 @@ doZipWrite(strm_t *pThis, uchar *pBuf, size_t lenBuf) zRet = zlibw.Deflate(&zstrm, Z_FINISH); /* no bad return value */ DBGPRINTF("after deflate, ret %d, avail_out %d\n", zRet, zstrm.avail_out); assert(zRet != Z_STREAM_ERROR); /* state not clobbered */ + if(zstrm.avail_out == pThis->sIOBufSize) + break; /* this is valid, indicates end of compression --> see zlib howto */ CHKiRet(strmPhysWrite(pThis, (uchar*)pThis->pZipBuf, pThis->sIOBufSize - zstrm.avail_out)); } while (zstrm.avail_out == 0); assert(zstrm.avail_in == 0); /* all input will be used */ - - zRet = zlibw.DeflateEnd(&zstrm); - if(zRet != Z_OK) { - DBGPRINTF("error %d returned from zlib/deflateEnd()\n", zRet); - ABORT_FINALIZE(RS_RET_ZLIB_ERR); +finalize_it: + if(bzInitDone) { + zRet = zlibw.DeflateEnd(&zstrm); + if(zRet != Z_OK) { + DBGPRINTF("error %d returned from zlib/deflateEnd()\n", zRet); + } } -finalize_it: + pthread_mutex_unlock(&mut); + RETiRet; } -- cgit From 44844b8af3be216cec340c8ff83fdc6f1d6f1fff Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 22 Sep 2009 14:22:34 +0200 Subject: minor: increased buffer size to be safe in all cases if the buffer was too small, we would see more API calls, but no failure, so this is no fix! --- runtime/stream.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/stream.c b/runtime/stream.c index e8d4a2a0..32467082 100644 --- a/runtime/stream.c +++ b/runtime/stream.c @@ -607,8 +607,9 @@ static rsRetVal strmConstructFinalize(strm_t *pThis) } else { /* we use the same size as the original buf, as we would like * to make sure we can write out everything with a SINGLE api call! + * We add another 128 bytes to take care of the gzip header and "all eventualities". */ - CHKmalloc(pThis->pZipBuf = (Bytef*) malloc(sizeof(uchar) * pThis->sIOBufSize)); + CHKmalloc(pThis->pZipBuf = (Bytef*) malloc(sizeof(uchar) * pThis->sIOBufSize + 128)); } } @@ -854,7 +855,6 @@ dbgprintf("XXX: doAsyncWriteInternal: strm %p, len %ld\n", pThis, (long) lenBuf) if(++pThis->iCnt == 1) pthread_cond_signal(&pThis->notEmpty); -finalize_it: RETiRet; } -- cgit From 37ba1df6e37b2d020001f390ccb2462ae04fc9c1 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 24 Sep 2009 09:48:38 +0200 Subject: bugfix: random data could be appended to message, possibly causing segfaults --- ChangeLog | 2 + runtime/datetime.c | 114 ++++++++++++++++++++++++++++++++++++----------------- runtime/datetime.h | 4 +- runtime/parser.c | 11 ++++-- runtime/rsyslog.h | 1 + tools/syslogd.c | 108 ++++++++++++++++++++++++++++++++------------------ 6 files changed, 160 insertions(+), 80 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0c127d1b..6272aee2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ --------------------------------------------------------------------------- Version 4.4.2 [v4-stable] (rgerhards), 2009-09-?? +- bugfix: random data could be appended to message, possibly causing + segfaults - bugfix: reverse lookup reduction logic in imudp do DNS queries too often A comparison was done between the current and the former source address. However, this was done on the full sockaddr_storage structure and not diff --git a/runtime/datetime.c b/runtime/datetime.c index 40ab4e9c..fc56b27c 100644 --- a/runtime/datetime.c +++ b/runtime/datetime.c @@ -140,6 +140,7 @@ static void getCurrTime(struct syslogTime *t, time_t *ttSeconds) * DO NOT PUT ANY OTHER CODE IN THIS BEGIN ... END BLOCK!!!! */ + /** * Parse a 32 bit integer number from a string. * @@ -147,17 +148,21 @@ static void getCurrTime(struct syslogTime *t, time_t *ttSeconds) * must be positioned at the first digit. Will be updated * so that on return it points to the first character AFTER * the integer parsed. + * \param pLenStr pointer to string length, decremented on exit by + * characters processed + * Note that if an empty string (len < 1) is passed in, + * the method always returns zero. * \retval The number parsed. */ - -static int srSLMGParseInt32(uchar** ppsz) +static int srSLMGParseInt32(uchar** ppsz, int *pLenStr) { register int i; i = 0; - while(isdigit((int) **ppsz)) { + while(*pLenStr > 0 && isdigit((int) **ppsz)) { i = i * 10 + **ppsz - '0'; ++(*ppsz); + --(*pLenStr); } return i; @@ -169,9 +174,13 @@ static int srSLMGParseInt32(uchar** ppsz) * updates the parse pointer position. The pTime parameter * is guranteed to be updated only if a new valid timestamp * could be obtained (restriction added 2008-09-16 by rgerhards). + * This method now also checks the maximum string length it is passed. + * If a *valid* timestamp is found, the string length is decremented + * by the number of characters processed. If it is not a valid timestamp, + * the length is kept unmodified. -- rgerhards, 2009-09-23 */ static rsRetVal -ParseTIMESTAMP3339(struct syslogTime *pTime, uchar** ppszTS) +ParseTIMESTAMP3339(struct syslogTime *pTime, uchar** ppszTS, int *pLenStr) { uchar *pszTS = *ppszTS; /* variables to temporarily hold time information while we parse */ @@ -186,6 +195,7 @@ ParseTIMESTAMP3339(struct syslogTime *pTime, uchar** ppszTS) char OffsetMode; /* UTC offset + or - */ char OffsetHour; /* UTC offset in hours */ int OffsetMinute; /* UTC offset in minutes */ + int lenStr; /* end variables to temporarily hold time information while we parse */ DEFiRet; @@ -193,48 +203,50 @@ ParseTIMESTAMP3339(struct syslogTime *pTime, uchar** ppszTS) assert(ppszTS != NULL); assert(pszTS != NULL); - year = srSLMGParseInt32(&pszTS); + lenStr = *pLenStr; + year = srSLMGParseInt32(&pszTS, &lenStr); /* We take the liberty to accept slightly malformed timestamps e.g. in * the format of 2003-9-1T1:0:0. This doesn't hurt on receiving. Of course, * with the current state of affairs, we would never run into this code * here because at postion 11, there is no "T" in such cases ;) */ - if(*pszTS++ != '-') + if(lenStr == 0 || *pszTS++ != '-') ABORT_FINALIZE(RS_RET_INVLD_TIME); - month = srSLMGParseInt32(&pszTS); + month = srSLMGParseInt32(&pszTS, &lenStr); if(month < 1 || month > 12) ABORT_FINALIZE(RS_RET_INVLD_TIME); - if(*pszTS++ != '-') + if(lenStr == 0 || *pszTS++ != '-') ABORT_FINALIZE(RS_RET_INVLD_TIME); - day = srSLMGParseInt32(&pszTS); + day = srSLMGParseInt32(&pszTS, &lenStr); if(day < 1 || day > 31) ABORT_FINALIZE(RS_RET_INVLD_TIME); - if(*pszTS++ != 'T') + if(lenStr == 0 || *pszTS++ != 'T') ABORT_FINALIZE(RS_RET_INVLD_TIME); - hour = srSLMGParseInt32(&pszTS); + hour = srSLMGParseInt32(&pszTS, &lenStr); if(hour < 0 || hour > 23) ABORT_FINALIZE(RS_RET_INVLD_TIME); - if(*pszTS++ != ':') + if(lenStr == 0 || *pszTS++ != ':') ABORT_FINALIZE(RS_RET_INVLD_TIME); - minute = srSLMGParseInt32(&pszTS); + minute = srSLMGParseInt32(&pszTS, &lenStr); if(minute < 0 || minute > 59) ABORT_FINALIZE(RS_RET_INVLD_TIME); - if(*pszTS++ != ':') + if(lenStr == 0 || *pszTS++ != ':') ABORT_FINALIZE(RS_RET_INVLD_TIME); - second = srSLMGParseInt32(&pszTS); + second = srSLMGParseInt32(&pszTS, &lenStr); if(second < 0 || second > 60) ABORT_FINALIZE(RS_RET_INVLD_TIME); /* Now let's see if we have secfrac */ - if(*pszTS == '.') { + if(lenStr > 0 && *pszTS == '.') { + --lenStr; uchar *pszStart = ++pszTS; - secfrac = srSLMGParseInt32(&pszTS); + secfrac = srSLMGParseInt32(&pszTS, &lenStr); secfracPrecision = (int) (pszTS - pszStart); } else { secfracPrecision = 0; @@ -242,23 +254,27 @@ ParseTIMESTAMP3339(struct syslogTime *pTime, uchar** ppszTS) } /* check the timezone */ - if(*pszTS == 'Z') - { + if(lenStr == 0) + ABORT_FINALIZE(RS_RET_INVLD_TIME); + + if(*pszTS == 'Z') { + --lenStr; pszTS++; /* eat Z */ OffsetMode = 'Z'; OffsetHour = 0; OffsetMinute = 0; } else if((*pszTS == '+') || (*pszTS == '-')) { OffsetMode = *pszTS; + --lenStr; pszTS++; - OffsetHour = srSLMGParseInt32(&pszTS); + OffsetHour = srSLMGParseInt32(&pszTS, &lenStr); if(OffsetHour < 0 || OffsetHour > 23) ABORT_FINALIZE(RS_RET_INVLD_TIME); - if(*pszTS++ != ':') + if(lenStr == 0 || *pszTS++ != ':') ABORT_FINALIZE(RS_RET_INVLD_TIME); - OffsetMinute = srSLMGParseInt32(&pszTS); + OffsetMinute = srSLMGParseInt32(&pszTS, &lenStr); if(OffsetMinute < 0 || OffsetMinute > 59) ABORT_FINALIZE(RS_RET_INVLD_TIME); } else { @@ -267,10 +283,12 @@ ParseTIMESTAMP3339(struct syslogTime *pTime, uchar** ppszTS) } /* OK, we actually have a 3339 timestamp, so let's indicated this */ - if(*pszTS == ' ') + if(lenStr > 0 && *pszTS == ' ') { + --lenStr; ++pszTS; - else + } else { ABORT_FINALIZE(RS_RET_INVLD_TIME); + } /* we had success, so update parse pointer and caller-provided timestamp */ *ppszTS = pszTS; @@ -286,6 +304,7 @@ ParseTIMESTAMP3339(struct syslogTime *pTime, uchar** ppszTS) pTime->OffsetMode = OffsetMode; pTime->OffsetHour = OffsetHour; pTime->OffsetMinute = OffsetMinute; + *pLenStr = lenStr; finalize_it: RETiRet; @@ -304,9 +323,13 @@ finalize_it: * permits us to use a pre-aquired timestamp and thus avoids to do * a (costly) time() call. Thanks to David Lang for insisting on * time() call reduction ;). + * This method now also checks the maximum string length it is passed. + * If a *valid* timestamp is found, the string length is decremented + * by the number of characters processed. If it is not a valid timestamp, + * the length is kept unmodified. -- rgerhards, 2009-09-23 */ static rsRetVal -ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS) +ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS, int *pLenStr) { /* variables to temporarily hold time information while we parse */ int month; @@ -316,6 +339,7 @@ ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS) int minute; int second; /* end variables to temporarily hold time information while we parse */ + int lenStr; uchar *pszTS; DEFiRet; @@ -323,6 +347,8 @@ ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS) pszTS = *ppszTS; assert(pszTS != NULL); assert(pTime != NULL); + assert(pLenStr != NULL); + lenStr = *pLenStr; /* If we look at the month (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec), * we may see the following character sequences occur: @@ -341,6 +367,9 @@ ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS) * june, when it first manifested. This also lead to invalid parsing of the rest * of the message, as the time stamp was not detected to be correct. - rgerhards */ + if(lenStr < 3) + ABORT_FINALIZE(RS_RET_INVLD_TIME); + switch(*pszTS++) { case 'J': @@ -455,26 +484,31 @@ ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS) ABORT_FINALIZE(RS_RET_INVLD_TIME); } + lenStr -= 3; + /* done month */ - if(*pszTS++ != ' ') + if(lenStr == 0 || *pszTS++ != ' ') ABORT_FINALIZE(RS_RET_INVLD_TIME); /* we accept a slightly malformed timestamp when receiving. This is * we accept one-digit days */ - if(*pszTS == ' ') + if(*pszTS == ' ') { + --lenStr; ++pszTS; + } - day = srSLMGParseInt32(&pszTS); + day = srSLMGParseInt32(&pszTS, &lenStr); if(day < 1 || day > 31) ABORT_FINALIZE(RS_RET_INVLD_TIME); - if(*pszTS++ != ' ') + if(lenStr == 0 || *pszTS++ != ' ') ABORT_FINALIZE(RS_RET_INVLD_TIME); + --lenStr; /* time part */ - hour = srSLMGParseInt32(&pszTS); + hour = srSLMGParseInt32(&pszTS, &lenStr); if(hour > 1970 && hour < 2100) { /* if so, we assume this actually is a year. This is a format found * e.g. in Cisco devices. @@ -484,23 +518,26 @@ ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS) year = hour; /* re-query the hour, this time it must be valid */ - if(*pszTS++ != ' ') + if(lenStr == 0 || *pszTS++ != ' ') ABORT_FINALIZE(RS_RET_INVLD_TIME); - hour = srSLMGParseInt32(&pszTS); + --lenStr; + hour = srSLMGParseInt32(&pszTS, &lenStr); } if(hour < 0 || hour > 23) ABORT_FINALIZE(RS_RET_INVLD_TIME); - if(*pszTS++ != ':') + if(lenStr == 0 || *pszTS++ != ':') ABORT_FINALIZE(RS_RET_INVLD_TIME); - minute = srSLMGParseInt32(&pszTS); + --lenStr; + minute = srSLMGParseInt32(&pszTS, &lenStr); if(minute < 0 || minute > 59) ABORT_FINALIZE(RS_RET_INVLD_TIME); - if(*pszTS++ != ':') + if(lenStr == 0 || *pszTS++ != ':') ABORT_FINALIZE(RS_RET_INVLD_TIME); - second = srSLMGParseInt32(&pszTS); + --lenStr; + second = srSLMGParseInt32(&pszTS, &lenStr); if(second < 0 || second > 60) ABORT_FINALIZE(RS_RET_INVLD_TIME); @@ -508,8 +545,10 @@ ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS) * invalid format, it occurs frequently enough (e.g. with Cisco devices) * to permit it as a valid case. -- rgerhards, 2008-09-12 */ - if(*pszTS++ == ':') + if(lenStr == 0 || *pszTS++ == ':') { ++pszTS; /* just skip past it */ + --lenStr; + } /* we had success, so update parse pointer and caller-provided timestamp * fields we do not have are not updated in the caller's timestamp. This @@ -526,6 +565,7 @@ ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS) pTime->second = second; pTime->secfracPrecision = 0; pTime->secfrac = 0; + *pLenStr = lenStr; finalize_it: RETiRet; diff --git a/runtime/datetime.h b/runtime/datetime.h index efb0a0af..6377a4a4 100644 --- a/runtime/datetime.h +++ b/runtime/datetime.h @@ -36,8 +36,8 @@ typedef struct datetime_s { /* interfaces */ BEGINinterface(datetime) /* name must also be changed in ENDinterface macro! */ void (*getCurrTime)(struct syslogTime *t, time_t *ttSeconds); - rsRetVal (*ParseTIMESTAMP3339)(struct syslogTime *pTime, uchar** ppszTS); - rsRetVal (*ParseTIMESTAMP3164)(struct syslogTime *pTime, uchar** pszTS); + rsRetVal (*ParseTIMESTAMP3339)(struct syslogTime *pTime, uchar** ppszTS, int *); + rsRetVal (*ParseTIMESTAMP3164)(struct syslogTime *pTime, uchar** pszTS, int *); int (*formatTimestampToMySQL)(struct syslogTime *ts, char* pDst, size_t iLenDst); int (*formatTimestampToPgSQL)(struct syslogTime *ts, char *pDst, size_t iLenDst); int (*formatTimestamp3339)(struct syslogTime *ts, char* pBuf, size_t iLenBuf); diff --git a/runtime/parser.c b/runtime/parser.c index 0b45bfd5..079bcf5e 100644 --- a/runtime/parser.c +++ b/runtime/parser.c @@ -274,6 +274,7 @@ finalize_it: RETiRet; } + /* Parse a received message. The object's rawmsg property is taken and * parsed according to the relevant standards. This can later be * extended to support configured parsers. @@ -284,6 +285,7 @@ rsRetVal parseMsg(msg_t *pMsg) DEFiRet; uchar *msg; int pri; + int lenMsg; int iPriText; CHKiRet(sanitizeMessage(pMsg)); @@ -292,8 +294,11 @@ rsRetVal parseMsg(msg_t *pMsg) DBGPRINTF("msg parser: flags %x, from '%s', msg '%s'\n", pMsg->msgFlags, pMsg->pszRcvFrom, pMsg->pszRawMsg); /* pull PRI */ - pri = DEFUPRI; + lenMsg = pMsg->iLenRawMsg; + if(lenMsg == 0) + ABORT_FINALIZE(RS_RET_EMPTY_MSG); msg = pMsg->pszRawMsg; + pri = DEFUPRI; iPriText = 0; if(*msg == '<') { /* while we process the PRI, we also fill the PRI textual representation @@ -301,7 +306,7 @@ rsRetVal parseMsg(msg_t *pMsg) * but it offers us performance... */ pri = 0; - while(isdigit((int) *++msg)) { + while(--lenMsg > 0 && isdigit((int) *++msg)) { pMsg->bufPRI[iPriText++ % 4] = *msg; /* mod 4 to guard against malformed messages! */ pri = 10 * pri + (*msg - '0'); } @@ -342,7 +347,7 @@ rsRetVal parseMsg(msg_t *pMsg) /* finalize message object */ pMsg->msgFlags &= ~NEEDS_PARSING; /* this message is now parsed */ - MsgPrepareEnqueue(pMsg); /* "historical" name - preparese for multi-threading */ + MsgPrepareEnqueue(pMsg); /* "historical" name - prepare for multi-threading */ finalize_it: RETiRet; diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h index 32177a9f..13b54731 100644 --- a/runtime/rsyslog.h +++ b/runtime/rsyslog.h @@ -280,6 +280,7 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth RS_RET_ACTION_FAILED = -2123, /**< action failed and is now suspended (consider this permanent for the time being) */ RS_RET_NONFATAL_CONFIG_ERR = -2124, /**< non-fatal error during config processing */ RS_RET_FILENAME_INVALID = -2140, /**< filename invalid, not found, no access, ... */ + RS_RET_EMPTY_MSG = -2141, /**< provided (raw) MSG is empty */ /* RainerScript error messages (range 1000.. 1999) */ RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */ diff --git a/tools/syslogd.c b/tools/syslogd.c index ff6369c3..5671dcde 100644 --- a/tools/syslogd.c +++ b/tools/syslogd.c @@ -1242,10 +1242,12 @@ msgConsumer(void __attribute__((unused)) *notNeeded, void *pUsr) * to after the terminating SP. The caller must ensure that the * provided buffer is large enough to hold the to be extracted value. * Returns 0 if everything is fine or 1 if either the field is not - * SP-terminated or any other error occurs. - * rger, 2005-11-24 + * SP-terminated or any other error occurs. -- rger, 2005-11-24 + * The function now receives the size of the string and makes sure + * that it does not process more than that. The *pLenStr counter is + * updated on exit. -- rgerhards, 2009-09-23 */ -static int parseRFCField(uchar **pp2parse, uchar *pResult) +static int parseRFCField(uchar **pp2parse, uchar *pResult, int *pLenStr) { uchar *p2parse; int iRet = 0; @@ -1257,14 +1259,17 @@ static int parseRFCField(uchar **pp2parse, uchar *pResult) p2parse = *pp2parse; /* this is the actual parsing loop */ - while(*p2parse && *p2parse != ' ') { + while(*pLenStr > 0 && *p2parse != ' ') { *pResult++ = *p2parse++; + --(*pLenStr); } - if(*p2parse == ' ') + if(*pLenStr > 0 && *p2parse == ' ') { ++p2parse; /* eat SP, but only if not at end of string */ - else + --(*pLenStr); + } else { iRet = 1; /* there MUST be an SP! */ + } *pResult = '\0'; /* set the new parse pointer */ @@ -1280,20 +1285,24 @@ static int parseRFCField(uchar **pp2parse, uchar *pResult) * to after the terminating SP. The caller must ensure that the * provided buffer is large enough to hold the to be extracted value. * Returns 0 if everything is fine or 1 if either the field is not - * SP-terminated or any other error occurs. - * rger, 2005-11-24 + * SP-terminated or any other error occurs. -- rger, 2005-11-24 + * The function now receives the size of the string and makes sure + * that it does not process more than that. The *pLenStr counter is + * updated on exit. -- rgerhards, 2009-09-23 */ -static int parseRFCStructuredData(uchar **pp2parse, uchar *pResult) +static int parseRFCStructuredData(uchar **pp2parse, uchar *pResult, int *pLenStr) { uchar *p2parse; int bCont = 1; int iRet = 0; + int lenStr; assert(pp2parse != NULL); assert(*pp2parse != NULL); assert(pResult != NULL); p2parse = *pp2parse; + lenStr = *pLenStr; /* this is the actual parsing loop * Remeber: structured data starts with [ and includes any characters @@ -1301,40 +1310,47 @@ static int parseRFCStructuredData(uchar **pp2parse, uchar *pResult) * structured data. There may also be \] inside the structured data, which * do NOT terminate an element. */ - if(*p2parse != '[') + if(lenStr == 0 || *p2parse != '[') return 1; /* this is NOT structured data! */ if(*p2parse == '-') { /* empty structured data? */ *pResult++ = '-'; ++p2parse; + --lenStr; } else { while(bCont) { - if(*p2parse == '\0') { + if(lenStr < 2) { iRet = 1; /* this is not valid! */ bCont = 0; } else if(*p2parse == '\\' && *(p2parse+1) == ']') { /* this is escaped, need to copy both */ *pResult++ = *p2parse++; *pResult++ = *p2parse++; + lenStr -= 2; } else if(*p2parse == ']' && *(p2parse+1) == ' ') { /* found end, just need to copy the ] and eat the SP */ *pResult++ = *p2parse; p2parse += 2; + lenStr -= 2; bCont = 0; } else { *pResult++ = *p2parse++; + --lenStr; } } } - if(*p2parse == ' ') + if(lenStr > 0 && *p2parse == ' ') { ++p2parse; /* eat SP, but only if not at end of string */ - else + --lenStr; + } else { iRet = 1; /* there MUST be an SP! */ + } *pResult = '\0'; /* set the new parse pointer */ *pp2parse = p2parse; + *pLenStr = lenStr; return 0; } @@ -1359,23 +1375,26 @@ int parseRFCSyslogMsg(msg_t *pMsg, int flags) { uchar *p2parse; uchar *pBuf; + int lenMsg; int bContParse = 1; BEGINfunc assert(pMsg != NULL); assert(pMsg->pszRawMsg != NULL); p2parse = pMsg->pszRawMsg + pMsg->offAfterPRI; /* point to start of text, after PRI */ + lenMsg = pMsg->iLenRawMsg - (pMsg->offAfterPRI + 1); - /* do a sanity check on the version and eat it */ + /* do a sanity check on the version and eat it (the caller checked this already) */ assert(p2parse[0] == '1' && p2parse[1] == ' '); p2parse += 2; + lenMsg -= 2; /* Now get us some memory we can use as a work buffer while parsing. * We simply allocated a buffer sufficiently large to hold all of the * message, so we can not run into any troubles. I think this is * more wise then to use individual buffers. */ - if((pBuf = malloc(sizeof(uchar) * ustrlen(p2parse) + 1)) == NULL) + if((pBuf = malloc(sizeof(uchar) * (lenMsg + 1))) == NULL) return 1; /* IMPORTANT NOTE: @@ -1386,7 +1405,7 @@ int parseRFCSyslogMsg(msg_t *pMsg, int flags) */ /* TIMESTAMP */ - if(datetime.ParseTIMESTAMP3339(&(pMsg->tTIMESTAMP), &p2parse) == RS_RET_OK) { + if(datetime.ParseTIMESTAMP3339(&(pMsg->tTIMESTAMP), &p2parse, &lenMsg) == RS_RET_OK) { if(flags & IGNDATE) { /* we need to ignore the msg data, so simply copy over reception date */ memcpy(&pMsg->tTIMESTAMP, &pMsg->tRcvdAt, sizeof(struct syslogTime)); @@ -1398,7 +1417,7 @@ int parseRFCSyslogMsg(msg_t *pMsg, int flags) /* HOSTNAME */ if(bContParse) { - parseRFCField(&p2parse, pBuf); + parseRFCField(&p2parse, pBuf, &lenMsg); MsgSetHOSTNAME(pMsg, pBuf); } else { /* we can not parse, so we get the system we @@ -1409,30 +1428,30 @@ int parseRFCSyslogMsg(msg_t *pMsg, int flags) /* APP-NAME */ if(bContParse) { - parseRFCField(&p2parse, pBuf); + parseRFCField(&p2parse, pBuf, &lenMsg); MsgSetAPPNAME(pMsg, (char*)pBuf); } /* PROCID */ if(bContParse) { - parseRFCField(&p2parse, pBuf); + parseRFCField(&p2parse, pBuf, &lenMsg); MsgSetPROCID(pMsg, (char*)pBuf); } /* MSGID */ if(bContParse) { - parseRFCField(&p2parse, pBuf); + parseRFCField(&p2parse, pBuf, &lenMsg); MsgSetMSGID(pMsg, (char*)pBuf); } /* STRUCTURED-DATA */ if(bContParse) { - parseRFCStructuredData(&p2parse, pBuf); + parseRFCStructuredData(&p2parse, pBuf, &lenMsg); MsgSetStructuredData(pMsg, (char*)pBuf); } /* MSG */ - MsgSetMSG(pMsg, (char*)p2parse); + MsgSetMSG(pMsg, (lenMsg == 0) ? "" : (char*)p2parse); free(pBuf); ENDfunc @@ -1460,11 +1479,15 @@ int parseLegacySyslogMsg(msg_t *pMsg, int flags) char *pWork; cstr_t *pStrB; int iCnt; + int lenMsg; int bTAGCharDetected; BEGINfunc assert(pMsg != NULL); assert(pMsg->pszRawMsg != NULL); + lenMsg = pMsg->iLenRawMsg - (pMsg->offAfterPRI + 1); +RUNLOG_VAR("%d", pMsg->offAfterPRI); +RUNLOG_VAR("%d", lenMsg); p2parse = pMsg->pszRawMsg + pMsg->offAfterPRI; /* point to start of text, after PRI */ /* Check to see if msg contains a timestamp. We start by assuming @@ -1473,13 +1496,14 @@ int parseLegacySyslogMsg(msg_t *pMsg, int flags) * message. There we go from high-to low precison and are done * when we find a matching one. -- rgerhards, 2008-09-16 */ - if(datetime.ParseTIMESTAMP3339(&(pMsg->tTIMESTAMP), &p2parse) == RS_RET_OK) { + if(datetime.ParseTIMESTAMP3339(&(pMsg->tTIMESTAMP), &p2parse, &lenMsg) == RS_RET_OK) { /* we are done - parse pointer is moved by ParseTIMESTAMP3339 */; - } else if(datetime.ParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), &p2parse) == RS_RET_OK) { + } else if(datetime.ParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), &p2parse, &lenMsg) == RS_RET_OK) { /* we are done - parse pointer is moved by ParseTIMESTAMP3164 */; - } else if(*p2parse == ' ') { /* try to see if it is slighly malformed - HP procurve seems to do that sometimes */ + } else if(*p2parse == ' ' && lenMsg > 1) { /* try to see if it is slighly malformed - HP procurve seems to do that sometimes */ ++p2parse; /* move over space */ - if(datetime.ParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), &p2parse) == RS_RET_OK) { + --lenMsg; + if(datetime.ParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), &p2parse, &lenMsg) == RS_RET_OK) { /* indeed, we got it! */ /* we are done - parse pointer is moved by ParseTIMESTAMP3164 */; } else { @@ -1487,6 +1511,7 @@ int parseLegacySyslogMsg(msg_t *pMsg, int flags) * for this try. */ --p2parse; + ++lenMsg; } } @@ -1520,14 +1545,15 @@ int parseLegacySyslogMsg(msg_t *pMsg, int flags) /* the memory allocated is far too much in most cases. But on the plus side, * it is quite fast... - rgerhards, 2007-09-20 */ - if((pBuf = malloc(sizeof(char)* (ustrlen(p2parse) +1))) == NULL) + if((pBuf = malloc(sizeof(char) * (lenMsg + 1))) == NULL) return 1; pWork = pBuf; /* this is the actual parsing loop */ - while(*p2parse && *p2parse != ' ' && *p2parse != ':') { + while(lenMsg > 0 && *p2parse != ' ' && *p2parse != ':') { if(*p2parse == '[' || *p2parse == ']' || *p2parse == '/') bTAGCharDetected = 1; *pWork++ = *p2parse++; + --lenMsg; } /* we need to handle ':' seperately, because it terminates the * TAG - so we also need to terminate the parser here! @@ -1539,13 +1565,17 @@ int parseLegacySyslogMsg(msg_t *pMsg, int flags) * will be true and the parse pointer remain as is. This is perfectly * well. */ - if(*p2parse == ':') { - bTAGCharDetected = 1; - /* We will move hostname to tag, so preserve ':' (otherwise we - * will needlessly change the message format) */ - *pWork++ = *p2parse++; - } else if(*p2parse == ' ') - ++p2parse; + if(lenMsg > 0) { + if(*p2parse == ':') { + bTAGCharDetected = 1; + /* We will move hostname to tag, so preserve ':' (otherwise we + * will needlessly change the message format) */ + *pWork++ = *p2parse++; + } else if(*p2parse == ' ') { + ++p2parse; + } + --lenMsg; + } *pWork = '\0'; MsgAssignHOSTNAME(pMsg, pBuf); } @@ -1584,12 +1614,14 @@ int parseLegacySyslogMsg(msg_t *pMsg, int flags) rsCStrSetAllocIncrement(pStrB, 33); pWork = pBuf; iCnt = 0; - while(*p2parse && *p2parse != ':' && *p2parse != ' ') { + while(lenMsg > 0 && *p2parse != ':' && *p2parse != ' ') { cstrAppendChar(pStrB, *p2parse++); ++iCnt; + --lenMsg; } - if(*p2parse == ':') { + if(lenMsg > 0 && *p2parse == ':') { ++p2parse; + --lenMsg; cstrAppendChar(pStrB, ':'); } cstrFinalize(pStrB); @@ -1625,7 +1657,7 @@ int parseLegacySyslogMsg(msg_t *pMsg, int flags) } /* The rest is the actual MSG */ - MsgSetMSG(pMsg, (char*)p2parse); + MsgSetMSG(pMsg, (lenMsg == 0) ? "" : (char*)p2parse); ENDfunc return 0; /* all ok */ -- cgit From e0dde79a806f46790df6104a6bacdbddaa938fd6 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 24 Sep 2009 10:49:11 +0200 Subject: bugfix: potential segfault in stream writer on destruction Most severely affected omfile. The problem was that some buffers were freed before the asynchronous writer thread was shut down. So the writer thread accessed invalid data, which may even already be overwritten. Symptoms (with omfile) were segfaults, grabled data and files with random names placed around the file system (most prominently into the root directory). Special thanks to Aaron for helping to track this down. --- ChangeLog | 8 ++++++++ runtime/stream.c | 14 +++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index a12f258e..7c6985b7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ --------------------------------------------------------------------------- Version 4.5.4 [v4-beta] (rgerhards), 2009-09-?? +- bugfix: potential segfault in stream writer on destruction + Most severely affected omfile. The problem was that some buffers were + freed before the asynchronous writer thread was shut down. So the + writer thread accessed invalid data, which may even already be + overwritten. Symptoms (with omfile) were segfaults, grabled data + and files with random names placed around the file system (most + prominently into the root directory). Special thanks to Aaron for + helping to track this down. - bugfix: potential race in object loader (obj.c) during use/release of object interface - bugfixes: potential problems in out file zip writer. Problems could diff --git a/runtime/stream.c b/runtime/stream.c index 32467082..9e88eca1 100644 --- a/runtime/stream.c +++ b/runtime/stream.c @@ -685,11 +685,6 @@ dbgprintf("XXX: destruct stream %p\n", pThis); if(pThis->fd != -1) strmCloseFile(pThis); - free(pThis->pszDir); - free(pThis->pZipBuf); - free(pThis->pszCurrFName); - free(pThis->pszFName); - if(pThis->bAsyncWrite) { stopWriter(pThis); pthread_mutex_destroy(&pThis->mut); @@ -702,6 +697,15 @@ dbgprintf("XXX: destruct stream %p\n", pThis); } else { free(pThis->pIOBuf); } + + /* IMPORTANT: we MUST free this only AFTER the ansyncWriter has been stopped, else + * we get random errors... + */ + free(pThis->pszDir); + free(pThis->pZipBuf); + free(pThis->pszCurrFName); + free(pThis->pszFName); + ENDobjDestruct(strm) -- cgit From eb9da005ba2d21e2f0b2a8ad23ad925d7d628a15 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 24 Sep 2009 11:02:00 +0200 Subject: (temporary?) removal of very conservative locks in stream.c ...after we seem to have identified the root cause of the segfault. I leave them commented out so that we can re-activate it if need arises (aka "get some practice drill first"). --- runtime/stream.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/stream.c b/runtime/stream.c index 9e88eca1..ff4515fc 100644 --- a/runtime/stream.c +++ b/runtime/stream.c @@ -1068,7 +1068,7 @@ doZipWrite(strm_t *pThis, uchar *pBuf, size_t lenBuf) assert(pThis != NULL); assert(pBuf != NULL); - pthread_mutex_lock(&mut); + //pthread_mutex_lock(&mut); /* allocate deflate state */ zstrm.zalloc = Z_NULL; @@ -1108,7 +1108,7 @@ finalize_it: } } - pthread_mutex_unlock(&mut); + //pthread_mutex_unlock(&mut); RETiRet; } -- cgit From d15eb7fa83fc4ed237a6e692b7a5e3648038333a Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 24 Sep 2009 16:05:40 +0200 Subject: bugfix: this morning's race patch was incomplete, completing now we needed to release ALL resources (including file handles!) only after the the async writer thread has terminated (else it may access them). In this case, we had a file handle leak, because the handle was sometimes only opened in the async writer, but the close was attempted before the writer even started (in some cases). --- runtime/stream.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/runtime/stream.c b/runtime/stream.c index ff4515fc..3348fb74 100644 --- a/runtime/stream.c +++ b/runtime/stream.c @@ -677,14 +677,11 @@ CODESTARTobjDestruct(strm) /* Note: mutex will be unlocked in stopWriter! */ d_pthread_mutex_lock(&pThis->mut); +dbgprintf("XXX: destruct stream 1 %p\n", pThis); if(pThis->tOperationsMode != STREAMMODE_READ) strmFlush(pThis); -dbgprintf("XXX: destruct stream %p\n", pThis); - /* ... then free resources */ - if(pThis->fd != -1) - strmCloseFile(pThis); - +dbgprintf("XXX: destruct stream 2 %p\n", pThis); if(pThis->bAsyncWrite) { stopWriter(pThis); pthread_mutex_destroy(&pThis->mut); @@ -697,10 +694,15 @@ dbgprintf("XXX: destruct stream %p\n", pThis); } else { free(pThis->pIOBuf); } +dbgprintf("XXX: destruct stream 3 (doing close) %p\n", pThis); - /* IMPORTANT: we MUST free this only AFTER the ansyncWriter has been stopped, else + /* Finally, we can free the resources. + * IMPORTANT: we MUST free this only AFTER the ansyncWriter has been stopped, else * we get random errors... */ + if(pThis->fd != -1) + strmCloseFile(pThis); + free(pThis->pszDir); free(pThis->pZipBuf); free(pThis->pszCurrFName); -- cgit From 8bab264ba168b5fee36a7b45020e5e2172c74224 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 29 Sep 2009 09:50:39 +0200 Subject: minor cleanup & preparation for 4.5.4 --- ChangeLog | 2 +- runtime/stream.c | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7c6985b7..cf05b59c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,5 @@ --------------------------------------------------------------------------- -Version 4.5.4 [v4-beta] (rgerhards), 2009-09-?? +Version 4.5.4 [v4-beta] (rgerhards), 2009-09-29 - bugfix: potential segfault in stream writer on destruction Most severely affected omfile. The problem was that some buffers were freed before the asynchronous writer thread was shut down. So the diff --git a/runtime/stream.c b/runtime/stream.c index 3348fb74..ac90df28 100644 --- a/runtime/stream.c +++ b/runtime/stream.c @@ -677,11 +677,9 @@ CODESTARTobjDestruct(strm) /* Note: mutex will be unlocked in stopWriter! */ d_pthread_mutex_lock(&pThis->mut); -dbgprintf("XXX: destruct stream 1 %p\n", pThis); if(pThis->tOperationsMode != STREAMMODE_READ) strmFlush(pThis); -dbgprintf("XXX: destruct stream 2 %p\n", pThis); if(pThis->bAsyncWrite) { stopWriter(pThis); pthread_mutex_destroy(&pThis->mut); @@ -694,7 +692,6 @@ dbgprintf("XXX: destruct stream 2 %p\n", pThis); } else { free(pThis->pIOBuf); } -dbgprintf("XXX: destruct stream 3 (doing close) %p\n", pThis); /* Finally, we can free the resources. * IMPORTANT: we MUST free this only AFTER the ansyncWriter has been stopped, else @@ -850,7 +847,6 @@ doAsyncWriteInternal(strm_t *pThis, size_t lenBuf) DEFiRet; ISOBJ_TYPE_assert(pThis, strm); -dbgprintf("XXX: doAsyncWriteInternal: strm %p, len %ld\n", pThis, (long) lenBuf); while(pThis->iCnt >= STREAM_ASYNC_NUMBUFS) d_pthread_cond_wait(&pThis->notFull, &pThis->mut); @@ -1065,13 +1061,10 @@ doZipWrite(strm_t *pThis, uchar *pBuf, size_t lenBuf) z_stream zstrm; int zRet; /* zlib return state */ bool bzInitDone = FALSE; - static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; DEFiRet; assert(pThis != NULL); assert(pBuf != NULL); - //pthread_mutex_lock(&mut); - /* allocate deflate state */ zstrm.zalloc = Z_NULL; zstrm.zfree = Z_NULL; @@ -1110,8 +1103,6 @@ finalize_it: } } - //pthread_mutex_unlock(&mut); - RETiRet; } -- cgit From 5c6eee3e440e486a1b2aeef7eeebb766509d79dc Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 29 Sep 2009 13:59:02 +0200 Subject: bumped version number --- configure.ac | 2 +- doc/manual.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 059d68c7..66a2d70d 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.61) -AC_INIT([rsyslog],[4.4.1],[rsyslog@lists.adiscon.com]) +AC_INIT([rsyslog],[4.4.2],[rsyslog@lists.adiscon.com]) AM_INIT_AUTOMAKE AC_CONFIG_SRCDIR([ChangeLog]) AC_CONFIG_MACRO_DIR([m4]) diff --git a/doc/manual.html b/doc/manual.html index 19332b33..5d43cb25 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -19,7 +19,7 @@ rsyslog support available directly from the source!

Please visit the rsyslog sponsor's page to honor the project sponsors or become one yourself! We are very grateful for any help towards the project goals.

-

This documentation is for version 4.4.1 (v4-stable) of rsyslog. +

This documentation is for version 4.4.2 (v4-stable) of rsyslog. Visit the rsyslog status page to obtain current version information and project status.

If you like rsyslog, you might -- cgit From 536415cf3dba053b0d2294b7f1dc8e34328e795f Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 29 Sep 2009 14:22:11 +0200 Subject: bugfix: invalid handling of zero-sized messages could lead to mis-addressing and potential memory corruption/segfault --- ChangeLog | 2 ++ runtime/parser.c | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6272aee2..abec5762 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ --------------------------------------------------------------------------- Version 4.4.2 [v4-stable] (rgerhards), 2009-09-?? +- bugfix: invalid handling of zero-sized messages, could lead to mis- + addressing and potential memory corruption/segfault - bugfix: random data could be appended to message, possibly causing segfaults - bugfix: reverse lookup reduction logic in imudp do DNS queries too often diff --git a/runtime/parser.c b/runtime/parser.c index 079bcf5e..7eff0801 100644 --- a/runtime/parser.c +++ b/runtime/parser.c @@ -167,6 +167,7 @@ sanitizeMessage(msg_t *pMsg) size_t iMaxLine; assert(pMsg != NULL); + assert(pMsg->iLenRawMsg > 0); # ifdef USE_NETZIP CHKiRet(uncompressMessage(pMsg)); @@ -288,6 +289,9 @@ rsRetVal parseMsg(msg_t *pMsg) int lenMsg; int iPriText; + if(pMsg->iLenRawMsg == 0) + ABORT_FINALIZE(RS_RET_EMPTY_MSG); + CHKiRet(sanitizeMessage(pMsg)); /* we needed to sanitize first, because we otherwise do not have a C-string we can print... */ @@ -295,8 +299,6 @@ rsRetVal parseMsg(msg_t *pMsg) /* pull PRI */ lenMsg = pMsg->iLenRawMsg; - if(lenMsg == 0) - ABORT_FINALIZE(RS_RET_EMPTY_MSG); msg = pMsg->pszRawMsg; pri = DEFUPRI; iPriText = 0; -- cgit From f45217e776c937b677653c287d63b54ac8281bba Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 29 Sep 2009 14:37:33 +0200 Subject: bugfix: zero-sized UDP messages are no longer processed Until now, they were forwarded to processing, but this makes no sense Also, it looks like the system seems to provide a zero return code on a UDP recvfrom() from time to time for some internal reasons. These "receives" are now silently ignored. --- ChangeLog | 5 +++++ plugins/imudp/imudp.c | 3 +++ 2 files changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index abec5762..331afe80 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,11 @@ Version 4.4.2 [v4-stable] (rgerhards), 2009-09-?? - bugfix: invalid handling of zero-sized messages, could lead to mis- addressing and potential memory corruption/segfault +- bugfix: zero-sized UDP messages are no longer processed + until now, they were forwarded to processing, but this makes no sense + Also, it looks like the system seems to provide a zero return code + on a UDP recvfrom() from time to time for some internal reasons. These + "receives" are now silently ignored. - bugfix: random data could be appended to message, possibly causing segfaults - bugfix: reverse lookup reduction logic in imudp do DNS queries too often diff --git a/plugins/imudp/imudp.c b/plugins/imudp/imudp.c index 658ceb23..6f4a6384 100644 --- a/plugins/imudp/imudp.c +++ b/plugins/imudp/imudp.c @@ -178,6 +178,9 @@ processSocket(int fd, struct sockaddr_storage *frominetPrev, int *pbIsPermitted, ABORT_FINALIZE(RS_RET_ERR); } + if(lenRcvBuf == 0) + continue; /* this looks a bit strange, but practice shows it happens... */ + /* if we reach this point, we had a good receive and can process the packet received */ /* check if we have a different sender than before, if so, we need to query some new values */ if(net.CmpHost(&frominet, frominetPrev, socklen) != 0) { -- cgit From 3be997f94354ffb03a6fb8b1874c42a9e2e88015 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 30 Sep 2009 12:41:38 +0200 Subject: doc bugfix: default for $DirCreateMode incorrectly stated --- ChangeLog | 1 + doc/rsconf1_dircreatemode.html | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index c50899e7..841af011 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,7 @@ Version 2.0.8 V2-STABLE (rgerhards), 2008-??-?? connection broke, but not if there was a problem with statement execution. The most probable case for such a case would be invalid sql inside the template, and this is now much easier to diagnose. +- doc bugfix: default for $DirCreateMode incorrectly stated --------------------------------------------------------------------------- Version 2.0.7 V2-STABLE (rgerhards), 2008-04-14 - bugfix: the default for $DirCreateMode was 0644, and as such wrong. diff --git a/doc/rsconf1_dircreatemode.html b/doc/rsconf1_dircreatemode.html index 66a35e18..057f53e5 100644 --- a/doc/rsconf1_dircreatemode.html +++ b/doc/rsconf1_dircreatemode.html @@ -5,9 +5,13 @@

$DirCreateMode

Type: global configuration directive

-

Default: 0644

+

Default: 0700

Description:

This is the same as $FileCreateMode, but for directories automatically generated.

+

Please visit the +rsyslog mailing list +archive +to understand why the default is so restrictive.

Sample:

@@ -15,8 +19,8 @@ index] [rsyslog site]

This documentation is part of the rsyslog project.
-Copyright © 2007 by Rainer Gerhards and +Copyright © 2007-2009 by Rainer Gerhards and Adiscon. Released under the GNU GPL -version 2 or higher.

+version 3 or higher.

- \ No newline at end of file + -- cgit From cb9761627630dc8aeafbbfcfe091f87b66b5a92a Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 1 Oct 2009 16:54:34 +0200 Subject: RFC5424 formatted messages with only structured data and no MSG part were improperly handled. This was a regression of one of the last bugfixes, so no previously released version contained this bug (thus it does not show up in the ChangeLog). --- runtime/datetime.c | 5 +++++ runtime/rsyslog.h | 2 +- tools/syslogd.c | 16 ++++++++++++---- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/runtime/datetime.c b/runtime/datetime.c index fc56b27c..99caaf97 100644 --- a/runtime/datetime.c +++ b/runtime/datetime.c @@ -213,18 +213,21 @@ ParseTIMESTAMP3339(struct syslogTime *pTime, uchar** ppszTS, int *pLenStr) */ if(lenStr == 0 || *pszTS++ != '-') ABORT_FINALIZE(RS_RET_INVLD_TIME); + --lenStr; month = srSLMGParseInt32(&pszTS, &lenStr); if(month < 1 || month > 12) ABORT_FINALIZE(RS_RET_INVLD_TIME); if(lenStr == 0 || *pszTS++ != '-') ABORT_FINALIZE(RS_RET_INVLD_TIME); + --lenStr; day = srSLMGParseInt32(&pszTS, &lenStr); if(day < 1 || day > 31) ABORT_FINALIZE(RS_RET_INVLD_TIME); if(lenStr == 0 || *pszTS++ != 'T') ABORT_FINALIZE(RS_RET_INVLD_TIME); + --lenStr; hour = srSLMGParseInt32(&pszTS, &lenStr); if(hour < 0 || hour > 23) @@ -232,12 +235,14 @@ ParseTIMESTAMP3339(struct syslogTime *pTime, uchar** ppszTS, int *pLenStr) if(lenStr == 0 || *pszTS++ != ':') ABORT_FINALIZE(RS_RET_INVLD_TIME); + --lenStr; minute = srSLMGParseInt32(&pszTS, &lenStr); if(minute < 0 || minute > 59) ABORT_FINALIZE(RS_RET_INVLD_TIME); if(lenStr == 0 || *pszTS++ != ':') ABORT_FINALIZE(RS_RET_INVLD_TIME); + --lenStr; second = srSLMGParseInt32(&pszTS, &lenStr); if(second < 0 || second > 60) ABORT_FINALIZE(RS_RET_INVLD_TIME); diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h index 13b54731..835fff27 100644 --- a/runtime/rsyslog.h +++ b/runtime/rsyslog.h @@ -280,7 +280,7 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth RS_RET_ACTION_FAILED = -2123, /**< action failed and is now suspended (consider this permanent for the time being) */ RS_RET_NONFATAL_CONFIG_ERR = -2124, /**< non-fatal error during config processing */ RS_RET_FILENAME_INVALID = -2140, /**< filename invalid, not found, no access, ... */ - RS_RET_EMPTY_MSG = -2141, /**< provided (raw) MSG is empty */ + RS_RET_EMPTY_MSG = -2143, /**< provided (raw) MSG is empty */ /* RainerScript error messages (range 1000.. 1999) */ RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */ diff --git a/tools/syslogd.c b/tools/syslogd.c index 5671dcde..5f6b480f 100644 --- a/tools/syslogd.c +++ b/tools/syslogd.c @@ -1320,9 +1320,17 @@ static int parseRFCStructuredData(uchar **pp2parse, uchar *pResult, int *pLenStr } else { while(bCont) { if(lenStr < 2) { - iRet = 1; /* this is not valid! */ - bCont = 0; - } else if(*p2parse == '\\' && *(p2parse+1) == ']') { + /* we now need to check if we have only structured data */ + if(lenStr > 0 && *p2parse == ']') { + *pResult++ = *p2parse; + p2parse++; + lenStr--; + bCont = 0; + } else { + iRet = 1; /* this is not valid! */ + bCont = 0; + } + } else if(*p2parse == '\\' && *(p2parse+1) == ']') { /* this is escaped, need to copy both */ *pResult++ = *p2parse++; *pResult++ = *p2parse++; @@ -1382,7 +1390,7 @@ int parseRFCSyslogMsg(msg_t *pMsg, int flags) assert(pMsg != NULL); assert(pMsg->pszRawMsg != NULL); p2parse = pMsg->pszRawMsg + pMsg->offAfterPRI; /* point to start of text, after PRI */ - lenMsg = pMsg->iLenRawMsg - (pMsg->offAfterPRI + 1); + lenMsg = pMsg->iLenRawMsg - pMsg->offAfterPRI; /* do a sanity check on the version and eat it (the caller checked this already) */ assert(p2parse[0] == '1' && p2parse[1] == ' '); -- cgit From 6a69e478224d1513dbe8501e8978643ba89c8c82 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 1 Oct 2009 18:39:21 +0200 Subject: added $InputTCPServerNotifyOnConnectionClose config directive --- ChangeLog | 4 ++++ doc/imtcp.html | 4 ++++ plugins/imtcp/imtcp.c | 5 +++++ tcpsrv.c | 19 +++++++++++++++++++ tcpsrv.h | 5 ++++- 5 files changed, 36 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index cf05b59c..7a40032b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,8 @@ --------------------------------------------------------------------------- +Version 4.5.5 [v4-beta] (rgerhards), 2009-09-?? +- added $InputTCPServerNotifyOnConnectionClose config directive + see doc for details +--------------------------------------------------------------------------- Version 4.5.4 [v4-beta] (rgerhards), 2009-09-29 - bugfix: potential segfault in stream writer on destruction Most severely affected omfile. The problem was that some buffers were diff --git a/doc/imtcp.html b/doc/imtcp.html index 5217634e..0ccdecc7 100644 --- a/doc/imtcp.html +++ b/doc/imtcp.html @@ -41,6 +41,10 @@ very limited interest in fixing this issue. This directive can not fix th That would require much more code changes, which I was unable to do so far. Full details can be found at the Cisco tcp syslog anomaly page. +
  • $InputTCPServerNotifyOnConnectionClose [on/off] (available since 4.5.5)
    +instructs imtcp to emit a message if the remote peer closes a connection.
    +Important: This directive is global to all listeners and must be given right +after loading imtcp, otherwise it may have no effect.
  • $InputTCPServerRun <port>
    Starts a TCP server on selected port
  • $InputTCPMaxListeners <number>
    diff --git a/plugins/imtcp/imtcp.c b/plugins/imtcp/imtcp.c index 01c4bc33..d122e976 100644 --- a/plugins/imtcp/imtcp.c +++ b/plugins/imtcp/imtcp.c @@ -84,6 +84,7 @@ static permittedPeers_t *pPermPeersRoot = NULL; static int iTCPSessMax = 200; /* max number of sessions */ static int iTCPLstnMax = 20; /* max number of sessions */ static int iStrmDrvrMode = 0; /* mode for stream driver, driver-dependent (0 mostly means plain tcp) */ +static int bEmitMsgOnClose = 0; /* emit an informational message on close by remote peer */ static int iAddtlFrameDelim = TCPSRV_NO_ADDTL_DELIMITER; /* addtl frame delimiter, e.g. for netscreen, default none */ static uchar *pszStrmDrvrAuthMode = NULL; /* authentication mode to use */ static uchar *pszInputName = NULL; /* value for inputname property, NULL is OK and handled by core engine */ @@ -197,6 +198,7 @@ static rsRetVal addTCPListener(void __attribute__((unused)) *pVal, uchar *pNewVa CHKiRet(tcpsrv.SetCBOnErrClose(pOurTcpsrv, onErrClose)); CHKiRet(tcpsrv.SetDrvrMode(pOurTcpsrv, iStrmDrvrMode)); CHKiRet(tcpsrv.SetAddtlFrameDelim(pOurTcpsrv, iAddtlFrameDelim)); + CHKiRet(tcpsrv.SetNotificationOnRemoteClose(pOurTcpsrv, bEmitMsgOnClose)); /* now set optional params, but only if they were actually configured */ if(pszStrmDrvrAuthMode != NULL) { CHKiRet(tcpsrv.SetDrvrAuthMode(pOurTcpsrv, pszStrmDrvrAuthMode)); @@ -277,6 +279,7 @@ resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unus iTCPSessMax = 200; iTCPLstnMax = 20; iStrmDrvrMode = 0; + bEmitMsgOnClose = 0; iAddtlFrameDelim = TCPSRV_NO_ADDTL_DELIMITER; free(pszInputName); pszInputName = NULL; @@ -313,6 +316,8 @@ CODEmodInit_QueryRegCFSLineHdlr NULL, &iTCPSessMax, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputtcpmaxlisteners"), 0, eCmdHdlrInt, NULL, &iTCPLstnMax, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputtcpservernotifyonconnectionclose"), 0, + eCmdHdlrBinary, NULL, &bEmitMsgOnClose, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputtcpserverstreamdrivermode"), 0, eCmdHdlrInt, NULL, &iStrmDrvrMode, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputtcpserverstreamdriverauthmode"), 0, diff --git a/tcpsrv.c b/tcpsrv.c index 0be723d1..543425ea 100644 --- a/tcpsrv.c +++ b/tcpsrv.c @@ -529,6 +529,14 @@ Run(tcpsrv_t *pThis) iRet = pThis->pRcvData(pThis->pSessions[iTCPSess], buf, sizeof(buf), &iRcvd); switch(iRet) { case RS_RET_CLOSED: + if(pThis->bEmitMsgOnClose) { + uchar *pszPeer; + int lenPeer; + errno = 0; + prop.GetString(pThis->pSessions[iTCPSess]->fromHostIP, &pszPeer, &lenPeer); + errmsg.LogError(0, iRet, "Netstream session %p closed by remote peer %s.\n", + pThis->pSessions[iTCPSess]->pStrm, pszPeer); + } pThis->pOnRegularClose(pThis->pSessions[iTCPSess]); tcps_sess.Destruct(&pThis->pSessions[iTCPSess]); break; @@ -778,6 +786,16 @@ SetRuleset(tcpsrv_t *pThis, ruleset_t *pRuleset) } +/* Set connection close notification */ +static rsRetVal +SetNotificationOnRemoteClose(tcpsrv_t *pThis, int bNewVal) +{ + DEFiRet; + pThis->bEmitMsgOnClose = bNewVal; + RETiRet; +} + + /* here follows a number of methods that shuffle authentication settings down * to the drivers. Drivers not supporting these settings may return an error * state. @@ -894,6 +912,7 @@ CODESTARTobjQueryInterface(tcpsrv) pIf->SetCBOnErrClose = SetCBOnErrClose; pIf->SetOnMsgReceive = SetOnMsgReceive; pIf->SetRuleset = SetRuleset; + pIf->SetNotificationOnRemoteClose = SetNotificationOnRemoteClose; finalize_it: ENDobjQueryInterface(tcpsrv) diff --git a/tcpsrv.h b/tcpsrv.h index 64065aab..b8d82163 100644 --- a/tcpsrv.h +++ b/tcpsrv.h @@ -54,12 +54,14 @@ struct tcpsrv_s { uchar *pszInputName; /**< value to be used as input name */ ruleset_t *pRuleset; /**< ruleset to bind to */ permittedPeers_t *pPermPeers;/**< driver's permitted peers */ + bool bEmitMsgOnClose; /**< emit an informational message when the remote peer closes connection */ int iLstnCurr; /**< max nbr of listeners currently supported */ netstrm_t **ppLstn; /**< our netstream listners */ tcpLstnPortList_t **ppLstnPort; /**< pointer to relevant listen port description */ int iLstnMax; /**< max number of listners supported */ int iSessMax; /**< max number of sessions supported */ tcpLstnPortList_t *pLstnPorts; /**< head pointer for listen ports */ + int addtlFrameDelim; /**< additional frame delimiter for plain TCP syslog framing (e.g. to handle NetScreen) */ tcps_sess_t **pSessions;/**< array of all of our sessions */ void *pUsr; /**< a user-settable pointer (provides extensibility for "derived classes")*/ @@ -114,8 +116,9 @@ BEGINinterface(tcpsrv) /* name must also be changed in ENDinterface macro! */ rsRetVal (*SetRuleset)(tcpsrv_t *pThis, ruleset_t*); /* 2009-06-12 */ /* added v7 */ rsRetVal (*SetLstnMax)(tcpsrv_t *pThis, int iMaxLstn); /* 2009-08-17 */ + rsRetVal (*SetNotificationOnRemoteClose)(tcpsrv_t *pThis, int bNewVal); /* 2009-10-01 */ ENDinterface(tcpsrv) -#define tcpsrvCURR_IF_VERSION 7 /* increment whenever you change the interface structure! */ +#define tcpsrvCURR_IF_VERSION 8 /* increment whenever you change the interface structure! */ /* change for v4: * - SetAddtlFrameDelim() added -- rgerhards, 2008-12-10 * - SetInputName() added -- rgerhards, 2008-12-10 -- cgit From 724ba2b27f4a2c583b3e257e33a2f0b4b9649ef1 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 1 Oct 2009 18:47:16 +0200 Subject: bumped version number, corrected error message code (minor nit) --- configure.ac | 2 +- doc/manual.html | 2 +- runtime/rsyslog.h | 1 + tcpsrv.c | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index eba3d76f..914969c1 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.61) -AC_INIT([rsyslog],[4.5.4],[rsyslog@lists.adiscon.com]) +AC_INIT([rsyslog],[4.5.5],[rsyslog@lists.adiscon.com]) AM_INIT_AUTOMAKE AC_CONFIG_SRCDIR([ChangeLog]) AC_CONFIG_MACRO_DIR([m4]) diff --git a/doc/manual.html b/doc/manual.html index ed0048bb..2d4b4390 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -19,7 +19,7 @@ rsyslog support available directly from the source!

    Please visit the rsyslog sponsor's page to honor the project sponsors or become one yourself! We are very grateful for any help towards the project goals.

    -

    This documentation is for version 4.5.4 (v4-beta branch) of rsyslog. +

    This documentation is for version 4.5.5 (v4-beta branch) of rsyslog. Visit the rsyslog status page to obtain current version information and project status.

    If you like rsyslog, you might diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h index 8a043dde..eb5b4537 100644 --- a/runtime/rsyslog.h +++ b/runtime/rsyslog.h @@ -367,6 +367,7 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth RS_RET_FILENAME_INVALID = -2140, /**< filename invalid, not found, no access, ... */ RS_RET_ZLIB_ERR = -2141, /**< error during zlib call */ RS_RET_VAR_NOT_FOUND = -2142, /**< variable not found */ + RS_RET_PEER_CLOSED_CONN = -2144, /**< remote peer closed connection (information, no error) */ /* RainerScript error messages (range 1000.. 1999) */ RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */ diff --git a/tcpsrv.c b/tcpsrv.c index 543425ea..0102bee7 100644 --- a/tcpsrv.c +++ b/tcpsrv.c @@ -534,7 +534,7 @@ Run(tcpsrv_t *pThis) int lenPeer; errno = 0; prop.GetString(pThis->pSessions[iTCPSess]->fromHostIP, &pszPeer, &lenPeer); - errmsg.LogError(0, iRet, "Netstream session %p closed by remote peer %s.\n", + errmsg.LogError(0, RS_RET_PEER_CLOSED_CONN, "Netstream session %p closed by remote peer %s.\n", pThis->pSessions[iTCPSess]->pStrm, pszPeer); } pThis->pOnRegularClose(pThis->pSessions[iTCPSess]); -- cgit From 4c8546fd6fb56d5439edb5a098c8f82bc8fc36aa Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 2 Oct 2009 09:25:54 +0200 Subject: bumped version number --- ChangeLog | 7 +++++++ configure.ac | 2 +- doc/manual.html | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 51d2e4a1..5055ebf1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,11 @@ --------------------------------------------------------------------------- +Version 4.5.6 [v4-beta] (rgerhards), 2009-09-?? +- included some important fixes from v4-stable: + * bugfix: invalid handling of zero-sized messages + * bugfix: zero-sized UDP messages are no longer processed + * bugfix: random data could be appended to message + * bugfix: reverse lookup reduction logic in imudp do DNS queries too often +--------------------------------------------------------------------------- Version 4.5.5 [v4-beta] (rgerhards), 2009-09-?? - added $InputTCPServerNotifyOnConnectionClose config directive see doc for details diff --git a/configure.ac b/configure.ac index 914969c1..39e78d24 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.61) -AC_INIT([rsyslog],[4.5.5],[rsyslog@lists.adiscon.com]) +AC_INIT([rsyslog],[4.5.6],[rsyslog@lists.adiscon.com]) AM_INIT_AUTOMAKE AC_CONFIG_SRCDIR([ChangeLog]) AC_CONFIG_MACRO_DIR([m4]) diff --git a/doc/manual.html b/doc/manual.html index 2d4b4390..e6935d50 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -19,7 +19,7 @@ rsyslog support available directly from the source!

    Please visit the rsyslog sponsor's page to honor the project sponsors or become one yourself! We are very grateful for any help towards the project goals.

    -

    This documentation is for version 4.5.5 (v4-beta branch) of rsyslog. +

    This documentation is for version 4.5.6 (v4-beta branch) of rsyslog. Visit the rsyslog status page to obtain current version information and project status.

    If you like rsyslog, you might -- cgit