From ebf894222f29bf3a574cf3c5cc804f0a71174ad3 Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Wed, 30 Apr 2025 17:06:54 +0800 Subject: [PATCH] - Add fix for RHEL-87525. --- ...x-deadlock-in-master_notify_submount.patch | 66 ++++++++++++++ ...-ordering-deadlock-in-expire_cleanup.patch | 77 ++++++++++++++++ autofs-5.1.9-fix-submount-shutdown-race.patch | 89 +++++++++++++++++++ autofs.spec | 14 ++- 4 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 autofs-5.1.9-fix-deadlock-in-master_notify_submount.patch create mode 100644 autofs-5.1.9-fix-lock-ordering-deadlock-in-expire_cleanup.patch create mode 100644 autofs-5.1.9-fix-submount-shutdown-race.patch diff --git a/autofs-5.1.9-fix-deadlock-in-master_notify_submount.patch b/autofs-5.1.9-fix-deadlock-in-master_notify_submount.patch new file mode 100644 index 0000000..2e9630d --- /dev/null +++ b/autofs-5.1.9-fix-deadlock-in-master_notify_submount.patch @@ -0,0 +1,66 @@ +autofs-5.1.9 - fix deadlock in master_notify_submount() + +From: Ian Kent + +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 +--- + 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); + } diff --git a/autofs-5.1.9-fix-lock-ordering-deadlock-in-expire_cleanup.patch b/autofs-5.1.9-fix-lock-ordering-deadlock-in-expire_cleanup.patch new file mode 100644 index 0000000..5202139 --- /dev/null +++ b/autofs-5.1.9-fix-lock-ordering-deadlock-in-expire_cleanup.patch @@ -0,0 +1,77 @@ +autofs-5.1.9 - fix lock ordering deadlock in expire_cleanup() + +From: Ian Kent + +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 +--- + 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; + } + diff --git a/autofs-5.1.9-fix-submount-shutdown-race.patch b/autofs-5.1.9-fix-submount-shutdown-race.patch new file mode 100644 index 0000000..51b3118 --- /dev/null +++ b/autofs-5.1.9-fix-submount-shutdown-race.patch @@ -0,0 +1,89 @@ +autofs-5.1.9 - fix submount shutdown race + +From: Ian Kent + +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 +--- + 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); + } diff --git a/autofs.spec b/autofs.spec index c488f50..be596db 100644 --- a/autofs.spec +++ b/autofs.spec @@ -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 - 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 - 1:5.1.9-11 - Bump release for October 2024 mass rebuild: Resolves: RHEL-64018