Blame SOURCES/0128-libmutipath-validate-the-argument-count-of-config-st.patch

8b67ad
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
8b67ad
From: Benjamin Marzinski <bmarzins@redhat.com>
8b67ad
Date: Wed, 14 Dec 2022 15:38:20 -0600
8b67ad
Subject: [PATCH] libmutipath: validate the argument count of config strings
8b67ad
8b67ad
The features, path_selector, and hardware_handler config options pass
8b67ad
their strings directly into the kernel.  If users omit the argument
8b67ad
counts from these strings, or use the wrong value, the kernel's table
8b67ad
parsing gets completely messed up, and the error messages it prints
8b67ad
don't reflect what actully went wrong. To avoid messing up the
8b67ad
kernel table parsing, verify that these strings correctly set the
8b67ad
argument count to the number of arguments they have.
8b67ad
8b67ad
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
8b67ad
Reviewed-by: Martin Wilck <mwilck@suse.com>
8b67ad
---
8b67ad
 libmultipath/dict.c | 110 ++++++++++++++++++++++++++++++++++++++++----
8b67ad
 1 file changed, 101 insertions(+), 9 deletions(-)
8b67ad
8b67ad
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
8b67ad
index a8c9e989..952b33d0 100644
8b67ad
--- a/libmultipath/dict.c
8b67ad
+++ b/libmultipath/dict.c
8b67ad
@@ -155,6 +155,58 @@ set_dir(vector strvec, void *ptr, const char *file, int line_nr)
8b67ad
 	return 0;
8b67ad
 }
8b67ad
 
8b67ad
+static int
8b67ad
+set_arg_str(vector strvec, void *ptr, int count_idx, const char *file,
8b67ad
+	    int line_nr)
8b67ad
+{
8b67ad
+	char **str_ptr = (char **)ptr;
8b67ad
+	char *old_str = *str_ptr;
8b67ad
+	const char * const spaces = " \f\r\t\v";
8b67ad
+	char *p, *end;
8b67ad
+	int idx = -1;
8b67ad
+	long int count = -1;
8b67ad
+
8b67ad
+	*str_ptr = set_value(strvec);
8b67ad
+	if (!*str_ptr) {
8b67ad
+		free(old_str);
8b67ad
+		return 1;
8b67ad
+	}
8b67ad
+	p = *str_ptr;
8b67ad
+	while (*p != '\0') {
8b67ad
+		p += strspn(p, spaces);
8b67ad
+		if (*p == '\0')
8b67ad
+			break;
8b67ad
+		idx += 1;
8b67ad
+		if (idx == count_idx) {
8b67ad
+			errno = 0;
8b67ad
+			count = strtol(p, &end, 10);
8b67ad
+			if (errno == ERANGE || end == p ||
8b67ad
+			    !(isspace(*end) || *end == '\0')) {
8b67ad
+				count = -1;
8b67ad
+				break;
8b67ad
+			}
8b67ad
+		}
8b67ad
+		p += strcspn(p, spaces);
8b67ad
+	}
8b67ad
+	if (count < 0) {
8b67ad
+		condlog(1, "%s line %d, missing argument count for %s",
8b67ad
+			file, line_nr, (char*)VECTOR_SLOT(strvec, 0));
8b67ad
+		goto fail;
8b67ad
+	}
8b67ad
+	if (count != idx - count_idx) {
8b67ad
+		condlog(1, "%s line %d, invalid argument count for %s:, got '%ld' expected '%d'",
8b67ad
+			file, line_nr, (char*)VECTOR_SLOT(strvec, 0), count,
8b67ad
+			idx - count_idx);
8b67ad
+		goto fail;
8b67ad
+	}
8b67ad
+	free(old_str);
8b67ad
+	return 0;
8b67ad
+fail:
8b67ad
+	free(*str_ptr);
8b67ad
+	*str_ptr = old_str;
8b67ad
+	return 0;
8b67ad
+}
8b67ad
+
8b67ad
 static int
8b67ad
 set_path(vector strvec, void *ptr, const char *file, int line_nr)
8b67ad
 {
8b67ad
@@ -337,6 +389,14 @@ def_ ## option ## _handler (struct config *conf, vector strvec,         \
8b67ad
 	return set_int(strvec, &conf->option, minval, maxval, file, line_nr); \
8b67ad
 }
8b67ad
 
8b67ad
+#define declare_def_arg_str_handler(option, count_idx)			\
8b67ad
+static int								\
8b67ad
+def_ ## option ## _handler (struct config *conf, vector strvec,		\
8b67ad
+			    const char *file, int line_nr)		\
8b67ad
+{									\
8b67ad
+	return set_arg_str(strvec, &conf->option, count_idx, file, line_nr); \
8b67ad
+}
8b67ad
+
8b67ad
 #define declare_def_snprint(option, function)				\
8b67ad
 static int								\
8b67ad
 snprint_def_ ## option (struct config *conf, char * buff, int len,	\
8b67ad
@@ -389,6 +449,17 @@ hw_ ## option ## _handler (struct config *conf, vector strvec,		\
8b67ad
 	return set_int(strvec, &hwe->option, minval, maxval, file, line_nr); \
8b67ad
 }
8b67ad
 
