Blob Blame History Raw
From 0d7a31540b25b2942ae35dd3c62d9ee33020a157 Mon Sep 17 00:00:00 2001
From: Tomas Heinrich <theinric@redhat.com>
Date: Tue, 7 Oct 2014 10:24:06 +0200
Subject: [PATCH] fix CVE-2014-3634

See the following links for details:
https://access.redhat.com/security/cve/CVE-2014-3634
http://www.rsyslog.com/remote-syslog-pri-vulnerability/
---
 grammar/rainerscript.h  |  4 +--
 runtime/msg.c           | 33 ++++++++++++++++---------
 runtime/parser.c        | 13 ++++++----
 runtime/rsyslog.h       | 66 ++++++++++++++++++++++++++++++++++++++++---------
 runtime/srutils.c       |  1 +
 runtime/syslogd-types.h |  3 ---
 6 files changed, 88 insertions(+), 32 deletions(-)

diff --git a/grammar/rainerscript.h b/grammar/rainerscript.h
index 0657330..52050e4 100644
--- a/grammar/rainerscript.h
+++ b/grammar/rainerscript.h
@@ -7,8 +7,8 @@
 #include <regex.h>
 #include "typedefs.h"
 
-
-#define	LOG_NFACILITIES	24	/* current number of syslog facilities */
+#define	LOG_NFACILITIES	24+1	/* This is a dupe from rsyslog.h, but we can't include it as
+				   I don't know how to get hold of that damn off64_t data type... */
 #define CNFFUNC_MAX_ARGS 32
 	/**< maximum number of arguments that any function can have (among
 	 *   others, this is used to size data structures).
diff --git a/runtime/msg.c b/runtime/msg.c
index 10ecf48..abb58c9 100644
--- a/runtime/msg.c
+++ b/runtime/msg.c
@@ -90,7 +90,7 @@ static char *two_digits[100] = {
 static struct {
 	uchar *pszName;
 	short lenName;
-} syslog_pri_names[192] = {
+} syslog_pri_names[200] = {
 	{ UCHAR_CONSTANT("0"), 3},
 	{ UCHAR_CONSTANT("1"), 3},
 	{ UCHAR_CONSTANT("2"), 3},
@@ -282,22 +282,30 @@ static struct {
 	{ UCHAR_CONSTANT("188"), 5},
 	{ UCHAR_CONSTANT("189"), 5},
 	{ UCHAR_CONSTANT("190"), 5},
-	{ UCHAR_CONSTANT("191"), 5}
+	{ UCHAR_CONSTANT("191"), 5},
+	{ UCHAR_CONSTANT("192"), 5},
+	{ UCHAR_CONSTANT("193"), 5},
+	{ UCHAR_CONSTANT("194"), 5},
+	{ UCHAR_CONSTANT("195"), 5},
+	{ UCHAR_CONSTANT("196"), 5},
+	{ UCHAR_CONSTANT("197"), 5},
+	{ UCHAR_CONSTANT("198"), 5},
+	{ UCHAR_CONSTANT("199"), 5},
 	};
 static char hexdigit[16] =
 	{'0', '1', '2', '3', '4', '5', '6', '7', '8',
 	 '9', 'A', 'B', 'C', 'D', 'E', 'F' };
 
 /*syslog facility names (as of RFC5424) */
-static char *syslog_fac_names[24] = { "kern", "user", "mail", "daemon", "auth", "syslog", "lpr",
+static char *syslog_fac_names[LOG_NFACILITIES] = { "kern", "user", "mail", "daemon", "auth", "syslog", "lpr",
 			    	      "news", "uucp", "cron", "authpriv", "ftp", "ntp", "audit",
 			    	      "alert", "clock", "local0", "local1", "local2", "local3",
-			    	      "local4", "local5", "local6", "local7" };
+			    	      "local4", "local5", "local6", "local7", "invld" };
 /* length of the facility names string (for optimizatiions) */
-static short len_syslog_fac_names[24] = { 4, 4, 4, 6, 4, 6, 3,
+static short len_syslog_fac_names[LOG_NFACILITIES] = { 4, 4, 4, 6, 4, 6, 3,
 			    	          4, 4, 4, 8, 3, 3, 5,
 			    	          5, 5, 6, 6, 6, 6,
-			    	          6, 6, 6, 6 };
+			    	          6, 6, 6, 6, 5 };
 
 /* table of severity names (in numerical order)*/
 static char *syslog_severity_names[8] = { "emerg", "alert", "crit", "err", "warning", "notice", "info", "debug" };
