From bb67fd7fbf99ce0ec01b347fad5d1d9d101bfa5d Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 18 Mar 2011 14:21:09 +0100 Subject: experimental: support for systemd-induced second PRI in klog if systemd writes a kernel log entry with a non-kernel priority, the priority recorded in the kernel log will be wrong. However, it will be immediately followed by another priority (with the kernel timestamp in between, if enabled). So imklog now tries to see if there is a second PRI and, if so, uses it. Note that we already support non-kernel PRIs in the kernel log, as this was done in BSD for quite some while. HOWEVER the config statement "$klogpermitnonkernelfacility on" must be used to permit this (otherwise non kernel messages are dropped). Sample of a such a message on a kernel without timestamping enabled: $ echo '<14>text' > /dev/kmsg $ dmesg -r <4><14>text NOTE: support for timestamp is NOT YET ENABLED! --- plugins/imklog/imklog.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/plugins/imklog/imklog.c b/plugins/imklog/imklog.c index 69c8cd1a..c09fa4d8 100644 --- a/plugins/imklog/imklog.c +++ b/plugins/imklog/imklog.c @@ -186,12 +186,28 @@ rsRetVal imklogLogIntMsg(int priority, char *fmt, ...) rsRetVal Syslog(int priority, uchar *pMsg) { DEFiRet; + int pri = -1; rsRetVal localRet; - /* Output using syslog */ - localRet = parsePRI(&pMsg, &priority); - if(localRet != RS_RET_INVALID_PRI && localRet != RS_RET_OK) - FINALIZE; + /* first check if we have two PRIs. This can happen in case of systemd, + * in which case the second PRI is the rigth one. + * TODO: added kernel timestamp support to this PoC. -- rgerhards, 2011-03-18 + */ + if(pMsg[3] == '<') { /* could be a pri... */ + uchar *pMsgTmp = pMsg + 3; + localRet = parsePRI(&pMsgTmp, &pri); + if(localRet == RS_RET_OK && pri >= 8 && pri <= 192) { + /* *this* is our PRI */ + DBGPRINTF("imklog detected secondary PRI in klog msg\n"); + pMsg = pMsgTmp; + priority = pri; + } + } + if(pri == -1) { + localRet = parsePRI(&pMsg, &priority); + if(localRet != RS_RET_INVALID_PRI && localRet != RS_RET_OK) + FINALIZE; + } /* if we don't get the pri, we use whatever we were supplied */ /* ignore non-kernel messages if not permitted */ -- cgit From 9faa5048e6140136379c7322c7bd29f3e5629b65 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 19 Apr 2011 07:28:21 +0200 Subject: updates ChangeLog with imported systemd support enhancement --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index 3cc13082..dc9c17f9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ --------------------------------------------------------------------------- Version 5.9.0 [V5-DEVEL] (rgerhards), 2011-03-?? - this begins a new devel branch for v5 +- added support for user-level PRI provided via systemd - added new config directive $InputTCPFlowControl to select if tcp received messages shall be flagged as light delayable or not. - enhanced omhdfs to support batching mode. This permits to increase -- cgit From de77494415ae8c169949d13ed0df0af3b1949b54 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 26 Apr 2011 18:23:42 +0200 Subject: bugfix: do not open files with full privileges, if privs will be dropped This make the privilege drop code more bulletproof, but breaks Ubuntu's work-around for log files created by external programs with the wrong user and/or group. Note that it was long said that this "functionality" would break once we go for serious privilege drop code, so hopefully nobody still depends on it (and, if so, they lost...). --- ChangeLog | 6 +++++ doc/rsconf1_omfileforcechown.html | 5 +++- tools/omfile.c | 51 ++++++++++++--------------------------- 3 files changed, 25 insertions(+), 37 deletions(-) diff --git a/ChangeLog b/ChangeLog index dc9c17f9..f98057a6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ --------------------------------------------------------------------------- Version 5.9.0 [V5-DEVEL] (rgerhards), 2011-03-?? +- bugfix: do not open files with full privileges, if privs will be dropped + This make the privilege drop code more bulletproof, but breaks Ubuntu's + work-around for log files created by external programs with the wrong + user and/or group. Note that it was long said that this "functionality" + would break once we go for serious privilege drop code, so hopefully + nobody still depends on it (and, if so, they lost...). - this begins a new devel branch for v5 - added support for user-level PRI provided via systemd - added new config directive $InputTCPFlowControl to select if tcp diff --git a/doc/rsconf1_omfileforcechown.html b/doc/rsconf1_omfileforcechown.html index 7415a6f6..a680810b 100644 --- a/doc/rsconf1_omfileforcechown.html +++ b/doc/rsconf1_omfileforcechown.html @@ -8,7 +8,10 @@

$omfileForceChown

Type: global configuration directive

Parameter Values: boolean (on/off, yes/no)

-

Available since: 4.7.0+, 5.3.0+

+

Available: 4.7.0+, 5.3.0-5.8.x, NOT available in 5.9.x or higher

+

Note: this directive has been removed and is no longer available. The +documentation is currently being retained for historical reaons. Expect +it to go away at some later stage as well.

Default: off

Description:

Forces rsyslogd to change the ownership for output files that already exist. Please note diff --git a/tools/omfile.c b/tools/omfile.c index 08f965b3..7585ea8c 100644 --- a/tools/omfile.c +++ b/tools/omfile.c @@ -122,13 +122,11 @@ typedef struct s_dynaFileCacheEntry dynaFileCacheEntry; #define USE_ASYNCWRITER_DFLT 0 /* default buffer use async writer */ #define FLUSHONTX_DFLT 1 /* default for flush on TX end */ -#define DFLT_bForceChown 0 /* globals for default values */ static int iDynaFileCacheSize = 10; /* max cache for dynamic files */ static int fCreateMode = 0644; /* mode to use when creating files */ static int fDirCreateMode = 0700; /* mode to use when creating files */ static int bFailOnChown; /* fail if chown fails? */ -static int bForceChown = DFLT_bForceChown; /* Force chown() on existing files? */ static uid_t fileUID; /* UID to be used for newly created files */ static uid_t fileGID; /* GID to be used for newly created files */ static uid_t dirUID; /* UID to be used for newly created directories */ @@ -153,7 +151,6 @@ typedef struct _instanceData { int fDirCreateMode; /* creation mode for mkdir() */ int bCreateDirs; /* auto-create directories? */ int bSyncFile; /* should the file by sync()'ed? 1- yes, 0- no */ - sbool bForceChown; /* force chown() on existing files? */ uid_t fileUID; /* IDs for creation */ uid_t dirUID; gid_t fileGID; @@ -200,7 +197,6 @@ CODESTARTdbgPrintInstInfo dbgprintf("\tfile cache size=%d\n", pData->iDynaFileCacheSize); dbgprintf("\tcreate directories: %s\n", pData->bCreateDirs ? "yes" : "no"); dbgprintf("\tfile owner %d, group %d\n", (int) pData->fileUID, (int) pData->fileGID); - dbgprintf("\tforce chown() for all files: %s\n", pData->bForceChown ? "yes" : "no"); dbgprintf("\tdirectory owner %d, group %d\n", (int) pData->dirUID, (int) pData->dirGID); dbgprintf("\tdir create mode 0%3.3o, file create mode 0%3.3o\n", pData->fDirCreateMode, pData->fCreateMode); @@ -239,6 +235,12 @@ rsRetVal setDynaFileCacheSize(void __attribute__((unused)) *pVal, int iNewVal) } +rsRetVal goneAway(void __attribute__((unused)) *pVal, int iNewVal) +{ + errmsg.LogError(0, RS_RET_ERR, "directive $omfileForceChown is no longer supported"); +} + + /* Helper to cfline(). Parses a output channel name up until the first * comma and then looks for the template specifier. Tries * to find that template. Maps the output channel to the @@ -388,22 +390,7 @@ prepareFile(instanceData *pData, uchar *newFileName) int fd; DEFiRet; - if(access((char*)newFileName, F_OK) == 0) { - if(pData->bForceChown) { - /* Try to fix wrong ownership set by someone else. Note that this code - * will no longer work once we have made the $PrivDrop code fully secure. - * This change is based on an idea of Michael Terry, provided as part of - * the effort to make rsyslogd the Ubuntu default syslogd. - * rgerhards, 2009-09-11 - */ - if(chown((char*)newFileName, pData->fileUID, pData->fileGID) != 0) { - if(pData->bFailOnChown) { - int eSave = errno; - errno = eSave; - } - } - } - } else { + if(access((char*)newFileName, F_OK) != 0) { /* file does not exist, create it (and eventually parent directories */ if(pData->bCreateDirs) { /* We first need to create parent dirs if they are missing. @@ -423,7 +410,7 @@ prepareFile(instanceData *pData, uchar *newFileName) pData->fCreateMode); if(fd != -1) { /* check and set uid/gid */ - if(pData->bForceChown || pData->fileUID != (uid_t)-1 || pData->fileGID != (gid_t) -1) { + if(pData->fileUID != (uid_t)-1 || pData->fileGID != (gid_t) -1) { /* we need to set owner/group */ if(fchown(fd, pData->fileUID, pData->fileGID) != 0) { if(pData->bFailOnChown) { @@ -473,6 +460,9 @@ prepareFile(instanceData *pData, uchar *newFileName) CHKiRet(strm.ConstructFinalize(pData->pStrm)); finalize_it: + if(pData->pStrm == NULL) { + DBGPRINTF("Error opening log file: %s\n", pData->f_fname); + } RETiRet; } @@ -647,6 +637,9 @@ writeFile(uchar **ppString, unsigned iMsgOpts, instanceData *pData) } else { /* "regular", non-dynafile */ if(pData->pStrm == NULL) { CHKiRet(prepareFile(pData, pData->f_fname)); + if(pData->pStrm == NULL) { + errmsg.LogError(0, RS_RET_NO_FILE_ACCESS, "Could no open output file '%s'", pData->f_fname); + } } } @@ -790,7 +783,6 @@ CODESTARTparseSelectorAct pData->fDirCreateMode = fDirCreateMode; pData->bCreateDirs = bCreateDirs; pData->bFailOnChown = bFailOnChown; - pData->bForceChown = bForceChown; pData->fileUID = fileUID; pData->fileGID = fileGID; pData->dirUID = dirUID; @@ -800,18 +792,6 @@ CODESTARTparseSelectorAct pData->iIOBufSize = (int) iIOBufSize; pData->iFlushInterval = iFlushInterval; pData->bUseAsyncWriter = bUseAsyncWriter; - - if(pData->bDynamicName == 0) { - /* try open and emit error message if not possible. At this stage, we ignore the - * return value of prepareFile, this is taken care of in later steps. - */ - prepareFile(pData, pData->f_fname); - - if(pData->pStrm == NULL) { - DBGPRINTF("Error opening log file: %s\n", pData->f_fname); - errmsg.LogError(0, RS_RET_NO_FILE_ACCESS, "Could no open output file '%s'", pData->f_fname); - } - } CODE_STD_FINALIZERparseSelectorAct ENDparseSelectorAct @@ -826,7 +806,6 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a dirUID = -1; dirGID = -1; bFailOnChown = 1; - bForceChown = DFLT_bForceChown; iDynaFileCacheSize = 10; fCreateMode = 0644; fDirCreateMode = 0700; @@ -901,7 +880,7 @@ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(omsdRegCFSLineHdlr((uchar *)"filecreatemode", 0, eCmdHdlrFileCreateMode, NULL, &fCreateMode, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"createdirs", 0, eCmdHdlrBinary, NULL, &bCreateDirs, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"failonchownfailure", 0, eCmdHdlrBinary, NULL, &bFailOnChown, STD_LOADABLE_MODULE_ID)); - CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileForceChown", 0, eCmdHdlrBinary, NULL, &bForceChown, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileforcechown", 0, eCmdHdlrBinary, goneAway, NULL, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionfileenablesync", 0, eCmdHdlrBinary, NULL, &bEnableSync, STD_LOADABLE_MODULE_ID)); CHKiRet(regCfSysLineHdlr((uchar *)"actionfiledefaulttemplate", 0, eCmdHdlrGetWord, NULL, &pszFileDfltTplName, NULL)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); -- cgit From 415b95cf453403f726f654cbc03ef3984446a870 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 26 Apr 2011 18:38:42 +0200 Subject: bugfix: pipes not opened in full priv mode when privs are to be dropped --- ChangeLog | 1 + tools/ompipe.c | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index f98057a6..d4fe37a6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,6 +6,7 @@ Version 5.9.0 [V5-DEVEL] (rgerhards), 2011-03-?? user and/or group. Note that it was long said that this "functionality" would break once we go for serious privilege drop code, so hopefully nobody still depends on it (and, if so, they lost...). +- bugfix: pipes not opened in full priv mode when privs are to be dropped - this begins a new devel branch for v5 - added support for user-level PRI provided via systemd - added new config directive $InputTCPFlowControl to select if tcp diff --git a/tools/ompipe.c b/tools/ompipe.c index 58725fb9..cbedb559 100644 --- a/tools/ompipe.c +++ b/tools/ompipe.c @@ -72,6 +72,7 @@ DEFobjCurrIf(errmsg) typedef struct _instanceData { uchar f_fname[MAXFNAME];/* pipe or template name (display only) */ short fd; /* pipe descriptor for (current) pipe */ + sbool bHadError; /* did we already have/report an error on this pipe? */ } instanceData; @@ -101,6 +102,17 @@ preparePipe(instanceData *pData) { DEFiRet; pData->fd = open((char*) pData->f_fname, O_RDWR|O_NONBLOCK|O_CLOEXEC); + if(pData->fd < 0 ) { + pData->fd = -1; + if(!pData->bHadError) { + char errStr[1024]; + rs_strerror_r(errno, errStr, sizeof(errStr)); + errmsg.LogError(0, RS_RET_NO_FILE_ACCESS, "Could no open output pipe '%s': %s", + pData->f_fname, errStr); + pData->bHadError = 1; + } + DBGPRINTF("Error opening log pipe: %s\n", pData->f_fname); + } RETiRet; } @@ -150,6 +162,7 @@ finalize_it: BEGINcreateInstance CODESTARTcreateInstance pData->fd = -1; + pData->bHadError = 0; ENDcreateInstance @@ -204,11 +217,6 @@ CODESTARTparseSelectorAct */ preparePipe(pData); - if(pData->fd < 0 ) { - pData->fd = -1; - DBGPRINTF("Error opening log pipe: %s\n", pData->f_fname); - errmsg.LogError(0, RS_RET_NO_FILE_ACCESS, "Could no open output pipe '%s'", pData->f_fname); - } CODE_STD_FINALIZERparseSelectorAct ENDparseSelectorAct -- cgit