- Add fix for RHEL-87525.

This commit is contained in:
Ian Kent 2025-04-30 17:06:54 +08:00
parent b847c35d22
commit ebf894222f
4 changed files with 245 additions and 1 deletions

View File

@ -0,0 +1,66 @@
autofs-5.1.9 - fix deadlock in master_notify_submount()
From: Ian Kent <raven@themaw.net>
A deadlock between mnts_remove_submount() and master_notify_submount()
can occur because master_notify_submount() holds the state mutex over
a call to mnts_find_submount() which then needs to take mnts_hash_mutex.
But mnts_remove_submount() takes mnts_hash_mutex and then needs to take
the state mutex to clear the ->ap field so deadlock cann occur.
But it isn't necessary for master_notify_submount() to take the state
mutex before calling mnts_find_submount() because if the submount is'
found a reference is taken on the entry so it won't go away while it's
being used. All that's needed is to ensure that the ->ap field doesn't
get set to NULL by mnts_remove_submount() while it's being used to check
if the submount has shutdown.
Fixes: 81ac572466e3 ("autofs-5.1.9 - fix submount shutdown race")
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
daemon/master.c | 7 +++----
2 files changed, 4 insertions(+), 4 deletions(-)
--- autofs-5.1.9.orig/CHANGELOG
+++ autofs-5.1.9/CHANGELOG
@@ -18,6 +18,7 @@
- refactor amd mount options handling.
- add some unimplemented amd map options.
- fix submount shutdown race.
+- fix deadlock in master_notify_submount().
02/11/2023 autofs-5.1.9
- fix kernel mount status notification.
--- autofs-5.1.9.orig/daemon/master.c
+++ autofs-5.1.9/daemon/master.c
@@ -1246,26 +1246,25 @@ int master_notify_submount(struct autofs
* ST_SHUTDOWN_FORCE we need to wait until it goes away
* or changes to state ST_SHUTDOWN or ST_READY.
*/
- st_mutex_lock();
while ((sbmnt = mnts_find_submount(path))) {
struct timespec t = { 0, 300000000 };
struct timespec r;
+ st_mutex_lock();
if (!sbmnt->ap ||
(sbmnt->ap->state != ST_SHUTDOWN_PENDING &&
sbmnt->ap->state != ST_SHUTDOWN_FORCE)) {
ret = 0;
+ st_mutex_unlock();
mnts_put_mount(sbmnt);
break;
}
+ st_mutex_unlock();
mnts_put_mount(sbmnt);
- st_mutex_unlock();
while (nanosleep(&t, &r) == -1 && errno == EINTR)
memcpy(&t, &r, sizeof(struct timespec));
- st_mutex_lock();
}
- st_mutex_unlock();
done:
mnts_put_mount(this);
}

View File