@@ -307,8 +315,8 @@ static short len_syslog_severity_names[8] = { 5, 5, 4, 3, 7, 6, 4, 5 };
  * and facility values to a numerical string... -- rgerhars, 2009-06-17
  */
 
-static char *syslog_number_names[24] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14",
-					 "15", "16", "17", "18", "19", "20", "21", "22", "23" };
+static char *syslog_number_names[LOG_NFACILITIES] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14",
+					 "15", "16", "17", "18", "19", "20", "21", "22", "23", "24" };
 
 /* global variables */
 #if defined(HAVE_MALLOC_TRIM) && !defined(HAVE_ATOMIC_BUILTINS)
@@ -678,8 +686,8 @@ static inline rsRetVal msgBaseConstruct(msg_t **ppThis)
 	pM->flowCtlType = 0;
 	pM->bParseSuccess = 0;
 	pM->iRefCount = 1;
-	pM->iSeverity = -1;
-	pM->iFacility = -1;
+	pM->iSeverity = LOG_DEBUG;
+	pM->iFacility = LOG_INVLD;
 	pM->iLenPROGNAME = -1;
 	pM->offAfterPRI = 0;
 	pM->offMSG = -1;
@@ -1499,7 +1507,10 @@ uchar *getMSG(msg_t *pM)
 /* Get PRI value as integer */
 static int getPRIi(msg_t *pM)
 {
-	return (pM->iFacility << 3) + (pM->iSeverity);
+	unsigned pri = (pM->iFacility << 3) + (pM->iSeverity);
+	if(pri > LOG_MAXPRI)
+		pri = LOG_PRI_INVLD;
+	return pri;
 }
 
 
