Blob Blame History Raw
autofs-5.1.8 - fix hosts map deadlock on restart

From: Ian Kent <raven@themaw.net>

When starting automount(8) with a hosts map that has mounts that were
in use at the last exit a deadlock can occur.

In this case automount(8) will perform the same steps but not actually
perform the mount to re-construct the context of each mount. But, with
the hosts map, that leads to calling back into the sun parse module
while holding the map module read lock which will again try and take
the write lock.

Fix this by only taking the write lock in the mount code path if the
module handle has not already been opened.

Signed-off-by: Ian Kent <raven@themaw.net>
---
 CHANGELOG           |    1 +
 daemon/lookup.c     |   22 ++++++++++++----------
 modules/parse_amd.c |   18 ++++++++++--------
 3 files changed, 23 insertions(+), 18 deletions(-)

--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -107,6 +107,7 @@
 - fix parse module instance mutex naming.
 - serialise lookup module open and reinit.
 - coverity fix for invalid access.
+- fix hosts map deadlock on restart.
 
 25/01/2021 autofs-5.1.7
 - make bind mounts propagation slave by default.
--- autofs-5.1.7.orig/daemon/lookup.c
+++ autofs-5.1.7/daemon/lookup.c
@@ -807,19 +807,21 @@ int do_lookup_mount(struct autofs_point
 	struct lookup_mod *lookup;
 	int status;
 
-	map_module_writelock(map);
 	if (!map->lookup) {
-		status = open_lookup(map->type, "",
-				     map->format, map->argc, map->argv, &lookup);
-		if (status != NSS_STATUS_SUCCESS) {
-			map_module_unlock(map);
-			debug(ap->logopt,
-			      "lookup module %s open failed", map->type);
-			return status;
+		map_module_writelock(map);
+		if (!map->lookup) {
+			status = open_lookup(map->type, "",
+					     map->format, map->argc, map->argv, &lookup);
+			if (status != NSS_STATUS_SUCCESS) {
+				map_module_unlock(map);
+				debug(ap->logopt,
+				      "lookup module %s open failed", map->type);
+				return status;
+			}
+			map->lookup = lookup;
 		}
-		map->lookup = lookup;
+		map_module_unlock(map);
 	}
-	map_module_unlock(map);
 
 	master_source_current_wait(ap->entry);
 	ap->entry->current = map;
--- autofs-5.1.7.orig/modules/parse_amd.c
+++ autofs-5.1.7/modules/parse_amd.c
@@ -1370,17 +1370,19 @@ static int do_host_mount(struct autofs_p
 		}
 	}
 
-	map_module_writelock(instance);
 	if (!instance->lookup) {
-		status = open_lookup("hosts", MODPREFIX, NULL, argc, pargv, &lookup);
-		if (status != NSS_STATUS_SUCCESS) {
-			map_module_unlock(instance);
-			debug(ap->logopt, "open lookup module hosts failed");
-			goto out;
+		map_module_writelock(instance);
+		if (!instance->lookup) {
+			status = open_lookup("hosts", MODPREFIX, NULL, argc, pargv, &lookup);
+			if (status != NSS_STATUS_SUCCESS) {
+				map_module_unlock(instance);
+				debug(ap->logopt, "open lookup module hosts failed");
+				goto out;
+			}
+			instance->lookup = lookup;
 		}
-		instance->lookup = lookup;
+		map_module_unlock(instance);
 	}
-	map_module_unlock(instance);
 
 	cache_writelock(source->mc);
 	me = cache_lookup_distinct(source->mc, name);