[dm-devel] [PATCH] libmultipath: clear removed path from mpp
lixiaokeng
lixiaokeng at huawei.com
Sat Nov 27 10:15:59 UTC 2021
multipathd[3525635]: ==3525635==ERROR: AddressSanitizer: heap-use-after-free on address 0xffffa4902fc0 at pc 0xffffac7d5b88 bp 0xffffa948dac0 sp 0xffffa948dae0
multipathd[3525635]: READ of size 8 at 0xffffa4902fc0 thread T7
multipathd[3525635]: #0 0xffffac7d5b87 in free_multipath (/usr/lib64/libmultipath.so.0+0x4bb87)
multipathd[3525635]: #1 0xaaaad6cf7057 (/usr/sbin/multipathd+0x17057)
multipathd[3525635]: #2 0xaaaad6cf78eb (/usr/sbin/multipathd+0x178eb)
multipathd[3525635]: #3 0xaaaad6cff4df (/usr/sbin/multipathd+0x1f4df)
multipathd[3525635]: #4 0xaaaad6cfffe7 (/usr/sbin/multipathd+0x1ffe7)
multipathd[3525635]: #5 0xffffac807be3 in uevent_dispatch (/usr/lib64/libmultipath.so.0+0x7dbe3)
multipathd[3525635]: #6 0xaaaad6cf563f (/usr/sbin/multipathd+0x1563f)
multipathd[3525635]: #7 0xffffac6877af (/usr/lib64/libpthread.so.0+0x87af)
multipathd[3525635]: #8 0xffffac44118b (/usr/lib64/libc.so.6+0xd518b)
multipathd[3525635]: 0xffffa4902fc0 is located 1344 bytes inside of 1440-byte region [0xffffa4902a80,0xffffa4903020)
multipathd[3525635]: freed by thread T7 here:
multipathd[3525635]: #0 0xffffac97d703 in free (/usr/lib64/libasan.so.4+0xd0703)
multipathd[3525635]: #1 0xffffac824827 in orphan_paths (/usr/lib64/libmultipath.so.0+0x9a827)
multipathd[3525635]: #2 0xffffac824a43 in remove_map (/usr/lib64/libmultipath.so.0+0x9aa43)
multipathd[3525635]: #3 0xaaaad6cf7057 (/usr/sbin/multipathd+0x17057)
multipathd[3525635]: #4 0xaaaad6cf78eb (/usr/sbin/multipathd+0x178eb)
multipathd[3525635]: #5 0xaaaad6cff4df (/usr/sbin/multipathd+0x1f4df)
multipathd[3525635]: #6 0xaaaad6cfffe7 (/usr/sbin/multipathd+0x1ffe7)
multipathd[3525635]: #7 0xffffac807be3 in uevent_dispatch (/usr/lib64/libmultipath.so.0+0x7dbe3)
multipathd[3525635]: #8 0xaaaad6cf563f (/usr/sbin/multipathd+0x1563f)
multipathd[3525635]: #9 0xffffac6877af (/usr/lib64/libpthread.so.0+0x87af)
multipathd[3525635]: #10 0xffffac44118b (/usr/lib64/libc.so.6+0xd518b)
When mpp only has one path and log out the path, there is an asan error.
In remove_mpp, the pp is freed firstly in orphan_path but is accessed,
changed in free_multipath later. Before free_path(pp), the pp should be
cleared from pp->mpp.
When pp is set to REMOVED, it will be an orphan path. At the same time,
clear it from it's map.
Signed-off-by: Lixiaokeng <lixiaokeng at huawei.com>
---
libmultipath/structs_vec.c | 20 +++++++++++++++++---
multipathd/main.c | 8 --------
2 files changed, 17 insertions(+), 11 deletions(-)
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
index 85d97ac1..ab5311cc 100644
--- a/libmultipath/structs_vec.c
+++ b/libmultipath/structs_vec.c
@@ -318,7 +318,9 @@ void orphan_paths(vector pathvec, struct multipath *mpp, const char *reason)
void set_path_removed(struct path *pp)
{
+ int i, j;
struct multipath *mpp = pp->mpp;
+ struct pathgroup * pgp;
orphan_path(pp, "removed");
/*
@@ -329,6 +331,20 @@ void set_path_removed(struct path *pp)
condlog(0, "%s: internal error: mpp == NULL", pp->dev);
return;
}
+
+ /*
+ * The path is removed, clear it from mp->paths and mpp->pgs.
+ */
+ i = find_slot(mpp->paths, pp);
+ if (i != -1)
+ vector_del_slot(mpp->paths, i);
+
+ vector_foreach_slot(mpp->pg, pgp, j) {
+ i = find_slot(pgp->paths, (void *)pp);
+ if (i != -1)
+ vector_del_slot(pgp->paths, i);
+ }
+
pp->mpp = mpp;
pp->initialized = INIT_REMOVED;
}
@@ -731,15 +747,13 @@ int verify_paths(struct multipath *mpp)
mpp->alias, pp->dev);
}
count++;
- vector_del_slot(mpp->paths, i);
- i--;
-
/*
* Don't delete path from pathvec yet. We'll do this
* after the path has been removed from the map, in
* sync_paths().
*/
set_path_removed(pp);
+ i--;
} else {
condlog(4, "%s: verified path %s dev_t %s",
mpp->alias, pp->dev, pp->dev_t);
diff --git a/multipathd/main.c b/multipathd/main.c
index 3f675136..388207a2 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -1226,14 +1226,6 @@ ev_remove_path (struct path *pp, struct vectors * vecs, int need_do_map)
goto fail;
}
- /*
- * we have to explicitly remove pp from mpp->paths,
- * update_mpp_paths() doesn't do that.
- */
- i = find_slot(mpp->paths, pp);
- if (i != -1)
- vector_del_slot(mpp->paths, i);
-
/*
* remove the map IF removing the last path
*/
--
More information about the dm-devel
mailing list