|
|
96dc52 |
autofs-5.1.7 - fix inconsistent locking in umount_subtree_mounts()
|
|
|
96dc52 |
|
|
|
96dc52 |
From: Ian Kent <raven@themaw.net>
|
|
|
96dc52 |
|
|
|
96dc52 |
Some map entry cache locking inconsistencies have crept in.
|
|
|
96dc52 |
|
|
|
96dc52 |
In umount_subtree_mounts() the cache write lock should be held when
|
|
|
96dc52 |
deleting multi-mount cache entries.
|
|
|
96dc52 |
|
|
|
96dc52 |
Signed-off-by: Ian Kent <raven@themaw.net>
|
|
|
96dc52 |
---
|
|
|
96dc52 |
CHANGELOG | 1 +
|
|
|
96dc52 |
daemon/automount.c | 42 ++++++++++++++++++++++++++++++------------
|
|
|
96dc52 |
lib/mounts.c | 8 --------
|
|
|
96dc52 |
3 files changed, 31 insertions(+), 20 deletions(-)
|
|
|
96dc52 |
|
|
|
96dc52 |
diff --git a/CHANGELOG b/CHANGELOG
|
|
|
96dc52 |
index 1dded118..64e619ec 100644
|
|
|
96dc52 |
--- a/CHANGELOG
|
|
|
96dc52 |
+++ b/CHANGELOG
|
|
|
96dc52 |
@@ -15,6 +15,7 @@
|
|
|
96dc52 |
- eliminate clean_stale_multi_triggers().
|
|
|
96dc52 |
- simplify mount_subtree() mount check.
|
|
|
96dc52 |
- fix mnts_get_expire_list() expire list construction.
|
|
|
96dc52 |
+- fix inconsistent locking in umount_subtree_mounts().
|
|
|
96dc52 |
|
|
|
96dc52 |
25/01/2021 autofs-5.1.7
|
|
|
96dc52 |
- make bind mounts propagation slave by default.
|
|
|
96dc52 |
diff --git a/daemon/automount.c b/daemon/automount.c
|
|
|
96dc52 |
index 7fa92877..93bd8556 100644
|
|
|
96dc52 |
--- a/daemon/automount.c
|
|
|
96dc52 |
+++ b/daemon/automount.c
|
|
|
96dc52 |
@@ -527,8 +527,11 @@ static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsi
|
|
|
96dc52 |
struct mapent_cache *mc;
|
|
|
96dc52 |
struct mapent *me;
|
|
|
96dc52 |
unsigned int is_mm_root = 0;
|
|
|
96dc52 |
+ int cur_state;
|
|
|
96dc52 |
int left;
|
|
|
96dc52 |
|
|
|
96dc52 |
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
|
|
|
96dc52 |
+
|
|
|
96dc52 |
me = lookup_source_mapent(ap, path, LKP_DISTINCT);
|
|
|
96dc52 |
if (!me) {
|
|
|
96dc52 |
char *ind_key;
|
|
|
96dc52 |
@@ -548,11 +551,11 @@ static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsi
|
|
|
96dc52 |
left = 0;
|
|
|
96dc52 |
|
|
|
96dc52 |
if (me && me->multi) {
|
|
|
96dc52 |
- char root[PATH_MAX];
|
|
|
96dc52 |
+ char root[PATH_MAX + 1];
|
|
|
96dc52 |
+ char key[PATH_MAX + 1];
|
|
|
96dc52 |
+ struct mapent *tmp;
|
|
|
96dc52 |
+ int status;
|
|
|
96dc52 |
char *base;
|
|
|
96dc52 |
- int cur_state;
|
|
|
96dc52 |
-
|
|
|
96dc52 |
- pthread_cleanup_push(cache_lock_cleanup, mc);
|
|
|
96dc52 |
|
|
|
96dc52 |
if (!strchr(me->multi->key, '/'))
|
|
|
96dc52 |
/* Indirect multi-mount root */
|
|
|
96dc52 |
@@ -567,25 +570,40 @@ static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsi
|
|
|
96dc52 |
else
|
|
|
96dc52 |
base = me->key + strlen(root);
|
|
|
96dc52 |
|
|
|
96dc52 |
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
|
|
|
96dc52 |
- /* Lock the closest parent nesting point for umount */
|
|
|
96dc52 |
- cache_multi_writelock(me->parent);
|
|
|
96dc52 |
- if (umount_multi_triggers(ap, me, root, base)) {
|
|
|
96dc52 |
+ left = umount_multi_triggers(ap, me, root, base);
|
|
|
96dc52 |
+ if (left) {
|
|
|
96dc52 |
warn(ap->logopt,
|
|
|
96dc52 |
"some offset mounts still present under %s", path);
|
|
|
96dc52 |
+ }
|
|
|
96dc52 |
+
|
|
|
96dc52 |
+ strcpy(key, me->key);
|
|
|
96dc52 |
+
|
|
|
96dc52 |
+ cache_unlock(mc);
|
|
|
96dc52 |
+ cache_writelock(mc);
|
|
|
96dc52 |
+ tmp = cache_lookup_distinct(mc, key);
|
|
|
96dc52 |
+ /* mapent went away while we waited? */
|
|
|
96dc52 |
+ if (tmp != me) {
|
|
|
96dc52 |
+ cache_unlock(mc);
|
|
|
96dc52 |
+ pthread_setcancelstate(cur_state, NULL);
|
|
|
96dc52 |
+ return 0;
|
|
|
96dc52 |
+ }
|
|
|
96dc52 |
+
|
|
|
96dc52 |
+ if (!left && is_mm_root) {
|
|
|
96dc52 |
+ status = cache_delete_offset_list(mc, me->key);
|
|
|
96dc52 |
+ if (status != CHE_OK)
|
|
|
96dc52 |
+ warn(ap->logopt, "couldn't delete offset list");
|
|
|
96dc52 |
left++;
|
|
|
96dc52 |
}
|
|
|
96dc52 |
- cache_multi_unlock(me->parent);
|
|
|
96dc52 |
+
|
|
|
96dc52 |
if (ap->entry->maps &&
|
|
|
96dc52 |
(ap->entry->maps->flags & MAP_FLAG_FORMAT_AMD))
|
|
|
96dc52 |
cache_pop_mapent(me);
|
|
|
96dc52 |
- pthread_setcancelstate(cur_state, NULL);
|
|
|
96dc52 |
- pthread_cleanup_pop(0);
|
|
|
96dc52 |
}
|
|
|
96dc52 |
-
|
|
|
96dc52 |
if (me)
|
|
|
96dc52 |
cache_unlock(mc);
|
|
|
96dc52 |
|
|
|
96dc52 |
+ pthread_setcancelstate(cur_state, NULL);
|
|
|
96dc52 |
+
|
|
|
96dc52 |
if (left || is_autofs_fs)
|
|
|
96dc52 |
return left;
|
|
|
96dc52 |
|
|
|
96dc52 |
diff --git a/lib/mounts.c b/lib/mounts.c
|
|
|
96dc52 |
index 87813b16..5ebfe5fd 100644
|
|
|
96dc52 |
--- a/lib/mounts.c
|
|
|
96dc52 |
+++ b/lib/mounts.c
|
|
|
96dc52 |
@@ -2736,9 +2736,6 @@ int umount_multi_triggers(struct autofs_point *ap, struct mapent *me, char *root
|
|
|
96dc52 |
left = do_umount_multi_triggers(ap, me, root, base);
|
|
|
96dc52 |
|
|
|
96dc52 |
if (!left && me->multi == me) {
|
|
|
96dc52 |
- struct mapent_cache *mc = me->mc;
|
|
|
96dc52 |
- int status;
|
|
|
96dc52 |
-
|
|
|
96dc52 |
/*
|
|
|
96dc52 |
* Special case.
|
|
|
96dc52 |
* If we can't umount the root container then we can't
|
|
|
96dc52 |
@@ -2756,11 +2753,6 @@ int umount_multi_triggers(struct autofs_point *ap, struct mapent *me, char *root
|
|
|
96dc52 |
}
|
|
|
96dc52 |
}
|
|
|
96dc52 |
|
|
|
96dc52 |
- /* We're done - clean out the offsets */
|
|
|
96dc52 |
- status = cache_delete_offset_list(mc, me->key);
|
|
|
96dc52 |
- if (status != CHE_OK)
|
|
|
96dc52 |
- warn(ap->logopt, "couldn't delete offset list");
|
|
|
96dc52 |
-
|
|
|
96dc52 |
/* check for mounted mount entry and remove it if found */
|
|
|
96dc52 |
mnts_remove_mount(root, MNTS_MOUNTED);
|
|
|
96dc52 |
}
|