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(-) diff --git a/CHANGELOG b/CHANGELOG index ae8730de3..36751885a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -31,6 +31,7 @@ - fix deadlock in master_notify_submount(). - remove mounts_mutex macros. - fix lock not released on error in mnts_add_amdmount(). +- fix lock ordering deadlock in expire_cleanup(). 02/11/2023 autofs-5.1.9 - fix kernel mount status notification. diff --git a/daemon/state.c b/daemon/state.c index 4e26bc68f..dbd22be61 100644 --- a/daemon/state.c +++ b/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; }