Blame SOURCES/rsyslog-8.24.0-rhbz1427828-set-unset-not-checking-varName.patch

fde8c1
From e2767839bc23f1a2f70543efabfe0ca1be166ee9 Mon Sep 17 00:00:00 2001
fde8c1
From: Rainer Gerhards <rgerhards@adiscon.com>
fde8c1
Date: Tue, 24 Jan 2017 13:24:29 +0100
fde8c1
Subject: [PATCH] rainescript: set/unset statement do not check variable name
fde8c1
 validity
fde8c1
fde8c1
Only JSON-based variables can be use with set and unset. Unfortunately,
fde8c1
this restriction is not checked. If an invalid variable is given
fde8c1
(e.g. $invalid), this is not detected upon config processing on
fde8c1
startup. During execution phase, this can lead to a segfault, a
fde8c1
memory leak or other types of problems.
fde8c1
fde8c1
see also https://github.com/rsyslog/rsyslog/issues/1376
fde8c1
closes https://github.com/rsyslog/rsyslog/issues/1377
fde8c1
---
fde8c1
 grammar/rainerscript.c | 43 +++++++++++++++++++++++++++++++++++++++----
fde8c1
 1 file changed, 39 insertions(+), 4 deletions(-)
fde8c1
fde8c1
diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c
fde8c1
index 0ebd6f1..2106ef9 100644
fde8c1
--- a/grammar/rainerscript.c
fde8c1
+++ b/grammar/rainerscript.c
fde8c1
@@ -3062,6 +3062,19 @@ cnfstmtNew(unsigned s_type)
fde8c1
 	return cnfstmt;
fde8c1
 }
fde8c1
 
fde8c1
+/* This function disables a cnfstmt by setting it to NOP. This is
fde8c1
+ * useful when we detect errors late in the parsing processing, where
fde8c1
+ * we need to return a valid cnfstmt. The optimizer later removes the
fde8c1
+ * NOPs, so all is well.
fde8c1
+ * NOTE: this call assumes that no dynamic data structures have been
fde8c1
+ * allocated. If so, these MUST be freed before calling cnfstmtDisable().
fde8c1
+ */
fde8c1
+static void
fde8c1
+cnfstmtDisable(struct cnfstmt *cnfstmt)
fde8c1
+{
fde8c1
+	cnfstmt->nodetype = S_NOP;
fde8c1
+}
fde8c1
+
fde8c1
 void cnfstmtDestructLst(struct cnfstmt *root);
fde8c1
 
fde8c1
 static void cnfIteratorDestruct(struct cnfitr *itr);
fde8c1
@@ -3166,11 +3179,22 @@ cnfIteratorDestruct(struct cnfitr *itr)
fde8c1
 struct cnfstmt *
fde8c1
 cnfstmtNewSet(char *var, struct cnfexpr *expr, int force_reset)
fde8c1
 {
fde8c1
+	propid_t propid;
fde8c1
 	struct cnfstmt* cnfstmt;
fde8c1
 	if((cnfstmt = cnfstmtNew(S_SET)) != NULL) {
fde8c1
-		cnfstmt->d.s_set.varname = (uchar*) var;
fde8c1
-		cnfstmt->d.s_set.expr = expr;
fde8c1
-		cnfstmt->d.s_set.force_reset = force_reset;
fde8c1
+		if(propNameToID((uchar *)var, &propid) == RS_RET_OK
fde8c1
+		   && (   propid == PROP_CEE
fde8c1
+		       || propid == PROP_LOCAL_VAR
fde8c1
+		       || propid == PROP_GLOBAL_VAR)
fde8c1
+		   ) {
fde8c1
+			cnfstmt->d.s_set.varname = (uchar*) var;
fde8c1
+			cnfstmt->d.s_set.expr = expr;
fde8c1
+			cnfstmt->d.s_set.force_reset = force_reset;
fde8c1
+		} else {
fde8c1
+			parser_errmsg("invalid variable '%s' in set statement.", var);
fde8c1
+			free(var);
fde8c1
+			cnfstmtDisable(cnfstmt);
fde8c1
+		}
fde8c1
 	}
fde8c1
 	return cnfstmt;
fde8c1
 }
fde8c1
@@ -3254,9 +3278,20 @@ cnfstmtNewReloadLookupTable(struct cnffparamlst *fparams)
fde8c1
 struct cnfstmt *
fde8c1
 cnfstmtNewUnset(char *var)
fde8c1
 {
fde8c1
+	propid_t propid;
fde8c1
 	struct cnfstmt* cnfstmt;
fde8c1
 	if((cnfstmt = cnfstmtNew(S_UNSET)) != NULL) {
fde8c1
-		cnfstmt->d.s_unset.varname = (uchar*) var;
fde8c1
+		if(propNameToID((uchar *)var, &propid) == RS_RET_OK
fde8c1
+		   && (   propid == PROP_CEE
fde8c1
+		       || propid == PROP_LOCAL_VAR
fde8c1
+		       || propid == PROP_GLOBAL_VAR)
fde8c1
+		   ) {
fde8c1
+			cnfstmt->d.s_unset.varname = (uchar*) var;
fde8c1
+		} else {
fde8c1
+			parser_errmsg("invalid variable '%s' in unset statement.", var);
fde8c1
+			free(var);
fde8c1
+			cnfstmtDisable(cnfstmt);
fde8c1
+		}
fde8c1
 	}
fde8c1
 	return cnfstmt;
fde8c1
 }