diff --git a/6016-Fix-possible-NULL-ptr-dereferences-and-memory-leaks.patch b/6016-Fix-possible-NULL-ptr-dereferences-and-memory-leaks.patch new file mode 100644 index 0000000000000000000000000000000000000000..b6acb7e7c4e3f25aea853a8c321e6db52e073a41 --- /dev/null +++ b/6016-Fix-possible-NULL-ptr-dereferences-and-memory-leaks.patch @@ -0,0 +1,76 @@ +From ac934fb9123ac13e1de5883df1e5d136ebbb544e Mon Sep 17 00:00:00 2001 +From: Mateusz Grzonka +Date: Mon, 13 Jun 2022 11:59:34 +0200 +Subject: [PATCH 2/5] Fix possible NULL ptr dereferences and memory leaks + +In Assemble there was a NULL check for sra variable, +which effectively didn't stop the execution in every case. +That might have resulted in a NULL pointer dereference. + +Also in super-ddf, mu variable was set to NULL for some condition, +and then immidiately dereferenced. +Additionally some memory wasn't freed as well. + +Conflict:NA +Reference:https://git.kernel.org/pub/scm/utils/mdadm/mdadm.git//commit?id=626bc45396c4959f2c4685c2faa7c4f553f4efdf + +Signed-off-by: Mateusz Grzonka +Signed-off-by: Jes Sorensen +--- + Assemble.c | 7 ++++++- + super-ddf.c | 9 +++++++-- + 2 files changed, 13 insertions(+), 3 deletions(-) + +diff --git a/Assemble.c b/Assemble.c +index 914c193..3ef4b29 100644 +--- a/Assemble.c ++++ b/Assemble.c +@@ -1909,7 +1909,12 @@ int assemble_container_content(struct supertype *st, int mdfd, + } + + sra = sysfs_read(mdfd, NULL, GET_VERSION|GET_DEVS); +- if (sra == NULL || strcmp(sra->text_version, content->text_version) != 0) { ++ if (sra == NULL) { ++ pr_err("Failed to read sysfs parameters\n"); ++ return 1; ++ } ++ ++ if (strcmp(sra->text_version, content->text_version) != 0) { + if (content->array.major_version == -1 && + content->array.minor_version == -2 && + c->readonly && +diff --git a/super-ddf.c b/super-ddf.c +index c095e8a..b61aa2f 100644 +--- a/super-ddf.c ++++ b/super-ddf.c +@@ -5121,13 +5121,16 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a, + */ + vc = find_vdcr(ddf, a->info.container_member, rv->disk.raid_disk, + &n_bvd, &vcl); +- if (vc == NULL) ++ if (vc == NULL) { ++ free(rv); + return NULL; ++ } + + mu = xmalloc(sizeof(*mu)); + if (posix_memalign(&mu->space, 512, sizeof(struct vcl)) != 0) { + free(mu); +- mu = NULL; ++ free(rv); ++ return NULL; + } + + mu->len = ddf->conf_rec_len * 512 * vcl->conf.sec_elmnt_count; +@@ -5157,6 +5160,8 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a, + pr_err("BUG: can't find disk %d (%d/%d)\n", + di->disk.raid_disk, + di->disk.major, di->disk.minor); ++ free(mu); ++ free(rv); + return NULL; + } + vc->phys_refnum[i_prim] = ddf->phys->entries[dl->pdnum].refnum; +-- +1.8.3.1 + diff --git a/6017-Monitor-use-devname-as-char-array-instead-of-pointer.patch b/6017-Monitor-use-devname-as-char-array-instead-of-pointer.patch new file mode 100644 index 0000000000000000000000000000000000000000..840d714e39d81db068afa127b008f745fa88a24e --- /dev/null +++ b/6017-Monitor-use-devname-as-char-array-instead-of-pointer.patch @@ -0,0 +1,43 @@ +From e3130805d3b9768325837b43587a74723f9222c5 Mon Sep 17 00:00:00 2001 +From: Kinga Tanska +Date: Thu, 14 Jul 2022 09:02:10 +0200 +Subject: [PATCH 3/5] Monitor: use devname as char array instead of pointer + +Device name wasn't filled properly due to incorrect use of strcpy. +Strcpy was used twice. Firstly to fill devname with "/dev/md/" +and then to add chosen name. First strcpy result was overwritten by +second one (as a result instead of "/dev/md/" +was assigned). This commit changes this implementation to use snprintf +and devname with fixed size. + +Conflict:context adaptation +Reference:https://git.kernel.org/pub/scm/utils/mdadm/mdadm.git//commit?id=c8d1c398505b62d9129a4e711f17e4469f4327ff + +Signed-off-by: Kinga Tanska +Signed-off-by: Jes Sorensen +--- + Monitor.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/Monitor.c b/Monitor.c +index 036103f..1980764 100644 +--- a/Monitor.c ++++ b/Monitor.c +@@ -175,9 +175,11 @@ int Monitor(struct mddev_dev *devlist, + if (mdlist->devname[0] == '/') + st->devname = xstrdup(mdlist->devname); + else { +- st->devname = xmalloc(8+strlen(mdlist->devname)+1); +- strcpy(strcpy(st->devname, "/dev/md/"), +- mdlist->devname); ++ /* length of "/dev/md/" + device name + terminating byte */ ++ size_t _len = sizeof("/dev/md/") + strnlen(mdlist->devname, PATH_MAX); ++ ++ st->devname = xcalloc(_len, sizeof(char)); ++ snprintf(st->devname, _len, "/dev/md/%s", mdlist->devname); + } + st->next = statelist; + st->devnm[0] = 0; +-- +1.8.3.1 + diff --git a/6018-mdadm-block-creation-with-long-names.patch b/6018-mdadm-block-creation-with-long-names.patch new file mode 100644 index 0000000000000000000000000000000000000000..1e4f3f1b40d75e4ea77f939cc807941b6f3c9c79 --- /dev/null +++ b/6018-mdadm-block-creation-with-long-names.patch @@ -0,0 +1,75 @@ +From b088a60fb9c5b11e61e4dff46048b904cd03a218 Mon Sep 17 00:00:00 2001 +From: Blazej Kucman +Date: Fri, 3 Dec 2021 15:31:15 +0100 +Subject: [PATCH 1/2] mdadm: block creation with long names + +This fixes buffer overflows in create_mddev(). It prohibits +creation with not supported names for DDF and native. For IMSM, +mdadm will do silent cut to 16 later. + +Conflict:NA +Reference:https://git.kernel.org/pub/scm/utils/mdadm/mdadm.git//commit?id=ced5fa8b170ad448f4076e24a10c731b5cfb36ce + +Signed-off-by: Mariusz Tkaczyk +Signed-off-by: Blazej Kucman +Signed-off-by: Jes Sorensen +--- + mdadm.8.in | 5 +++++ + mdadm.c | 9 ++++++++- + mdadm.h | 5 +++++ + 3 files changed, 18 insertions(+), 1 deletion(-) + +diff --git a/mdadm.8.in b/mdadm.8.in +index 9aec9f4..58614fd 100644 +--- a/mdadm.8.in ++++ b/mdadm.8.in +@@ -2129,6 +2129,11 @@ is run, but will be created by + .I udev + once the array becomes active. + ++The max length md-device name is limited to 32 characters. ++Different metadata types have more strict limitation ++(like IMSM where only 16 characters are allowed). ++For that reason, long name could be truncated or rejected, it depends on metadata policy. ++ + As devices are added, they are checked to see if they contain RAID + superblocks or filesystems. They are also checked to see if the variance in + device size exceeds 1%. +diff --git a/mdadm.c b/mdadm.c +index 25a1abd..cb45b59 100644 +--- a/mdadm.c ++++ b/mdadm.c +@@ -1354,9 +1354,16 @@ int main(int argc, char *argv[]) + mdfd = open_mddev(devlist->devname, 1); + if (mdfd < 0) + exit(1); +- } else ++ } else { ++ char *bname = basename(devlist->devname); ++ ++ if (strlen(bname) > MD_NAME_MAX) { ++ pr_err("Name %s is too long.\n", devlist->devname); ++ exit(1); ++ } + /* non-existent device is OK */ + mdfd = open_mddev(devlist->devname, 0); ++ } + if (mdfd == -2) { + pr_err("device %s exists but is not an md array.\n", devlist->devname); + exit(1); +diff --git a/mdadm.h b/mdadm.h +index 387e681..e25d8a2 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -1793,3 +1793,8 @@ char *xstrdup(const char *str); + #define INVALID_SECTORS 1 + /* And another special number needed for --data_offset=variable */ + #define VARIABLE_OFFSET 3 ++ ++/** ++ * This is true for native and DDF, IMSM allows 16. ++ */ ++#define MD_NAME_MAX 32 +-- +1.8.3.1 + diff --git a/6019-mdadm-Don-t-open-md-device-for-CREATE-and-ASSEMBLE.patch b/6019-mdadm-Don-t-open-md-device-for-CREATE-and-ASSEMBLE.patch new file mode 100644 index 0000000000000000000000000000000000000000..f90de8346cc90c5aecbd2d4a93c55d1b1849b855 --- /dev/null +++ b/6019-mdadm-Don-t-open-md-device-for-CREATE-and-ASSEMBLE.patch @@ -0,0 +1,173 @@ +From 64b5618da8217bff1ad84c0631e0baf90398693b Mon Sep 17 00:00:00 2001 +From: Logan Gunthorpe +Date: Wed, 27 Jul 2022 15:52:46 -0600 +Subject: [PATCH] mdadm: Don't open md device for CREATE and ASSEMBLE + +The mdadm command tries to open the md device for most modes, first +thing, no matter what. When running to create or assemble an array, +in most cases, the md device will not exist, the open call will fail +and everything will proceed correctly. + +However, when running tests, a create or assembly command may be run +shortly after stopping an array and the old md device file may still +be around. Then, if create_on_open is set in the kernel, a new md +device will be created when mdadm does its initial open. + +When mdadm gets around to creating the new device with the new_array +parameter it issues this error: + + mdadm: Fail to create md0 when using + /sys/module/md_mod/parameters/new_array, fallback to creation via node + +This is because an mddev was already created by the kernel with the +earlier open() call and thus the new one being created will fail with +EEXIST. The mdadm command will still successfully be created due to +falling back to the node creation method. However, the error message +itself will fail any test that's running it. + +This issue is a race condition that is very rare, but a recent change +in the kernel caused this to happen more frequently: about 1 in 50 +times. + +To fix this, don't bother trying to open the md device for CREATE, +ASSEMBLE and BUILD commands, as the file descriptor will never be used +anyway even if it is successfully openned. The mdfd has not been used +for these commands since: + + 7f91af49ad09 ("Delay creation of array devices for assemble/build/create") + +The checks that were done on the open device can be changed to being +done with stat. + +Side note: it would be nice to disable create_on_open as well to help +solve this, but it seems the work for this was never finished. By default, +mdadm will create using the old node interface when a name is specified +unless the user specifically puts names=yes in a config file, which +doesn't seem to be common or desirable to require this.. + +Conflict:add stdbool.h +Reference:https://git.kernel.org/pub/scm/utils/mdadm/mdadm.git//commit?id=27ad4900501c615b7c6b266bf23948e5606dba53 + +Signed-off-by: Logan Gunthorpe +Signed-off-by: Jes Sorensen +--- + lib.c | 12 ++++++++++++ + mdadm.c | 40 ++++++++++++++++++++-------------------- + mdadm.h | 2 ++ + 3 files changed, 34 insertions(+), 20 deletions(-) + +diff --git a/lib.c b/lib.c +index 60890b9..57cc052 100644 +--- a/lib.c ++++ b/lib.c +@@ -152,6 +152,18 @@ char *stat2devnm(struct stat *st) + return devid2devnm(st->st_rdev); + } + ++bool stat_is_md_dev(struct stat *st) ++{ ++ if ((S_IFMT & st->st_mode) != S_IFBLK) ++ return false; ++ if (major(st->st_rdev) == MD_MAJOR) ++ return true; ++ if (major(st->st_rdev) == (unsigned)get_mdp_major()) ++ return true; ++ ++ return false; ++} ++ + char *fd2devnm(int fd) + { + struct stat stb; +diff --git a/mdadm.c b/mdadm.c +index 7319d02..da66c76 100644 +--- a/mdadm.c ++++ b/mdadm.c +@@ -1343,6 +1343,9 @@ int main(int argc, char *argv[]) + + if (mode == MANAGE || mode == BUILD || mode == CREATE || + mode == GROW || (mode == ASSEMBLE && ! c.scan)) { ++ struct stat stb; ++ int ret; ++ + if (devs_found < 1) { + pr_err("an md device must be given in this mode\n"); + exit(2); +@@ -1355,6 +1358,12 @@ int main(int argc, char *argv[]) + mdfd = open_mddev(devlist->devname, 1); + if (mdfd < 0) + exit(1); ++ ++ ret = fstat(mdfd, &stb); ++ if (ret) { ++ pr_err("fstat failed on %s.\n", devlist->devname); ++ exit(1); ++ } + } else { + char *bname = basename(devlist->devname); + +@@ -1362,30 +1371,21 @@ int main(int argc, char *argv[]) + pr_err("Name %s is too long.\n", devlist->devname); + exit(1); + } +- /* non-existent device is OK */ +- mdfd = open_mddev(devlist->devname, 0); +- } +- if (mdfd == -2) { +- pr_err("device %s exists but is not an md array.\n", devlist->devname); +- exit(1); +- } +- if ((int)ident.super_minor == -2) { +- struct stat stb; +- if (mdfd < 0) { ++ ++ ret = stat(devlist->devname, &stb); ++ if (ident.super_minor == -2 && ret != 0) { + pr_err("--super-minor=dev given, and listed device %s doesn't exist.\n", +- devlist->devname); ++ devlist->devname); ++ exit(1); ++ } ++ ++ if (!ret && !stat_is_md_dev(&stb)) { ++ pr_err("device %s exists but is not an md array.\n", devlist->devname); + exit(1); + } +- fstat(mdfd, &stb); +- ident.super_minor = minor(stb.st_rdev); +- } +- if (mdfd >= 0 && mode != MANAGE && mode != GROW) { +- /* We don't really want this open yet, we just might +- * have wanted to check some things +- */ +- close(mdfd); +- mdfd = -1; + } ++ if (ident.super_minor == -2) ++ ident.super_minor = minor(stb.st_rdev); + } + + if (s.raiddisks) { +diff --git a/mdadm.h b/mdadm.h +index 58b14b9..8e7029c 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -45,6 +45,7 @@ extern __off64_t lseek64 __P ((int __fd, __off64_t __offset, int __whence)); + #include + #include + #include ++#include + #ifdef __GLIBC__ + /* Newer glibc requires sys/sysmacros.h directly for makedev() */ + #include +@@ -1581,6 +1582,7 @@ void *super1_make_v0(struct supertype *st, struct mdinfo *info, mdp_super_t *sb0 + extern char *stat2kname(struct stat *st); + extern char *fd2kname(int fd); + extern char *stat2devnm(struct stat *st); ++bool stat_is_md_dev(struct stat *st); + extern char *fd2devnm(int fd); + extern void udev_block(char *devnm); + extern void udev_unblock(void); +-- +1.8.3.1 + diff --git a/mdadm.spec b/mdadm.spec index 3aabbe214bd4b69beb24f49e84965caf125d9e86..e22309c4918c4d0170641232e304f64404476d12 100644 --- a/mdadm.spec +++ b/mdadm.spec @@ -1,6 +1,6 @@ Name: mdadm Version: 4.1 -Release: rc2.0.11 +Release: rc2.0.12 Summary: The software RAID arrays user manage tools License: GPLv2+ URL: http://www.kernel.org/pub/linux/utils/raid/mdadm/ @@ -26,6 +26,10 @@ Patch6012: 6012-Create-Block-rounding-size-to-max.patch Patch6013: 6013-mdadm-fix-coredump-of-mdadm-monitor-r.patch Patch6014: 6014-mdadm-Fix-mdadm-r-remove-option-regresision.patch Patch6015: 6015-monitor-Avoid-segfault-when-calling-NULL-get_bad_blo.patch +Patch6016: 6016-Fix-possible-NULL-ptr-dereferences-and-memory-leaks.patch +Patch6017: 6017-Monitor-use-devname-as-char-array-instead-of-pointer.patch +Patch6018: 6018-mdadm-block-creation-with-long-names.patch +Patch6019: 6019-mdadm-Don-t-open-md-device-for-CREATE-and-ASSEMBLE.patch BuildRequires: systemd gcc binutils Requires(post): systemd coreutils @@ -88,6 +92,9 @@ install -d -m 710 %{buildroot}/var/run/mdadm/ %{_mandir}/man*/* %changelog +* Thu Dec 8 2022 Zhiqiang Liu - 4.1-rc2.0.12 +- backport four upstream bugfix patches + * Mon Nov 14 2022 Zhiqiang Liu - 4.1-rc2.0.11 - backport upstream bugfix patch to fix segfault problem in monitor.c