backport four bugfix patches

fix issue:https://gitee.com/src-openeuler/mdadm/issues/I62L1B?from=project-issue

Signed-off-by: liuzhiqiang <lzhq28@mail.ustc.edu.cn>
(cherry picked from commit 304fa34fea4c4543d0c07bd9ab14abffcf45a8bb)
This commit is contained in:
Zhiqiang Liu 2022-12-08 16:36:23 +08:00 committed by openeuler-sync-bot
parent 6aaef226aa
commit 5ee6fbf059
5 changed files with 375 additions and 1 deletions

View File

@ -0,0 +1,76 @@
From ac934fb9123ac13e1de5883df1e5d136ebbb544e Mon Sep 17 00:00:00 2001
From: Mateusz Grzonka <mateusz.grzonka@intel.com>
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 <mateusz.grzonka@intel.com>
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
---
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

View File

@ -0,0 +1,43 @@
From e3130805d3b9768325837b43587a74723f9222c5 Mon Sep 17 00:00:00 2001
From: Kinga Tanska <kinga.tanska@intel.com>
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 <device_name> instead of "/dev/md/<device_name>"
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 <kinga.tanska@intel.com>
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
---
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

View File

@ -0,0 +1,75 @@
From b088a60fb9c5b11e61e4dff46048b904cd03a218 Mon Sep 17 00:00:00 2001
From: Blazej Kucman <blazej.kucman@intel.com>
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 <mariusz.tkaczyk@linux.intel.com>
Signed-off-by: Blazej Kucman <blazej.kucman@intel.com>
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
---
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

View File

@ -0,0 +1,173 @@
From 64b5618da8217bff1ad84c0631e0baf90398693b Mon Sep 17 00:00:00 2001
From: Logan Gunthorpe <logang@deltatee.com>
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 <logang@deltatee.com>
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
---
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 <errno.h>
#include <string.h>
#include <syslog.h>
+#include <stdbool.h>
#ifdef __GLIBC__
/* Newer glibc requires sys/sysmacros.h directly for makedev() */
#include <sys/sysmacros.h>
@@ -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

View File

@ -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 <liuzhiqiang26@huawei.com> - 4.1-rc2.0.12
- backport four upstream bugfix patches
* Mon Nov 14 2022 Zhiqiang Liu <liuzhiqiang26@huawei.com> - 4.1-rc2.0.11
- backport upstream bugfix patch to fix segfault problem in monitor.c