8b67ad
+#define declare_hw_arg_str_handler(option, count_idx)			\
8b67ad
+static int								\
8b67ad
+hw_ ## option ## _handler (struct config *conf, vector strvec,		\
8b67ad
+			    const char *file, int line_nr)		\
8b67ad
+{									\
8b67ad
+	struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable);		\
8b67ad
+	if (!hwe)							\
8b67ad
+		return 1;						\
8b67ad
+	return set_arg_str(strvec, &hwe->option, count_idx, file, line_nr); \
8b67ad
+}
8b67ad
+
8b67ad
 
8b67ad
 #define declare_hw_snprint(option, function)				\
8b67ad
 static int								\
8b67ad
@@ -420,6 +491,16 @@ ovr_ ## option ## _handler (struct config *conf, vector strvec,		\
8b67ad
 		       file, line_nr); \
8b67ad
 }
8b67ad
 
8b67ad
+#define declare_ovr_arg_str_handler(option, count_idx)			\
8b67ad
+static int								\
8b67ad
+ovr_ ## option ## _handler (struct config *conf, vector strvec,		\
8b67ad
+			    const char *file, int line_nr)		\
8b67ad
+{									\
8b67ad
+	if (!conf->overrides)						\
8b67ad
+		return 1;						\
8b67ad
+	return set_arg_str(strvec, &conf->overrides->option, count_idx, file, line_nr); \
8b67ad
+}
8b67ad
+
8b67ad
 #define declare_ovr_snprint(option, function)				\
8b67ad
 static int								\
8b67ad
 snprint_ovr_ ## option (struct config *conf, char * buff, int len,	\
8b67ad
@@ -450,6 +531,17 @@ mp_ ## option ## _handler (struct config *conf, vector strvec,		\
8b67ad
 	return set_int(strvec, &mpe->option, minval, maxval, file, line_nr); \
8b67ad
 }
8b67ad
 
8b67ad
+#define declare_mp_arg_str_handler(option, count_idx)			\
8b67ad
+static int								\
8b67ad
+mp_ ## option ## _handler (struct config *conf, vector strvec,		\
8b67ad
+			    const char *file, int line_nr)		\
8b67ad
+{									\
8b67ad
+	struct mpentry * mpe = VECTOR_LAST_SLOT(conf->mptable);		\
8b67ad
+	if (!mpe)							\
8b67ad
+		return 1;						\
8b67ad
+	return set_arg_str(strvec, &mpe->option, count_idx, file, line_nr); \
8b67ad
+}
8b67ad
+
8b67ad
 #define declare_mp_snprint(option, function)				\
8b67ad
 static int								\
8b67ad
 snprint_mp_ ## option (struct config *conf, char * buff, int len,	\
8b67ad
@@ -634,13 +726,13 @@ snprint_def_marginal_pathgroups(struct config *conf, char *buff, int len,
8b67ad
 }
8b67ad
 
8b67ad
 
8b67ad
-declare_def_handler(selector, set_str)
8b67ad
+declare_def_arg_str_handler(selector, 1)
8b67ad
 declare_def_snprint_defstr(selector, print_str, DEFAULT_SELECTOR)
8b67ad
-declare_hw_handler(selector, set_str)
8b67ad
+declare_hw_arg_str_handler(selector, 1)
8b67ad
 declare_hw_snprint(selector, print_str)
8b67ad
-declare_ovr_handler(selector, set_str)
8b67ad
+declare_ovr_arg_str_handler(selector, 1)
8b67ad
 declare_ovr_snprint(selector, print_str)
8b67ad
-declare_mp_handler(selector, set_str)
8b67ad
+declare_mp_arg_str_handler(selector, 1)
8b67ad
 declare_mp_snprint(selector, print_str)
8b67ad
 
8b67ad
 static int snprint_uid_attrs(struct config *conf, char *buff, int len,
8b67ad
@@ -717,13 +809,13 @@ declare_hw_snprint(prio_args, print_str)
8b67ad
 declare_mp_handler(prio_args, set_str)
8b67ad
 declare_mp_snprint(prio_args, print_str)
8b67ad
 
8b67ad
-declare_def_handler(features, set_str)
8b67ad
+declare_def_arg_str_handler(features, 0)
8b67ad
 declare_def_snprint_defstr(features, print_str, DEFAULT_FEATURES)
8b67ad
-declare_ovr_handler(features, set_str)
8b67ad
+declare_ovr_arg_str_handler(features, 0)
8b67ad
 declare_ovr_snprint(features, print_str)
8b67ad
-declare_hw_handler(features, set_str)
8b67ad
+declare_hw_arg_str_handler(features, 0)
8b67ad
 declare_hw_snprint(features, print_str)
8b67ad
-declare_mp_handler(features, set_str)
8b67ad
+declare_mp_arg_str_handler(features, 0)
8b67ad
 declare_mp_snprint(features, print_str)
8b67ad
 
8b67ad
 declare_def_handler(checker_name, set_str)
8b67ad
@@ -1894,7 +1986,7 @@ declare_hw_snprint(revision, print_str)
8b67ad
 declare_hw_handler(bl_product, set_regex)
8b67ad
 declare_hw_snprint(bl_product, print_str)
8b67ad
 
8b67ad
-declare_hw_handler(hwhandler, set_str)
8b67ad
+declare_hw_arg_str_handler(hwhandler, 0)
8b67ad
 declare_hw_snprint(hwhandler, print_str)
8b67ad
 
8b67ad
 /*