diff --git a/0077-libmultipath-don-t-leak-memory-on-invalid-strings.patch b/0077-libmultipath-don-t-leak-memory-on-invalid-strings.patch new file mode 100644 index 0000000..07d0427 --- /dev/null +++ b/0077-libmultipath-don-t-leak-memory-on-invalid-strings.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Wed, 14 Dec 2022 15:38:19 -0600 +Subject: [PATCH] libmultipath: don't leak memory on invalid strings + +If set_path() or set_str_noslash() are called with a bad value, they +ignore it and continue to use the old value. But they weren't freeing +the bad value, causing a memory leak. + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +--- + libmultipath/dict.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/libmultipath/dict.c b/libmultipath/dict.c +index 46b9f225..861d1d17 100644 +--- a/libmultipath/dict.c ++++ b/libmultipath/dict.c +@@ -156,6 +156,7 @@ set_path(vector strvec, void *ptr, const char *file, int line_nr) + if ((*str_ptr)[0] != '/'){ + condlog(1, "%s line %d, %s is not an absolute path. Ignoring", + file, line_nr, *str_ptr); ++ free(*str_ptr); + *str_ptr = old_str; + } else + free(old_str); +@@ -176,6 +177,7 @@ set_str_noslash(vector strvec, void *ptr, const char *file, int line_nr) + if (strchr(*str_ptr, '/')) { + condlog(1, "%s line %d, %s cannot contain a slash. Ignoring", + file, line_nr, *str_ptr); ++ free(*str_ptr); + *str_ptr = old_str; + } else + free(old_str); diff --git a/0078-libmutipath-validate-the-argument-count-of-config-st.patch b/0078-libmutipath-validate-the-argument-count-of-config-st.patch new file mode 100644 index 0000000..d0b65e7 --- /dev/null +++ b/0078-libmutipath-validate-the-argument-count-of-config-st.patch @@ -0,0 +1,195 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Wed, 14 Dec 2022 15:38:20 -0600 +Subject: [PATCH] libmutipath: validate the argument count of config strings + +The features, path_selector, and hardware_handler config options pass +their strings directly into the kernel. If users omit the argument +counts from these strings, or use the wrong value, the kernel's table +parsing gets completely messed up, and the error messages it prints +don't reflect what actully went wrong. To avoid messing up the +kernel table parsing, verify that these strings correctly set the +argument count to the number of arguments they have. + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +--- + libmultipath/dict.c | 110 ++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 101 insertions(+), 9 deletions(-) + +diff --git a/libmultipath/dict.c b/libmultipath/dict.c +index 861d1d17..eb2f33a2 100644 +--- a/libmultipath/dict.c ++++ b/libmultipath/dict.c +@@ -142,6 +142,58 @@ set_dir(vector strvec, void *ptr, const char *file, int line_nr) + return 0; + } + ++static int ++set_arg_str(vector strvec, void *ptr, int count_idx, const char *file, ++ int line_nr) ++{ ++ char **str_ptr = (char **)ptr; ++ char *old_str = *str_ptr; ++ const char * const spaces = " \f\r\t\v"; ++ char *p, *end; ++ int idx = -1; ++ long int count = -1; ++ ++ *str_ptr = set_value(strvec); ++ if (!*str_ptr) { ++ free(old_str); ++ return 1; ++ } ++ p = *str_ptr; ++ while (*p != '\0') { ++ p += strspn(p, spaces); ++ if (*p == '\0') ++ break; ++ idx += 1; ++ if (idx == count_idx) { ++ errno = 0; ++ count = strtol(p, &end, 10); ++ if (errno == ERANGE || end == p || ++ !(isspace(*end) || *end == '\0')) { ++ count = -1; ++ break; ++ } ++ } ++ p += strcspn(p, spaces); ++ } ++ if (count < 0) { ++ condlog(1, "%s line %d, missing argument count for %s", ++ file, line_nr, (char*)VECTOR_SLOT(strvec, 0)); ++ goto fail; ++ } ++ if (count != idx - count_idx) { ++ condlog(1, "%s line %d, invalid argument count for %s:, got '%ld' expected '%d'", ++ file, line_nr, (char*)VECTOR_SLOT(strvec, 0), count, ++ idx - count_idx); ++ goto fail; ++ } ++ free(old_str); ++ return 0; ++fail: ++ free(*str_ptr); ++ *str_ptr = old_str; ++ return 0; ++} ++ + static int + set_path(vector strvec, void *ptr, const char *file, int line_nr) + { +@@ -294,6 +346,14 @@ def_ ## option ## _handler (struct config *conf, vector strvec, \ + return set_int(strvec, &conf->option, minval, maxval, file, line_nr); \ + } + ++#define declare_def_arg_str_handler(option, count_idx) \ ++static int \ ++def_ ## option ## _handler (struct config *conf, vector strvec, \ ++ const char *file, int line_nr) \ ++{ \ ++ return set_arg_str(strvec, &conf->option, count_idx, file, line_nr); \ ++} ++ + #define declare_def_snprint(option, function) \ + static int \ + snprint_def_ ## option (struct config *conf, struct strbuf *buff, \ +@@ -346,6 +406,17 @@ hw_ ## option ## _handler (struct config *conf, vector strvec, \ + return set_int(strvec, &hwe->option, minval, maxval, file, line_nr); \ + } + ++#define declare_hw_arg_str_handler(option, count_idx) \ ++static int \ ++hw_ ## option ## _handler (struct config *conf, vector strvec, \ ++ const char *file, int line_nr) \ ++{ \ ++ struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable); \ ++ if (!hwe) \ ++ return 1; \ ++ return set_arg_str(strvec, &hwe->option, count_idx, file, line_nr); \ ++} ++ + + #define declare_hw_snprint(option, function) \ + static int \ +@@ -377,6 +448,16 @@ ovr_ ## option ## _handler (struct config *conf, vector strvec, \ + file, line_nr); \ + } + ++#define declare_ovr_arg_str_handler(option, count_idx) \ ++static int \ ++ovr_ ## option ## _handler (struct config *conf, vector strvec, \ ++ const char *file, int line_nr) \ ++{ \ ++ if (!conf->overrides) \ ++ return 1; \ ++ return set_arg_str(strvec, &conf->overrides->option, count_idx, file, line_nr); \ ++} ++ + #define declare_ovr_snprint(option, function) \ + static int \ + snprint_ovr_ ## option (struct config *conf, struct strbuf *buff, \ +@@ -407,6 +488,17 @@ mp_ ## option ## _handler (struct config *conf, vector strvec, \ + return set_int(strvec, &mpe->option, minval, maxval, file, line_nr); \ + } + ++#define declare_mp_arg_str_handler(option, count_idx) \ ++static int \ ++mp_ ## option ## _handler (struct config *conf, vector strvec, \ ++ const char *file, int line_nr) \ ++{ \ ++ struct mpentry * mpe = VECTOR_LAST_SLOT(conf->mptable); \ ++ if (!mpe) \ ++ return 1; \ ++ return set_arg_str(strvec, &mpe->option, count_idx, file, line_nr); \ ++} ++ + #define declare_mp_snprint(option, function) \ + static int \ + snprint_mp_ ## option (struct config *conf, struct strbuf *buff, \ +@@ -591,13 +683,13 @@ snprint_def_marginal_pathgroups(struct config *conf, struct strbuf *buff, + } + + +-declare_def_handler(selector, set_str) ++declare_def_arg_str_handler(selector, 1) + declare_def_snprint_defstr(selector, print_str, DEFAULT_SELECTOR) +-declare_hw_handler(selector, set_str) ++declare_hw_arg_str_handler(selector, 1) + declare_hw_snprint(selector, print_str) +-declare_ovr_handler(selector, set_str) ++declare_ovr_arg_str_handler(selector, 1) + declare_ovr_snprint(selector, print_str) +-declare_mp_handler(selector, set_str) ++declare_mp_arg_str_handler(selector, 1) + declare_mp_snprint(selector, print_str) + + static int snprint_uid_attrs(struct config *conf, struct strbuf *buff, +@@ -672,13 +764,13 @@ declare_hw_snprint(prio_args, print_str) + declare_mp_handler(prio_args, set_str) + declare_mp_snprint(prio_args, print_str) + +-declare_def_handler(features, set_str) ++declare_def_arg_str_handler(features, 0) + declare_def_snprint_defstr(features, print_str, DEFAULT_FEATURES) +-declare_ovr_handler(features, set_str) ++declare_ovr_arg_str_handler(features, 0) + declare_ovr_snprint(features, print_str) +-declare_hw_handler(features, set_str) ++declare_hw_arg_str_handler(features, 0) + declare_hw_snprint(features, print_str) +-declare_mp_handler(features, set_str) ++declare_mp_arg_str_handler(features, 0) + declare_mp_snprint(features, print_str) + + declare_def_handler(checker_name, set_str) +@@ -1857,7 +1949,7 @@ declare_hw_snprint(revision, print_str) + declare_hw_handler(bl_product, set_str) + declare_hw_snprint(bl_product, print_str) + +-declare_hw_handler(hwhandler, set_str) ++declare_hw_arg_str_handler(hwhandler, 0) + declare_hw_snprint(hwhandler, print_str) + + /* diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index 2fa73b7..844e7d5 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,6 +1,6 @@ Name: device-mapper-multipath Version: 0.8.7 -Release: 16%{?dist} +Release: 17%{?dist} Summary: Tools to manage multipath devices using device-mapper License: GPLv2 URL: http://christophe.varoqui.free.fr/ @@ -86,6 +86,8 @@ Patch0073: 0073-libmultipath-prepare-proto_id-for-use-by-non-scsi-de.patch Patch0074: 0074-libmultipath-get-nvme-path-transport-protocol.patch Patch0075: 0075-libmultipath-enforce-queue_mode-bio-for-nmve-tcp-pat.patch Patch0076: 0076-multipath.conf-5-remove-io-affinity-information.patch +Patch0077: 0077-libmultipath-don-t-leak-memory-on-invalid-strings.patch +Patch0078: 0078-libmutipath-validate-the-argument-count-of-config-st.patch # runtime @@ -288,6 +290,11 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Wed Dec 21 2022 Benjamin Marzinski - 0.8.7-17 +- Add 0077-libmultipath-don-t-leak-memory-on-invalid-strings.patch +- Add 0078-libmutipath-validate-the-argument-count-of-config-st.patch +- Resolves: bz #2145225 + * Wed Nov 30 2022 Benjamin Marzinski - 0.8.7-16 - Add 0076-multipath.conf-5-remove-io-affinity-information.patch - Resolves: bz #2143125