summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2011-09-15 15:17:47 +0200
committerRainer Gerhards <rgerhards@adiscon.com>2011-09-15 15:17:47 +0200
commit1d0e4ba3b34464343c388ccef3ca8b08df42076a (patch)
treed17f746f7c8cb2f00aa3ab956740fd616e2390c0 /tools
parentb7e69a240037277e77685af5ea5623cdd89ec2d2 (diff)
parent11ee5cbdfb08ba3e42a853c08144fa24cd55d6da (diff)
downloadrsyslog-1d0e4ba3b34464343c388ccef3ca8b08df42076a.tar.gz
rsyslog-1d0e4ba3b34464343c388ccef3ca8b08df42076a.tar.xz
rsyslog-1d0e4ba3b34464343c388ccef3ca8b08df42076a.zip
Merge branch 'v4-stable' of git+ssh://git.adiscon.com/git/rsyslog into v4-stable
Diffstat (limited to 'tools')
-rw-r--r--tools/omfile.c39
-rw-r--r--tools/ompipe.c2
-rw-r--r--tools/syslogd.c88
3 files changed, 98 insertions, 31 deletions
diff --git a/tools/omfile.c b/tools/omfile.c
index 02418c46..88e8115e 100644
--- a/tools/omfile.c
+++ b/tools/omfile.c
@@ -89,11 +89,13 @@ 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 */
@@ -118,6 +120,7 @@ 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 */
+ bool bForceChown; /* force chown() on existing files? */
uid_t fileUID; /* IDs for creation */
uid_t dirUID;
gid_t fileGID;
@@ -163,8 +166,9 @@ CODESTARTdbgPrintInstInfo
dbgprintf("\tflush interval=%d\n", pData->iFlushInterval);
dbgprintf("\tfile cache size=%d\n", pData->iDynaFileCacheSize);
dbgprintf("\tcreate directories: %s\n", pData->bCreateDirs ? "yes" : "no");
- dbgprintf("\tfile owner %d, group %d\n", pData->fileUID, pData->fileGID);
- dbgprintf("\tdirectory owner %d, group %d\n", pData->dirUID, pData->dirGID);
+ 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);
dbgprintf("\tfail if owner/group can not be set: %s\n", pData->bFailOnChown ? "yes" : "no");
@@ -351,7 +355,22 @@ prepareFile(instanceData *pData, uchar *newFileName)
int fd;
DEFiRet;
- if(access((char*)newFileName, F_OK) != 0) {
+ 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 {
/* file does not exist, create it (and eventually parent directories */
if(pData->bCreateDirs) {
/* We first need to create parent dirs if they are missing.
@@ -371,7 +390,7 @@ prepareFile(instanceData *pData, uchar *newFileName)
pData->fCreateMode);
if(fd != -1) {
/* check and set uid/gid */
- if(pData->fileUID != (uid_t)-1 || pData->fileGID != (gid_t) -1) {
+ if(pData->bForceChown || 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) {
@@ -653,7 +672,14 @@ CODESTARTparseSelectorAct
*/
if(!strncmp((char*) p, ":omfile:", sizeof(":omfile:") - 1)) {
p += sizeof(":omfile:") - 1;
- }
+ } else {
+ if(*p == '$') {
+ errmsg.LogError(0, RS_RET_OUTDATED_STMT,
+ "action '%s' treated as ':omfile:%s' - please "
+ "change syntax, '%s' will not be supported in "
+ "rsyslog v6 and above.", p, p, p);
+ }
+ }
if(!(*p == '$' || *p == '?' || *p == '/' || *p == '.' || *p == '-'))
ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
@@ -731,6 +757,7 @@ CODESTARTparseSelectorAct
pData->fDirCreateMode = fDirCreateMode;
pData->bCreateDirs = bCreateDirs;
pData->bFailOnChown = bFailOnChown;
+ pData->bForceChown = bForceChown;
pData->fileUID = fileUID;
pData->fileGID = fileGID;
pData->dirUID = dirUID;
@@ -766,6 +793,7 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a
dirUID = -1;
dirGID = -1;
bFailOnChown = 1;
+ bForceChown = DFLT_bForceChown;
iDynaFileCacheSize = 10;
fCreateMode = 0644;
fDirCreateMode = 0700;
@@ -833,6 +861,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 *)"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));
diff --git a/tools/ompipe.c b/tools/ompipe.c
index 998a8f4a..1409287e 100644
--- a/tools/ompipe.c
+++ b/tools/ompipe.c
@@ -36,9 +36,11 @@
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
+#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
+#include <fcntl.h>
#include <unistd.h>
#include <sys/file.h>
diff --git a/tools/syslogd.c b/tools/syslogd.c
index ba27d08a..f66cbee3 100644
--- a/tools/syslogd.c
+++ b/tools/syslogd.c
@@ -254,11 +254,14 @@ int bDropTrailingLF = 1; /* drop trailing LF's on reception? */
int iCompatibilityMode = 0; /* version we should be compatible with; 0 means sysklogd. It is
the default, so if no -c<n> option is given, we make ourselvs
as compatible to sysklogd as possible. */
+#define DFLT_bLogStatusMsgs 1
+static int bLogStatusMsgs = DFLT_bLogStatusMsgs; /* log rsyslog start/stop/HUP messages? */
static int bDebugPrintTemplateList = 1;/* output template list in debug mode? */
static int bDebugPrintCfSysLineHandlerList = 1;/* output cfsyslinehandler list in debug mode? */
static int bDebugPrintModuleList = 1;/* output module list in debug mode? */
-uchar cCCEscapeChar = '\\';/* character to be used to start an escape sequence for control chars */
+uchar cCCEscapeChar = '#';/* character to be used to start an escape sequence for control chars */
int bEscapeCCOnRcv = 1; /* escape control characters on reception: 0 - no, 1 - yes */
+int bEscapeTab = 1; /* treat tab as escape control character: 0 - no, 1 - yes */
static int bErrMsgToStderr = 1; /* print error messages to stderr (in addition to everything else)? */
int bReduceRepeatMsgs; /* reduce repeated message - 0 - no, 1 - yes */
int bActExecWhenPrevSusp; /* execute action only when previous one was suspended? */
@@ -337,12 +340,14 @@ getFIOPName(unsigned iFIOP)
static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
{
cCCEscapeChar = '#';
+ bLogStatusMsgs = DFLT_bLogStatusMsgs;
bActExecWhenPrevSusp = 0;
iActExecOnceInterval = 0;
bDebugPrintTemplateList = 1;
bDebugPrintCfSysLineHandlerList = 1;
bDebugPrintModuleList = 1;
bEscapeCCOnRcv = 1; /* default is to escape control characters */
+ bEscapeTab = 1;
bReduceRepeatMsgs = 0;
free(pszMainMsgQFName);
pszMainMsgQFName = NULL;
@@ -371,7 +376,7 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a
/* hardcoded standard templates (used for defaults) */
-static uchar template_DebugFormat[] = "\"Debug line with all properties:\nFROMHOST: '%FROMHOST%', fromhost-ip: '%fromhost-ip%', HOSTNAME: '%HOSTNAME%', PRI: %PRI%,\nsyslogtag '%syslogtag%', programname: '%programname%', APP-NAME: '%APP-NAME%', PROCID: '%PROCID%', MSGID: '%MSGID%',\nTIMESTAMP: '%TIMESTAMP%', STRUCTURED-DATA: '%STRUCTURED-DATA%',\nmsg: '%msg%'\nescaped msg: '%msg:::drop-cc%'\nrawmsg: '%rawmsg%'\n\n\"";
+static uchar template_DebugFormat[] = "\"Debug line with all properties:\nFROMHOST: '%FROMHOST%', fromhost-ip: '%fromhost-ip%', HOSTNAME: '%HOSTNAME%', PRI: %PRI%,\nsyslogtag '%syslogtag%', programname: '%programname%', APP-NAME: '%APP-NAME%', PROCID: '%PROCID%', MSGID: '%MSGID%',\nTIMESTAMP: '%TIMESTAMP%', STRUCTURED-DATA: '%STRUCTURED-DATA%',\nmsg: '%msg%'\nescaped msg: '%msg:::drop-cc%'\ninputname: %inputname% rawmsg: '%rawmsg%'\n\n\"";
static uchar template_SyslogProtocol23Format[] = "\"<%PRI%>1 %TIMESTAMP:::date-rfc3339% %HOSTNAME% %APP-NAME% %PROCID% %MSGID% %STRUCTURED-DATA% %msg%\n\"";
static uchar template_TraditionalFileFormat[] = "\"%TIMESTAMP% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n\"";
static uchar template_FileFormat[] = "\"%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n\"";
@@ -809,7 +814,7 @@ parseAndSubmitMessage(uchar *hname, uchar *hnameIP, uchar *msg, int len, int fla
/* log an error? Very questionable... rgerhards, 2006-11-30 */
/* decided: we do not log an error, it won't help... rger, 2007-06-21 */
++pData;
- } else if(bEscapeCCOnRcv && iscntrl((int) *pData)) {
+ } else if(bEscapeCCOnRcv && iscntrl((int) *pData) && (*pData != '\t' || bEscapeTab)) {
/* we are configured to escape control characters. Please note
* that this most probably break non-western character sets like
* Japanese, Korean or Chinese. rgerhards, 2007-07-17
@@ -906,7 +911,7 @@ logmsgInternal(int iErr, int pri, uchar *msg, int flags)
* permits us to process unmodified config files which otherwise contain a
* supressor statement.
*/
- if(((Debug || NoFork) && bErrMsgToStderr) || iConfigVerify) {
+ if(((Debug == DEBUG_FULL || NoFork) && bErrMsgToStderr) || iConfigVerify) {
if(LOG_PRI(pri) == LOG_ERR)
fprintf(stderr, "rsyslogd: %s\n", msg);
}
@@ -1650,10 +1655,10 @@ static void doDie(int sig)
# define MSG1 "DoDie called.\n"
# define MSG2 "DoDie called 5 times - unconditional exit\n"
static int iRetries = 0; /* debug aid */
- if(Debug)
+ if(Debug == DEBUG_FULL)
write(1, MSG1, sizeof(MSG1) - 1);
if(iRetries++ == 4) {
- if(Debug)
+ if(Debug == DEBUG_FULL)
write(1, MSG2, sizeof(MSG2) - 1);
abort();
}
@@ -1719,7 +1724,7 @@ die(int sig)
thrdTerminateAll();
/* and THEN send the termination log message (see long comment above) */
- if (sig) {
+ if(sig && bLogStatusMsgs) {
(void) snprintf(buf, sizeof(buf) / sizeof(char),
" [origin software=\"rsyslogd\" " "swVersion=\"" VERSION \
"\" x-pid=\"%d\" x-info=\"http://www.rsyslog.com\"]" " exiting on signal %d.",
@@ -1840,6 +1845,9 @@ static rsRetVal setMaxFiles(void __attribute__((unused)) *pVal, int iFiles)
iFiles, errStr, (long) maxFiles.rlim_max);
ABORT_FINALIZE(RS_RET_ERR_RLIM_NOFILE);
}
+#ifdef USE_UNLIMITED_SELECT
+ glbl.SetFdSetSize(howmany(iFiles, __NFDBITS) * sizeof (fd_mask));
+#endif
DBGPRINTF("Max number of files set to %d [kernel max %ld].\n", iFiles, (long) maxFiles.rlim_max);
finalize_it:
@@ -2294,6 +2302,9 @@ init()
legacyOptsHook();
+ /* re-generate local host name property, as the config may have changed our FQDN settings */
+ glbl.GenerateLocalHostNameProperty();
+
/* we are now done with reading the configuration. This is the right time to
* free some objects that were just needed for loading it. rgerhards 2005-10-19
*/
@@ -2413,11 +2424,13 @@ init()
/* we now generate the startup message. It now includes everything to
* identify this instance. -- rgerhards, 2005-08-17
*/
- snprintf(bufStartUpMsg, sizeof(bufStartUpMsg)/sizeof(char),
- " [origin software=\"rsyslogd\" " "swVersion=\"" VERSION \
- "\" x-pid=\"%d\" x-info=\"http://www.rsyslog.com\"] (re)start",
- (int) myPid);
- logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, (uchar*)bufStartUpMsg, 0);
+ if(bLogStatusMsgs) {
+ snprintf(bufStartUpMsg, sizeof(bufStartUpMsg)/sizeof(char),
+ " [origin software=\"rsyslogd\" " "swVersion=\"" VERSION \
+ "\" x-pid=\"%d\" x-info=\"http://www.rsyslog.com\"] (re)start",
+ (int) myPid);
+ logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, (uchar*)bufStartUpMsg, 0);
+ }
memset(&sigAct, 0, sizeof (sigAct));
sigemptyset(&sigAct.sa_mask);
@@ -2448,6 +2461,25 @@ finalize_it:
}
+
+/* Put the rsyslog main thread to sleep for n seconds. This was introduced as
+ * a quick and dirty workaround for a privilege drop race in regard to listener
+ * startup, which itself was a result of the not-yet-done proper coding of
+ * privilege drop code (quite some effort). It may be useful for other occasions, too.
+ * is specified).
+ * rgerhards, 2009-06-12
+ */
+static rsRetVal
+putToSleep(void __attribute__((unused)) *pVal, int iNewVal)
+{
+ DEFiRet;
+ DBGPRINTF("rsyslog main thread put to sleep via $sleep %d directive...\n", iNewVal);
+ srSleep(iNewVal, 0);
+ DBGPRINTF("rsyslog main thread continues after $sleep %d\n", iNewVal);
+ RETiRet;
+}
+
+
/* Switch to either an already existing rule set or start a new one. The
* named rule set becomes the new "current" rule set (what means that new
* actions are added to it).
@@ -2566,12 +2598,14 @@ doHUP(void)
{
char buf[512];
- snprintf(buf, sizeof(buf) / sizeof(char),
- " [origin software=\"rsyslogd\" " "swVersion=\"" VERSION
- "\" x-pid=\"%d\" x-info=\"http://www.rsyslog.com\"] rsyslogd was HUPed, type '%s'.",
- (int) myPid, glbl.GetHUPisRestart() ? "restart" : "lightweight");
- errno = 0;
- logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, (uchar*)buf, 0);
+ if(bLogStatusMsgs) {
+ snprintf(buf, sizeof(buf) / sizeof(char),
+ " [origin software=\"rsyslogd\" " "swVersion=\"" VERSION
+ "\" x-pid=\"%d\" x-info=\"http://www.rsyslog.com\"] rsyslogd was HUPed, type '%s'.",
+ (int) myPid, glbl.GetHUPisRestart() ? "restart" : "lightweight");
+ errno = 0;
+ logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, (uchar*)buf, 0);
+ }
if(glbl.GetHUPisRestart()) {
DBGPRINTF("Received SIGHUP, configured to be restart, reloading rsyslogd.\n");
@@ -2695,9 +2729,11 @@ static rsRetVal loadBuildInModules(void)
* is that rsyslog will terminate if we can not register our built-in config commands.
* This, I think, is the right thing to do. -- rgerhards, 2007-07-31
*/
+ CHKiRet(regCfSysLineHdlr((uchar *)"logrsyslogstatusmessages", 0, eCmdHdlrBinary, NULL, &bLogStatusMsgs, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"actionresumeretrycount", 0, eCmdHdlrInt, NULL, &glbliActionResumeRetryCount, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"defaultruleset", 0, eCmdHdlrGetWord, setDefaultRuleset, NULL, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"ruleset", 0, eCmdHdlrGetWord, setCurrRuleset, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"sleep", 0, eCmdHdlrInt, putToSleep, NULL, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuefilename", 0, eCmdHdlrGetWord, NULL, &pszMainMsgQFName, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuesize", 0, eCmdHdlrInt, NULL, &iMainMsgQueueSize, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuehighwatermark", 0, eCmdHdlrInt, NULL, &iMainMsgQHighWtrMark, NULL));
@@ -2725,6 +2761,7 @@ static rsRetVal loadBuildInModules(void)
CHKiRet(regCfSysLineHdlr((uchar *)"actionresumeinterval", 0, eCmdHdlrInt, setActionResumeInterval, NULL, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"controlcharacterescapeprefix", 0, eCmdHdlrGetChar, NULL, &cCCEscapeChar, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"escapecontrolcharactersonreceive", 0, eCmdHdlrBinary, NULL, &bEscapeCCOnRcv, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"escapecontrolcharactertab", 0, eCmdHdlrBinary, NULL, &bEscapeTab, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"droptrailinglfonreception", 0, eCmdHdlrBinary, NULL, &bDropTrailingLF, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"template", 0, eCmdHdlrCustomHandler, conf.doNameLine, (void*)DIR_TEMPLATE, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"outchannel", 0, eCmdHdlrCustomHandler, conf.doNameLine, (void*)DIR_OUTCHANNEL, NULL));
@@ -2882,7 +2919,7 @@ static rsRetVal mainThread()
* is still in its infancy (and not really done), we currently accept this issue.
* rgerhards, 2009-06-29
*/
- if(!(Debug || NoFork)) {
+ if(!(Debug == DEBUG_FULL || NoFork)) {
close(1);
close(2);
bErrMsgToStderr = 0;
@@ -3073,7 +3110,7 @@ doGlblProcessInit(void)
thrdInit();
- if( !(Debug || NoFork) )
+ if( !(Debug == DEBUG_FULL || NoFork) )
{
DBGPRINTF("Checking pidfile.\n");
if (!check_pid(PidFile))
@@ -3172,6 +3209,7 @@ int realMain(int argc, char **argv)
uchar *LocalHostName;
uchar *LocalDomain;
uchar *LocalFQDNName;
+ char cwdbuf[128]; /* buffer to obtain/display current working directory */
/* first, parse the command line options. We do not carry out any actual work, just
* see what we should do. This relieves us from certain anomalies and we can process
@@ -3255,11 +3293,12 @@ int realMain(int argc, char **argv)
}
}
- if ((argc -= optind))
+ if(argc - optind)
usage();
- DBGPRINTF("rsyslogd %s startup, compatibility mode %d, module path '%s'\n",
- VERSION, iCompatibilityMode, glblModPath == NULL ? "" : (char*)glblModPath);
+ DBGPRINTF("rsyslogd %s startup, compatibility mode %d, module path '%s', cwd:%s\n",
+ VERSION, iCompatibilityMode, glblModPath == NULL ? "" : (char*)glblModPath,
+ getcwd(cwdbuf, sizeof(cwdbuf)));
/* we are done with the initial option parsing and processing. Now we init the system. */
@@ -3530,9 +3569,6 @@ int realMain(int argc, char **argv)
if(!iConfigVerify)
CHKiRet(doGlblProcessInit());
- /* re-generate local host name property, as the config may have changed our FQDN settings */
- glbl.GenerateLocalHostNameProperty();
-
CHKiRet(mainThread());
/* do any de-init's that need to be done AFTER this comment */