summaryrefslogtreecommitdiffstats
path: root/plugins/imuxsock/imuxsock.c
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2011-12-16 12:51:12 +0100
committerRainer Gerhards <rgerhards@adiscon.com>2011-12-16 12:51:12 +0100
commitb80b0672beb9b8b4d07791791bb9f2fb7c73889a (patch)
treeebed7e9f05e60a701710f7ce0dc6269982db90eb /plugins/imuxsock/imuxsock.c
parent3d75ffa1af11dc641cbdf35bea74a5928adc026c (diff)
parent01c7c9ffc6771f73df9ee0bc18e30534d6c6974c (diff)
downloadrsyslog-b80b0672beb9b8b4d07791791bb9f2fb7c73889a.tar.gz
rsyslog-b80b0672beb9b8b4d07791791bb9f2fb7c73889a.tar.xz
rsyslog-b80b0672beb9b8b4d07791791bb9f2fb7c73889a.zip
Merge branch 'v5-devel'
Conflicts: ChangeLog configure.ac doc/manual.html plugins/imuxsock/imuxsock.c runtime/modules.c
Diffstat (limited to 'plugins/imuxsock/imuxsock.c')
-rw-r--r--plugins/imuxsock/imuxsock.c166
1 files changed, 161 insertions, 5 deletions
diff --git a/plugins/imuxsock/imuxsock.c b/plugins/imuxsock/imuxsock.c
index cf4211e7..fa36a962 100644
--- a/plugins/imuxsock/imuxsock.c
+++ b/plugins/imuxsock/imuxsock.c
@@ -34,6 +34,7 @@
#include <string.h>
#include <errno.h>
#include <unistd.h>
+#include <fcntl.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <sys/socket.h>
@@ -140,6 +141,7 @@ typedef struct lstn_s {
sbool bParseHost; /* should parser parse host name? read-only after startup */
sbool bCreatePath; /* auto-creation of socket directory? */
sbool bUseCreds; /* pull original creator credentials from socket */
+ sbool bAnnotate; /* annotate events with trusted properties */
sbool bWritePid; /* write original PID into tag */
sbool bUseSysTimeStamp; /* use timestamp from system (instead of from message) */
} lstn_t;
@@ -176,6 +178,8 @@ static struct configSettings_s {
int ratelimitBurstSysSock;
int ratelimitSeverity;
int ratelimitSeveritySysSock;
+ int bAnnotate; /* annotate trusted properties */
+ int bAnnotateSysSock; /* same, for system log socket */
} cs;
struct instanceConf_s {
@@ -189,6 +193,7 @@ struct instanceConf_s {
int ratelimitInterval; /* interval in seconds, 0 = off */
int ratelimitBurst; /* max nbr of messages in interval */
int ratelimitSeverity;
+ int bAnnotate; /* annotate trusted properties */
struct instanceConf_s *next;
};
@@ -201,6 +206,7 @@ struct modConfData_s {
int ratelimitSeveritySysSock;
sbool bOmitLocalLogging;
sbool bWritePidSysSock;
+ int bAnnotateSysSock;
sbool bUseSysTimeStamp;
};
static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
@@ -325,6 +331,7 @@ static rsRetVal addInstance(void __attribute__((unused)) *pVal, uchar *pNewVal)
inst->bCreatePath = cs.bCreatePath;
inst->bUseSysTimeStamp = cs.bUseSysTimeStamp;
inst->bWritePid = cs.bWritePid;
+ inst->bAnnotate = cs.bAnnotate;
inst->next = NULL;
/* node created, let's add to config */
@@ -386,7 +393,8 @@ addListner(instanceConf_t *inst)
listeners[nfd].flags = inst->bIgnoreTimestamp ? IGNDATE : NOFLAG;
listeners[nfd].bCreatePath = inst->bCreatePath;
listeners[nfd].sockName = ustrdup(inst->sockName);
- listeners[nfd].bUseCreds = (inst->bWritePid || inst->ratelimitInterval) ? 1 : 0;
+ listeners[nfd].bUseCreds = (inst->bWritePid || inst->ratelimitInterval || inst->bAnnotate) ? 1 : 0;
+ listeners[nfd].bAnnotate = inst->bAnnotate;
listeners[nfd].bWritePid = inst->bWritePid;
listeners[nfd].bUseSysTimeStamp = inst->bUseSysTimeStamp;
nfd++;
@@ -509,6 +517,7 @@ openLogSocket(lstn_t *pLstn)
}
# else /* HAVE_SCM_CREDENTIALS */
pLstn->bUseCreds = 0;
+ pLstn->bAnnotate = 0;
# endif /* HAVE_SCM_CREDENTIALS */
finalize_it:
@@ -591,6 +600,103 @@ fixPID(uchar *bufTAG, int *lenTag, struct ucred *cred)
}
+/* Get an "trusted property" from the system. Returns an empty string if the
+ * property can not be obtained. Inspired by similiar functionality inside
+ * journald. Currently works with Linux /proc filesystem, only.
+ */
+static rsRetVal
+getTrustedProp(struct ucred *cred, char *propName, uchar *buf, size_t lenBuf, int *lenProp)
+{
+ int fd;
+ int i;
+ int lenRead;
+ char namebuf[1024];
+ DEFiRet;
+
+ if(snprintf(namebuf, sizeof(namebuf), "/proc/%lu/%s", (long unsigned) cred->pid,
+ propName) >= (int) sizeof(namebuf)) {
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ if((fd = open(namebuf, O_RDONLY)) == -1) {
+ DBGPRINTF("error reading '%s'\n", namebuf);
+ *lenProp = 0;
+ FINALIZE;
+ }
+ if((lenRead = read(fd, buf, lenBuf - 1)) == -1) {
+ DBGPRINTF("error reading file data for '%s'\n", namebuf);
+ *lenProp = 0;
+ close(fd);
+ FINALIZE;
+ }
+
+ /* we strip after the first \n */
+ for(i = 0 ; i < lenRead ; ++i) {
+ if(buf[i] == '\n')
+ break;
+ else if(iscntrl(buf[i]))
+ buf[i] = ' ';
+ }
+ buf[i] = '\0';
+ *lenProp = i;
+
+ close(fd);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* read the exe trusted property path (so far, /proc fs only)
+ */
+static rsRetVal
+getTrustedExe(struct ucred *cred, uchar *buf, size_t lenBuf, int* lenProp)
+{
+ int lenRead;
+ char namebuf[1024];
+ DEFiRet;
+
+ if(snprintf(namebuf, sizeof(namebuf), "/proc/%lu/exe", (long unsigned) cred->pid)
+ >= (int) sizeof(namebuf)) {
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ if((lenRead = readlink(namebuf, (char*)buf, lenBuf - 1)) == -1) {
+ DBGPRINTF("error reading link '%s'\n", namebuf);
+ *lenProp = 0;
+ FINALIZE;
+ }
+
+ buf[lenRead] = '\0';
+ *lenProp = lenRead;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* copy a trusted property in escaped mode. That is, the property can contain
+ * any character and so it must be properly quoted AND escaped.
+ * It is assumed the output buffer is large enough. Returns the number of
+ * characters added.
+ */
+static inline int
+copyescaped(uchar *dstbuf, uchar *inbuf, int inlen)
+{
+ int iDst, iSrc;
+
+ *dstbuf = '"';
+ for(iDst=1, iSrc=0 ; iSrc < inlen ; ++iDst, ++iSrc) {
+ if(inbuf[iSrc] == '"' || inbuf[iSrc] == '\\') {
+ dstbuf[iDst++] = '\\';
+ }
+ dstbuf[iDst] = inbuf[iSrc];
+ }
+ dstbuf[iDst++] = '"';
+ return iDst;
+}
+
+
/* submit received message to the queue engine
* We now parse the message according to expected format so that we
* can also mangle it if necessary.
@@ -610,6 +716,11 @@ SubmitMsg(uchar *pRcv, int lenRcv, lstn_t *pLstn, struct ucred *cred, struct tim
struct syslogTime st;
time_t tt;
rs_ratelimit_state_t *ratelimiter = NULL;
+ int lenProp;
+ uchar propBuf[1024];
+ uchar msgbuf[8192];
+ uchar *pmsgbuf;
+ int toffs; /* offset for trusted properties */
DEFiRet;
/* TODO: handle format errors?? */
@@ -647,6 +758,47 @@ SubmitMsg(uchar *pRcv, int lenRcv, lstn_t *pLstn, struct ucred *cred, struct tim
FINALIZE;
}
+ /* created trusted properties */
+ if(cred != NULL && pLstn->bAnnotate) {
+ if((unsigned) (lenRcv + 4096) < sizeof(msgbuf)) {
+ pmsgbuf = msgbuf;
+ } else {
+ CHKmalloc(pmsgbuf = malloc(lenRcv+4096));
+ }
+ memcpy(pmsgbuf, pRcv, lenRcv);
+ memcpy(pmsgbuf+lenRcv, " @[", 3);
+ toffs = lenRcv + 3; /* next free location */
+ lenProp = snprintf((char*)propBuf, sizeof(propBuf), "_PID=%lu _UID=%lu _GID=%lu",
+ (long unsigned) cred->pid, (long unsigned) cred->uid,
+ (long unsigned) cred->gid);
+ memcpy(pmsgbuf+toffs, propBuf, lenProp);
+ toffs = toffs + lenProp;
+ getTrustedProp(cred, "comm", propBuf, sizeof(propBuf), &lenProp);
+ if(lenProp) {
+ memcpy(pmsgbuf+toffs, " _COMM=", 7);
+ memcpy(pmsgbuf+toffs+7, propBuf, lenProp);
+ toffs = toffs + 7 + lenProp;
+ }
+ getTrustedExe(cred, propBuf, sizeof(propBuf), &lenProp);
+ if(lenProp) {
+ memcpy(pmsgbuf+toffs, " _EXE=", 6);
+ memcpy(pmsgbuf+toffs+6, propBuf, lenProp);
+ toffs = toffs + 6 + lenProp;
+ }
+ getTrustedProp(cred, "cmdline", propBuf, sizeof(propBuf), &lenProp);
+ if(lenProp) {
+ memcpy(pmsgbuf+toffs, " _CMDLINE=", 10);
+ toffs = toffs + 10 +
+ copyescaped(pmsgbuf+toffs+10, propBuf, lenProp);
+ }
+ /* finalize string */
+ pmsgbuf[toffs] = ']';
+ pmsgbuf[toffs+1] = '\0';
+ pRcv = pmsgbuf;
+ lenRcv = toffs + 1;
+ }
+
+
/* we now create our own message object and submit it to the queue */
CHKiRet(msgConstructWithTime(&pMsg, &st, tt));
MsgSetRawMsg(pMsg, (char*)pRcv, lenRcv);
@@ -777,14 +929,11 @@ static rsRetVal readSocket(lstn_t *pLstn)
cred = NULL;
ts = NULL;
if(pLstn->bUseCreds || pLstn->bUseSysTimeStamp) {
- dbgprintf("XXX: pre CM loop, length of control message %d\n", (int) msgh.msg_controllen);
for(cm = CMSG_FIRSTHDR(&msgh); cm; cm = CMSG_NXTHDR(&msgh, cm)) {
- dbgprintf("XXX: in CM loop, %d, %d\n", cm->cmsg_level, cm->cmsg_type);
# if HAVE_SCM_CREDENTIALS
if( pLstn->bUseCreds
&& cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_CREDENTIALS) {
cred = (struct ucred*) CMSG_DATA(cm);
- dbgprintf("XXX: got credentials pid %d\n", (int) cred->pid);
break;
}
# endif /* HAVE_SCM_CREDENTIALS */
@@ -798,7 +947,6 @@ static rsRetVal readSocket(lstn_t *pLstn)
}
# endif /* HAVE_SO_TIMESTAMP */
}
- dbgprintf("XXX: post CM loop\n");
}
CHKiRet(SubmitMsg(pRcv, iRcvd, pLstn, cred, ts));
} else if(iRcvd < 0 && errno != EINTR) {
@@ -850,6 +998,7 @@ activateListeners()
listeners[0].ratelimitSev = runModConf->ratelimitSeveritySysSock;
listeners[0].bUseCreds = (runModConf->bWritePidSysSock || runModConf->ratelimitIntervalSysSock) ? 1 : 0;
listeners[0].bWritePid = runModConf->bWritePidSysSock;
+ listeners[0].bAnnotate = runModConf->bAnnotateSysSock;
listeners[0].bUseSysTimeStamp = runModConf->bUseSysTimeStamp;
sd_fds = sd_listen_fds(0);
@@ -1075,6 +1224,8 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a
cs.bUseSysTimeStampSysSock = 1;
cs.bWritePid = 0;
cs.bWritePidSysSock = 0;
+ cs.bAnnotate = 0;
+ cs.bAnnotateSysSock = 0;
cs.bCreatePath = DFLT_bCreatePath;
cs.ratelimitInterval = DFLT_ratelimitInterval;
cs.ratelimitIntervalSysSock = DFLT_ratelimitInterval;
@@ -1118,6 +1269,7 @@ CODEmodInit_QueryRegCFSLineHdlr
listeners[0].fd = -1;
listeners[0].bParseHost = 0;
listeners[0].bUseCreds = 0;
+ listeners[0].bAnnotate = 0;
listeners[0].bCreatePath = 0;
listeners[0].bUseSysTimeStamp = 1;
@@ -1147,6 +1299,8 @@ CODEmodInit_QueryRegCFSLineHdlr
NULL, &cs.pLogHostName, STD_LOADABLE_MODULE_ID, eConfObjGlobal));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputunixlistensocketflowcontrol", 0, eCmdHdlrBinary,
NULL, &cs.bUseFlowCtl, STD_LOADABLE_MODULE_ID, eConfObjGlobal));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputunixlistensocketannotate", 0, eCmdHdlrBinary,
+ NULL, &cs.bAnnotate, STD_LOADABLE_MODULE_ID, eConfObjGlobal));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputunixlistensocketcreatepath", 0, eCmdHdlrBinary,
NULL, &cs.bCreatePath, STD_LOADABLE_MODULE_ID, eConfObjGlobal));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputunixlistensocketusesystimestamp", 0, eCmdHdlrBinary,
@@ -1175,6 +1329,8 @@ CODEmodInit_QueryRegCFSLineHdlr
setSystemLogFlowControl, NULL, STD_LOADABLE_MODULE_ID, eConfObjGlobal));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"systemlogusesystimestamp", 0, eCmdHdlrBinary,
NULL, &cs.bUseSysTimeStampSysSock, STD_LOADABLE_MODULE_ID, eConfObjGlobal));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"systemlogsocketannotate", 0, eCmdHdlrBinary,
+ NULL, &cs.bAnnotateSysSock, STD_LOADABLE_MODULE_ID, eConfObjGlobal));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"systemlogusepidfromsystem", 0, eCmdHdlrBinary,
NULL, &cs.bWritePidSysSock, STD_LOADABLE_MODULE_ID, eConfObjGlobal));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"systemlogratelimitinterval", 0, eCmdHdlrInt,