autofs/autofs-5.1.9-fix-submount-shutdown-race.patch

90 lines
2.5 KiB
Diff

autofs-5.1.9 - fix submount shutdown race
From: Ian Kent <raven@themaw.net>
In function master_notify_submount() an expire notification is sent to
existing submounts. automount waits for the task to complete then, if
the submount is exiting, waits for the submount to reach a completion
state.
But the submount can go away during these checks resulting in the
autofs mount point structure field of the mount list structure to be
set to NULL which can then lead to a crash.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
daemon/master.c | 23 +++++++++++++----------
lib/mounts.c | 2 ++
3 files changed, 16 insertions(+), 10 deletions(-)
--- autofs-5.1.4.orig/CHANGELOG
+++ autofs-5.1.4/CHANGELOG
@@ -154,6 +154,7 @@
- fix multi-mount check.
- fix get parent multi-mount check in try_remount().
- fix deadlock in remount.
+- fix submount shutdown race.
xx/xx/2018 autofs-5.1.5
- fix flag file permission.
--- autofs-5.1.4.orig/daemon/master.c
+++ autofs-5.1.4/daemon/master.c
@@ -1213,22 +1213,24 @@ int master_notify_submount(struct autofs
this = mnts_find_submount(path);
if (this) {
+ struct autofs_point *found;
+
/* We have found a submount to expire */
st_mutex_lock();
-
- if (this->ap->state == ST_SHUTDOWN) {
+ found = this->ap;
+ if (!found || found->state == ST_SHUTDOWN) {
this = NULL;
st_mutex_unlock();
goto done;
}
-
- this->ap->shutdown = ap->shutdown;
-
- __st_add_task(this->ap, state);
-
+ found->shutdown = ap->shutdown;
+ __st_add_task(found, state);
st_mutex_unlock();
- st_wait_task(this->ap, state, 0);
+ /* This is ok because found isn't dereferenced during
+ * the wait checks.
+ */
+ st_wait_task(found, state, 0);
/*
* If our submount gets to state ST_SHUTDOWN_PENDING or
@@ -1240,8 +1242,9 @@ int master_notify_submount(struct autofs
struct timespec t = { 0, 300000000 };
struct timespec r;
- if (sbmnt->ap->state != ST_SHUTDOWN_PENDING &&
- sbmnt->ap->state != ST_SHUTDOWN_FORCE) {
+ if (!sbmnt->ap ||
+ (sbmnt->ap->state != ST_SHUTDOWN_PENDING &&
+ sbmnt->ap->state != ST_SHUTDOWN_FORCE)) {
ret = 0;
mnts_put_mount(sbmnt);
break;
--- autofs-5.1.4.orig/lib/mounts.c
+++ autofs-5.1.4/lib/mounts.c
@@ -1153,7 +1153,9 @@ void mnts_remove_submount(const char *mp
this = mnts_lookup(mp);
if (this && this->flags & MNTS_AUTOFS) {
this->flags &= ~MNTS_AUTOFS;
+ st_mutex_lock();
this->ap = NULL;
+ st_mutex_unlock();
list_del_init(&this->submount);
__mnts_put_mount(this);
}