diff --git a/runtime/parser.c b/runtime/parser.c
index 74b28f4..e708b33 100644
--- a/runtime/parser.c
+++ b/runtime/parser.c
@@ -444,7 +444,7 @@ finalize_it:
 static inline rsRetVal
 ParsePRI(msg_t *pMsg)
 {
-	int pri;
+	unsigned pri;
 	uchar *msg;
 	int lenMsg;
 	DEFiRet;
@@ -463,13 +463,16 @@ ParsePRI(msg_t *pMsg)
 			 * but it offers us performance...
 			 */
 			pri = 0;
-			while(--lenMsg > 0 && isdigit((int) *++msg)) {
+			while(--lenMsg > 0 && isdigit((int) *++msg) && pri <= LOG_MAXPRI) {
 				pri = 10 * pri + (*msg - '0');
 			}
-			if(*msg == '>')
+			if(*msg == '>') {
 				++msg;
-			if(pri & ~(LOG_FACMASK|LOG_PRIMASK))
-				pri = DEFUPRI;
+			} else {
+				pri = LOG_PRI_INVLD;
+			}
+			if(pri > LOG_MAXPRI)
+				pri = LOG_PRI_INVLD;
 		}
 		pMsg->iFacility = LOG_FAC(pri);
 		pMsg->iSeverity = LOG_PRI(pri);
diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h
index e62ba86..37c4b1b 100644
--- a/runtime/rsyslog.h
+++ b/runtime/rsyslog.h
@@ -76,19 +76,63 @@
  * #                  End Config Settings                      # *
  * ############################################################# */
 
-/* portability: not all platforms have these defines, so we
- * define them here if they are missing. -- rgerhards, 2008-03-04
+/* make sure we uses consistent macros, no matter what the
+ * platform gives us.
  */
-#ifndef LOG_MAKEPRI
-#	define	LOG_MAKEPRI(fac, pri)	(((fac) << 3) | (pri))
-#endif
-#ifndef LOG_PRI
-#	define	LOG_PRI(p)	((p) & LOG_PRIMASK)
-#endif
-#ifndef LOG_FAC
-#	define	LOG_FAC(p)	(((p) & LOG_FACMASK) >> 3)
-#endif
+#define LOG_NFACILITIES 24+1 /* plus one for our special "invld" facility! */
+#define LOG_MAXPRI 191	/* highest supported valid PRI value --> RFC3164, RFC5424 */
+#undef LOG_MAKEPRI
+#define LOG_PRI_INVLD	(LOG_INVLD|LOG_DEBUG)	/* PRI is invalid --> special "invld.=debug" PRI code (rsyslog-specific) */
+
+#define	LOG_EMERG	0	/* system is unusable */
+#define	LOG_ALERT	1	/* action must be taken immediately */
+#define	LOG_CRIT	2	/* critical conditions */
+#define	LOG_ERR		3	/* error conditions */
+#define	LOG_WARNING	4	/* warning conditions */
+#define	LOG_NOTICE	5	/* normal but significant condition */
+#define	LOG_INFO	6	/* informational */
+#define	LOG_DEBUG	7	/* debug-level messages */
+
+#define	LOG_KERN	(0<<3)	/* kernel messages */
+#define	LOG_USER	(1<<3)	/* random user-level messages */
+#define	LOG_MAIL	(2<<3)	/* mail system */
+#define	LOG_DAEMON	(3<<3)	/* system daemons */
+#define	LOG_AUTH	(4<<3)	/* security/authorization messages */
+#define	LOG_SYSLOG	(5<<3)	/* messages generated internally by syslogd */
+#define	LOG_LPR		(6<<3)	/* line printer subsystem */
+#define	LOG_NEWS	(7<<3)	/* network news subsystem */
+#define	LOG_UUCP	(8<<3)	/* UUCP subsystem */
+#define	LOG_CRON	(9<<3)	/* clock daemon */
+#define	LOG_AUTHPRIV	(10<<3)	/* security/authorization messages (private) */
+#define	LOG_FTP		(11<<3)	/* ftp daemon */
+#define	LOG_LOCAL0	(16<<3)	/* reserved for local use */
+#define	LOG_LOCAL1	(17<<3)	/* reserved for local use */
+#define	LOG_LOCAL2	(18<<3)	/* reserved for local use */
+#define	LOG_LOCAL3	(19<<3)	/* reserved for local use */
+#define	LOG_LOCAL4	(20<<3)	/* reserved for local use */
+#define	LOG_LOCAL5	(21<<3)	/* reserved for local use */
+#define	LOG_LOCAL6	(22<<3)	/* reserved for local use */
+#define	LOG_LOCAL7	(23<<3)	/* reserved for local use */
+#define LOG_FAC_INVLD   24
+#define	LOG_INVLD	(LOG_FAC_INVLD<<3)	/* invalid facility/PRI code */
+
+/* we need to use a function to avoid side-effects. This MUST guard
+ * against invalid facility values. rgerhards, 2014-09-16
+ */
+static inline int pri2fac(const int pri)
+{
+	unsigned fac = pri >> 3;
+	return (fac > 23) ? LOG_FAC_INVLD : fac;
+}
+
+#define LOG_FAC(x) pri2fac(x)
+
+static inline int pri2sev(const int pri)
+{
+	return pri & 0x07;
+}
 
+#define LOG_PRI(x) pri2sev(x)
 
 /* the rsyslog core provides information about present feature to plugins
  * asking it. Below are feature-test macros which must be used to query
diff --git a/runtime/srutils.c b/runtime/srutils.c
index 6a509b4..4f9f6c1 100644
--- a/runtime/srutils.c
+++ b/runtime/srutils.c
@@ -103,6 +103,7 @@ syslogName_t	syslogFacNames[] = {
 	{"local5",       LOG_LOCAL5},
 	{"local6",       LOG_LOCAL6},
 	{"local7",       LOG_LOCAL7},
+	{"invld",        LOG_INVLD},
 	{NULL,           -1},
 };
 
diff --git a/runtime/syslogd-types.h b/runtime/syslogd-types.h
index 6947a11..8aee425 100644
--- a/runtime/syslogd-types.h
+++ b/runtime/syslogd-types.h
@@ -27,9 +27,6 @@
 
 #include "stringbuf.h"
 #include <sys/param.h>
-#if HAVE_SYSLOG_H
-#include <syslog.h>
-#endif
 
 /* we use RSTRUE/FALSE to prevent name claches with other packages */
 #define RSFALSE 0
-- 
1.9.3