@ -0,0 +1,77 @@
autofs-5.1.9 - fix lock ordering deadlock in expire_cleanup()
From: Ian Kent <raven@themaw.net>
Commit 81ac572466e3 ("autofs-5.1.9 - fix submount shutdown race")
introduced a lock ordering deadlock between the state mutex and the
mounts hash list mutex when fixing a submount shutdown race. It's enough
to just move the conditional alarm set function call outside of the
state mutex critical section to fix it.
Fixes: 81ac572466e3 ("autofs-5.1.9 - fix submount shutdown race")
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
daemon/state.c | 12 ++++++++----
2 files changed, 9 insertions(+), 4 deletions(-)
--- autofs-5.1.9.orig/CHANGELOG
+++ autofs-5.1.9/CHANGELOG
@@ -19,6 +19,7 @@
- add some unimplemented amd map options.
- fix submount shutdown race.
- fix deadlock in master_notify_submount().
+- fix lock ordering deadlock in expire_cleanup().
02/11/2023 autofs-5.1.9
- fix kernel mount status notification.
--- autofs-5.1.9.orig/daemon/state.c
+++ autofs-5.1.9/daemon/state.c
@@ -62,8 +62,9 @@ void expire_cleanup(void *arg)
pthread_t thid = pthread_self();
struct expire_args *ec;
struct autofs_point *ap;
- int success;
enum states next = ST_INVAL;
+ unsigned int need_alarm = 0;
+ int success;
ec = (struct expire_args *) arg;
ap = ec->ap;
@@ -99,7 +100,7 @@ void expire_cleanup(void *arg)
}
if (ap->state == ST_EXPIRE)
- conditional_alarm_add(ap, ap->exp_runfreq);
+ need_alarm = 1;
/* FALLTHROUGH */
@@ -116,7 +117,7 @@ void expire_cleanup(void *arg)
rv = ops->askumount(ap->logopt, ap->ioctlfd, &idle);
if (!rv && !idle && !ap->shutdown) {
next = ST_READY;
- conditional_alarm_add(ap, ap->exp_runfreq);
+ need_alarm = 1;
break;
}
@@ -129,7 +130,7 @@ void expire_cleanup(void *arg)
/* Failed shutdown returns to ready */
warn(ap->logopt, "filesystem %s still busy", ap->path);
- conditional_alarm_add(ap, ap->exp_runfreq);
+ need_alarm = 1;
next = ST_READY;
break;
#endif
@@ -156,6 +157,9 @@ void expire_cleanup(void *arg)
st_mutex_unlock();
+ if (need_alarm)
+ conditional_alarm_add(ap, ap->exp_runfreq);
+
return;
}

View File

@ -0,0 +1,89 @@
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.9.orig/CHANGELOG
+++ autofs-5.1.9/CHANGELOG
@@ -17,6 +17,7 @@
- make iocl ops ->timeout() handle per-dentry expire.
- refactor amd mount options handling.
- add some unimplemented amd map options.
+- fix submount shutdown race.
02/11/2023 autofs-5.1.9
- fix kernel mount status notification.
--- autofs-5.1.9.orig/daemon/master.c
+++ autofs-5.1.9/daemon/master.c
@@ -1222,22 +1222,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
@@ -1249,8 +1251,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.9.orig/lib/mounts.c
+++ autofs-5.1.9/lib/mounts.c
@@ -1136,7 +1136,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);
}

View File

@ -12,7 +12,7 @@
Summary: A tool for automatically mounting and unmounting filesystems
Name: autofs
Version: 5.1.9
Release: 11%{?dist}
Release: 12%{?dist}
Epoch: 1
License: GPL-2.0-or-later
Source: https://www.kernel.org/pub/linux/daemons/autofs/v5/autofs-%{version}.tar.gz
@ -35,6 +35,11 @@ Patch15: autofs-5.1.9-make-ioctl-ops-timeout-handle-per-dentry-expire.patch
Patch16: autofs-5.1.9-refactor-amd-mount-options-handling.patch
Patch17: autofs-5.1.9-add-some-unimplemented-amd-map-options.patch
# RHEL-87525
Patch20: autofs-5.1.9-fix-submount-shutdown-race.patch
Patch21: autofs-5.1.9-fix-deadlock-in-master_notify_submount.patch
Patch22: autofs-5.1.9-fix-lock-ordering-deadlock-in-expire_cleanup.patch
%if %{with_systemd}
BuildRequires: systemd-units
BuildRequires: systemd-devel
@ -206,6 +211,13 @@ fi
%dir /etc/auto.master.d
%changelog
* Wed Apr 30 2025 Ian Kent <ikent@redhat.com> - 1:5.1.9-12
- RHEL-87525 - autofs hang - autofs-5.1.4-114.el8_10.2 [rhel-10]
- fix submount shutdown race.
- fix deadlock in master_notify_submount().
- fix lock ordering deadlock in expire_cleanup().
- Resolves: RHEL-87525
* Tue Oct 29 2024 Troy Dawson <tdawson@redhat.com> - 1:5.1.9-11
- Bump release for October 2024 mass rebuild:
Resolves: RHEL-64018