From 7e5ec859c8d6b972c4fafa873b22c30b927ec15f Mon Sep 17 00:00:00 2001
From: Tomas Heinrich <theinric@redhat.com>
Date: Fri, 12 Apr 2013 10:09:33 +0200
Subject: [PATCH] bugfix: prevent a segfault if ratelimit condition is not met

Move the severity-check logic inside the ratelimiter and add a new
function ratelimitSetSeverity() to manipulate the treshold.
Currently only utilized by the imuxsock module.
---
 plugins/imuxsock/imuxsock.c |    9 +++++----
 runtime/ratelimit.c         |   14 +++++++++++++-
 runtime/ratelimit.h         |    2 ++
 3 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/plugins/imuxsock/imuxsock.c b/plugins/imuxsock/imuxsock.c
index 0f4ded1..9553747 100644
--- a/plugins/imuxsock/imuxsock.c
+++ b/plugins/imuxsock/imuxsock.c
@@ -412,6 +412,8 @@ addListner(instanceConf_t *inst)
 		ratelimitSetLinuxLike(listeners[nfd].dflt_ratelimiter,
 				      listeners[nfd].ratelimitInterval,
 				      listeners[nfd].ratelimitBurst);
+		ratelimitSetSeverity(listeners[nfd].dflt_ratelimiter,
+				     listeners[nfd].ratelimitSev);
 		nfd++;
 	} else {
 		errmsg.LogError(0, NO_ERRCODE, "Out of unix socket name descriptors, ignoring %s\n",
@@ -586,6 +588,7 @@ findRatelimiter(lstn_t *pLstn, struct ucred *cred, ratelimit_t **prl)
 		pidbuf[sizeof(pidbuf)-1] = '\0'; /* to be on safe side */
 		CHKiRet(ratelimitNew(&rl, "imuxsock", pidbuf));
 		ratelimitSetLinuxLike(rl, pLstn->ratelimitInterval, pLstn->ratelimitBurst);
+		ratelimitSetSeverity(rl, pLstn->ratelimitSev);
 		CHKmalloc(keybuf = malloc(sizeof(pid_t)));
 		*keybuf = cred->pid;
 		r = hashtable_insert(pLstn->ht, keybuf, rl);
@@ -775,10 +778,7 @@ SubmitMsg(uchar *pRcv, int lenRcv, lstn_t *pLstn, struct ucred *cred, struct tim
 	facil = LOG_FAC(pri);
 	sever = LOG_PRI(pri);
 
-	if(sever >= pLstn->ratelimitSev) {
-		/* note: if cred == NULL, then ratelimiter == NULL as well! */
-		findRatelimiter(pLstn, cred, &ratelimiter); /* ignore error, better so than others... */
-	}
+	findRatelimiter(pLstn, cred, &ratelimiter); /* ignore error, better so than others... */
 
 	if(ts == NULL) {
 		datetime.getCurrTime(&st, &tt);
@@ -1075,6 +1075,7 @@ activateListeners()
 		ratelimitSetLinuxLike(listeners[0].dflt_ratelimiter,
 		listeners[0].ratelimitInterval,
 		listeners[0].ratelimitBurst);
+	ratelimitSetSeverity(listeners[0].dflt_ratelimiter,listeners[0].ratelimitSev);
 
 	sd_fds = sd_listen_fds(0);
 	if(sd_fds < 0) {
diff --git a/runtime/ratelimit.c b/runtime/ratelimit.c
index 4b618fb..d83da2d 100644
--- a/runtime/ratelimit.c
+++ b/runtime/ratelimit.c
@@ -202,7 +202,9 @@ ratelimitMsg(ratelimit_t *ratelimit, msg_t *pMsg, msg_t **ppRepMsg)
 	DEFiRet;
 
 	*ppRepMsg = NULL;
-	if(ratelimit->interval) {
+	/* Only the messages having severity level at or below the
+	 * treshold (the value is >=) are subject to ratelimiting. */
+	if(ratelimit->interval && (pMsg->iSeverity >= ratelimit->severity)) {
 		if(withinRatelimit(ratelimit, pMsg->ttGenTime) == 0) {
 			msgDestruct(&pMsg);
 			ABORT_FINALIZE(RS_RET_DISCARDMSG);
@@ -284,6 +286,7 @@ ratelimitNew(ratelimit_t **ppThis, char *modname, char *dynname)
 		namebuf[sizeof(namebuf)-1] = '\0'; /* to be on safe side */
 		pThis->name = strdup(namebuf);
 	}
+	/* pThis->severity == 0 - all messages are ratelimited */
 	pThis->bReduceRepeatMsgs = loadConf->globals.bReduceRepeatMsgs;
 	*ppThis = pThis;
 finalize_it:
@@ -316,6 +319,15 @@ ratelimitSetThreadSafe(ratelimit_t *ratelimit)
 	pthread_mutex_init(&ratelimit->mut, NULL);
 }
 
+/* Severity level determines which messages are subject to
+ * ratelimiting. Default (no value set) is all messages.
+ */
+void
+ratelimitSetSeverity(ratelimit_t *ratelimit, intTiny severity)
+{
+	ratelimit->severity = severity;
+}
+
 void
 ratelimitDestruct(ratelimit_t *ratelimit)
 {
diff --git a/runtime/ratelimit.h b/runtime/ratelimit.h
index 820817b..a058b06 100644
--- a/runtime/ratelimit.h
+++ b/runtime/ratelimit.h
@@ -26,6 +26,7 @@ struct ratelimit_s {
 	/* support for Linux kernel-type ratelimiting */
 	unsigned short interval;
 	unsigned short burst;
+	intTiny severity; /**< ratelimit only equal or lower severity levels (eq or higher values) */
 	unsigned done;
 	unsigned missed;
 	time_t begin;
@@ -41,6 +42,7 @@ struct ratelimit_s {
 rsRetVal ratelimitNew(ratelimit_t **ppThis, char *modname, char *dynname);
 void ratelimitSetThreadSafe(ratelimit_t *ratelimit);
 void ratelimitSetLinuxLike(ratelimit_t *ratelimit, unsigned short interval, unsigned short burst);
+void ratelimitSetSeverity(ratelimit_t *ratelimit, intTiny severity);
 rsRetVal ratelimitMsg(ratelimit_t *ratelimit, msg_t *pMsg, msg_t **ppRep);
 rsRetVal ratelimitAddMsg(ratelimit_t *ratelimit, multi_submit_t *pMultiSub, msg_t *pMsg);
 void ratelimitDestruct(ratelimit_t *pThis);
-- 
1.7.10.4