From 4c6235a8ea761acf02384af872980dcb4fc72755 Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Tue, 29 Nov 2022 10:47:46 +0800 Subject: [PATCH] - add fixes for bz2147491. --- ....1.8-coverity-fix-for-invalid-access.patch | 32 +++ ...8-fix-deadlock-with-hosts-map-reload.patch | 169 +++++++++++ ....8-fix-hosts-map-deadlock-on-restart.patch | 97 +++++++ ...x-memory-leak-in-update_hosts_mounts.patch | 53 ++++ ...x-parse-module-instance-mutex-naming.patch | 183 ++++++++++++ ...ialise-lookup-module-open-and-reinit.patch | 272 ++++++++++++++++++ autofs.spec | 25 +- 7 files changed, 830 insertions(+), 1 deletion(-) create mode 100644 autofs-5.1.8-coverity-fix-for-invalid-access.patch create mode 100644 autofs-5.1.8-fix-deadlock-with-hosts-map-reload.patch create mode 100644 autofs-5.1.8-fix-hosts-map-deadlock-on-restart.patch create mode 100644 autofs-5.1.8-fix-memory-leak-in-update_hosts_mounts.patch create mode 100644 autofs-5.1.8-fix-parse-module-instance-mutex-naming.patch create mode 100644 autofs-5.1.8-serialise-lookup-module-open-and-reinit.patch diff --git a/autofs-5.1.8-coverity-fix-for-invalid-access.patch b/autofs-5.1.8-coverity-fix-for-invalid-access.patch new file mode 100644 index 0000000..d5b8d74 --- /dev/null +++ b/autofs-5.1.8-coverity-fix-for-invalid-access.patch @@ -0,0 +1,32 @@ +autofs-5.1.8 - coverity fix for invalid access + +From: Ian Kent + +Fix invalid access in modules/parse_amd.c:do_host_mount(). + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + modules/parse_amd.c | 1 - + 2 files changed, 1 insertion(+), 1 deletion(-) + +--- autofs-5.1.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -106,6 +106,7 @@ + - fix missing unlock in sasl_do_kinit_ext_cc(). + - fix parse module instance mutex naming. + - serialise lookup module open and reinit. ++- coverity fix for invalid access. + + 25/01/2021 autofs-5.1.7 + - make bind mounts propagation slave by default. +--- autofs-5.1.7.orig/modules/parse_amd.c ++++ autofs-5.1.7/modules/parse_amd.c +@@ -1366,7 +1366,6 @@ static int do_host_mount(struct autofs_p + if (!instance) { + error(ap->logopt, MODPREFIX + "failed to create source instance for hosts map"); +- close_lookup(lookup); + goto out; + } + } diff --git a/autofs-5.1.8-fix-deadlock-with-hosts-map-reload.patch b/autofs-5.1.8-fix-deadlock-with-hosts-map-reload.patch new file mode 100644 index 0000000..0a5ba63 --- /dev/null +++ b/autofs-5.1.8-fix-deadlock-with-hosts-map-reload.patch @@ -0,0 +1,169 @@ +autofs-5.1.8 - fix deadlock with hosts map reload + +From: Ian Kent + +When reloading maps the hosts map calls lookup method ->parse_mount() +for each multi-mount root entry in the map (each host) while holding +the cache read lock which leads to a cache lock deadlock. + +Remove the need to hold the cache read lock by creating an independent +list of entries for the update so the lock doesn't need to be taken. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + modules/lookup_hosts.c | 100 ++++++++++++++++++++++++++++++++++++++++--------- + 2 files changed, 83 insertions(+), 18 deletions(-) + +--- autofs-5.1.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -108,6 +108,7 @@ + - serialise lookup module open and reinit. + - coverity fix for invalid access. + - fix hosts map deadlock on restart. ++- fix deadlock with hosts map reload. + + 25/01/2021 autofs-5.1.7 + - make bind mounts propagation slave by default. +--- autofs-5.1.7.orig/modules/lookup_hosts.c ++++ autofs-5.1.7/modules/lookup_hosts.c +@@ -201,10 +201,72 @@ static int do_parse_mount(struct autofs_ + return NSS_STATUS_SUCCESS; + } + ++struct update_context { ++ char *key; ++ int key_len; ++ char *entry; ++ struct update_context *next; ++}; ++ ++static int add_update_entry(struct update_context **entries, struct mapent *me) ++{ ++ struct update_context *upd; ++ char *key, *ent; ++ ++ key = strdup(me->key); ++ if (!key) ++ return 0; ++ ++ ent = strdup(me->mapent); ++ if (!ent) { ++ free(key); ++ return 0; ++ } ++ ++ upd = malloc(sizeof(struct update_context)); ++ if (!upd) { ++ free(ent); ++ free(key); ++ return 0; ++ } ++ ++ upd->key = key; ++ upd->key_len = me->len; ++ upd->entry = ent; ++ upd->next = NULL; ++ if (*entries) ++ (*entries)->next = upd; ++ *entries = upd; ++ ++ return 1; ++} ++ ++static void free_update_entries(struct update_context *entries) ++{ ++ struct update_context *this = entries; ++ ++ while (this) { ++ struct update_context *next = this->next; ++ free(this->key); ++ free(this->entry); ++ free(this); ++ this = next; ++ } ++} ++ ++void entries_cleanup(void *arg) ++{ ++ struct update_context *entries = arg; ++ ++ free_update_entries(entries); ++} ++ + static void update_hosts_mounts(struct autofs_point *ap, + struct map_source *source, time_t age, + struct lookup_context *ctxt) + { ++ struct update_context *head = NULL; ++ struct update_context *entries = NULL; + struct mapent_cache *mc; + struct mapent *me; + char *mapent; +@@ -212,6 +274,8 @@ static void update_hosts_mounts(struct a + + mc = source->mc; + ++ pthread_cleanup_push(entries_cleanup, head); ++ + pthread_cleanup_push(cache_lock_cleanup, mc); + cache_writelock(mc); + me = cache_lookup_first(mc); +@@ -224,39 +288,39 @@ static void update_hosts_mounts(struct a + + mapent = get_exports(ap, me->key); + if (mapent) { +- cache_update(mc, source, me->key, mapent, age); ++ int ret; ++ ++ ret = cache_update(mc, source, me->key, mapent, age); + free(mapent); ++ if (!IS_MM_ROOT(me)) ++ goto next; ++ if (ret != CHE_FAIL) { ++ if (!add_update_entry(&entries, me)) ++ warn(ap->logopt, MODPREFIX ++ "failed to add update entry for %s", me->key); ++ else if (!head) ++ head = entries; ++ } + } + next: + me = cache_lookup_next(mc, me); + } + pthread_cleanup_pop(1); + +- pthread_cleanup_push(cache_lock_cleanup, mc); +- cache_readlock(mc); +- me = cache_lookup_first(mc); +- while (me) { +- /* +- * Hosts map entry not yet expanded, already expired +- * or not the base of the tree +- */ +- if (!IS_MM(me) || !IS_MM_ROOT(me)) +- goto cont; +- ++ while (head) { + debug(ap->logopt, MODPREFIX +- "attempt to update exports for %s", me->key); ++ "attempt to update exports for %s", head->key); + + master_source_current_wait(ap->entry); + ap->entry->current = source; + ap->flags |= MOUNT_FLAG_REMOUNT; +- ret = ctxt->parse->parse_mount(ap, me->key, strlen(me->key), +- me->mapent, ctxt->parse->context); ++ ret = ctxt->parse->parse_mount(ap, head->key, strlen(head->key), ++ head->entry, ctxt->parse->context); + if (ret) + warn(ap->logopt, MODPREFIX +- "failed to parse mount %s", me->mapent); ++ "failed to parse mount %s", head->entry); + ap->flags &= ~MOUNT_FLAG_REMOUNT; +-cont: +- me = cache_lookup_next(mc, me); ++ head = head->next; + } + pthread_cleanup_pop(1); + } diff --git a/autofs-5.1.8-fix-hosts-map-deadlock-on-restart.patch b/autofs-5.1.8-fix-hosts-map-deadlock-on-restart.patch new file mode 100644 index 0000000..2cb65c2 --- /dev/null +++ b/autofs-5.1.8-fix-hosts-map-deadlock-on-restart.patch @@ -0,0 +1,97 @@ +autofs-5.1.8 - fix hosts map deadlock on restart + +From: Ian Kent + +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 +--- + 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); diff --git a/autofs-5.1.8-fix-memory-leak-in-update_hosts_mounts.patch b/autofs-5.1.8-fix-memory-leak-in-update_hosts_mounts.patch new file mode 100644 index 0000000..ac02f51 --- /dev/null +++ b/autofs-5.1.8-fix-memory-leak-in-update_hosts_mounts.patch @@ -0,0 +1,53 @@ +autofs-5.1.8 - fix memory leak in update_hosts_mounts() + +From: Ian Kent + +Coverity has reported a memory leak in update_hosts_mounts() introduced +by the map reload deadlock fix. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + modules/lookup_hosts.c | 13 +++++++------ + 2 files changed, 8 insertions(+), 6 deletions(-) + +--- autofs-5.1.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -109,6 +109,7 @@ + - coverity fix for invalid access. + - fix hosts map deadlock on restart. + - fix deadlock with hosts map reload. ++- fix memory leak in update_hosts_mounts(). + + 25/01/2021 autofs-5.1.7 + - make bind mounts propagation slave by default. +--- autofs-5.1.7.orig/modules/lookup_hosts.c ++++ autofs-5.1.7/modules/lookup_hosts.c +@@ -307,20 +307,21 @@ next: + } + pthread_cleanup_pop(1); + +- while (head) { ++ entries = head; ++ while (entries) { + debug(ap->logopt, MODPREFIX +- "attempt to update exports for %s", head->key); ++ "attempt to update exports for %s", entries->key); + + master_source_current_wait(ap->entry); + ap->entry->current = source; + ap->flags |= MOUNT_FLAG_REMOUNT; +- ret = ctxt->parse->parse_mount(ap, head->key, strlen(head->key), +- head->entry, ctxt->parse->context); ++ ret = ctxt->parse->parse_mount(ap, entries->key, strlen(entries->key), ++ entries->entry, ctxt->parse->context); + if (ret) + warn(ap->logopt, MODPREFIX +- "failed to parse mount %s", head->entry); ++ "failed to parse mount %s", entries->entry); + ap->flags &= ~MOUNT_FLAG_REMOUNT; +- head = head->next; ++ entries = entries->next; + } + pthread_cleanup_pop(1); + } diff --git a/autofs-5.1.8-fix-parse-module-instance-mutex-naming.patch b/autofs-5.1.8-fix-parse-module-instance-mutex-naming.patch new file mode 100644 index 0000000..2f929d8 --- /dev/null +++ b/autofs-5.1.8-fix-parse-module-instance-mutex-naming.patch @@ -0,0 +1,183 @@ +autofs-5.1.8 - fix parse module instance mutex naming + +From: Ian Kent + +The naming used for parse module instance locks is the same as that +used for map lookup instances. Rename these to make it clear they +are being used in the parse modules. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + modules/parse_amd.c | 28 ++++++++++++++-------------- + modules/parse_sun.c | 20 ++++++++++---------- + 3 files changed, 25 insertions(+), 24 deletions(-) + +--- autofs-5.1.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -104,6 +104,7 @@ + - dont use initgroups() at spawn. + - fix invalid tsv access. + - fix missing unlock in sasl_do_kinit_ext_cc(). ++- fix parse module instance mutex naming. + + 25/01/2021 autofs-5.1.7 + - make bind mounts propagation slave by default. +--- autofs-5.1.7.orig/modules/parse_amd.c ++++ autofs-5.1.7/modules/parse_amd.c +@@ -39,18 +39,18 @@ int parse_version = AUTOFS_PARSE_VERSION + + static struct mount_mod *mount_nfs = NULL; + static int init_ctr = 0; +-static pthread_mutex_t instance_mutex = PTHREAD_MUTEX_INITIALIZER; ++static pthread_mutex_t parse_instance_mutex = PTHREAD_MUTEX_INITIALIZER; + +-static void instance_mutex_lock(void) ++static void parse_instance_mutex_lock(void) + { +- int status = pthread_mutex_lock(&instance_mutex); ++ int status = pthread_mutex_lock(&parse_instance_mutex); + if (status) + fatal(status); + } + +-static void instance_mutex_unlock(void) ++static void parse_instance_mutex_unlock(void) + { +- int status = pthread_mutex_unlock(&instance_mutex); ++ int status = pthread_mutex_unlock(&parse_instance_mutex); + if (status) + fatal(status); + } +@@ -112,7 +112,7 @@ int parse_init(int argc, const char *con + + /* We only need this once. NFS mounts are so common that we cache + this module. */ +- instance_mutex_lock(); ++ parse_instance_mutex_lock(); + if (mount_nfs) + init_ctr++; + else { +@@ -121,11 +121,11 @@ int parse_init(int argc, const char *con + } else { + kill_context(ctxt); + *context = NULL; +- instance_mutex_unlock(); ++ parse_instance_mutex_unlock(); + return 1; + } + } +- instance_mutex_unlock(); ++ parse_instance_mutex_unlock(); + + return 0; + } +@@ -1358,11 +1358,11 @@ static int do_host_mount(struct autofs_p + argc = 1; + } + +- instance_mutex_lock(); ++ parse_instance_mutex_lock(); + status = open_lookup("hosts", MODPREFIX, NULL, argc, pargv, &lookup); + if (status != NSS_STATUS_SUCCESS) { + debug(ap->logopt, "open lookup module hosts failed"); +- instance_mutex_unlock(); ++ parse_instance_mutex_unlock(); + goto out; + } + +@@ -1374,13 +1374,13 @@ static int do_host_mount(struct autofs_p + if (!instance) { + error(ap->logopt, MODPREFIX + "failed to create source instance for hosts map"); +- instance_mutex_unlock(); ++ parse_instance_mutex_unlock(); + close_lookup(lookup); + goto out; + } + } + instance->lookup = lookup; +- instance_mutex_unlock(); ++ parse_instance_mutex_unlock(); + + cache_writelock(source->mc); + me = cache_lookup_distinct(source->mc, name); +@@ -2373,12 +2373,12 @@ int parse_done(void *context) + int rv = 0; + struct parse_context *ctxt = (struct parse_context *) context; + +- instance_mutex_lock(); ++ parse_instance_mutex_lock(); + if (--init_ctr == 0) { + rv = close_mount(mount_nfs); + mount_nfs = NULL; + } +- instance_mutex_unlock(); ++ parse_instance_mutex_unlock(); + if (ctxt) + kill_context(ctxt); + +--- autofs-5.1.7.orig/modules/parse_sun.c ++++ autofs-5.1.7/modules/parse_sun.c +@@ -41,18 +41,18 @@ int parse_version = AUTOFS_PARSE_VERSION + + static struct mount_mod *mount_nfs = NULL; + static int init_ctr = 0; +-static pthread_mutex_t instance_mutex = PTHREAD_MUTEX_INITIALIZER; ++static pthread_mutex_t parse_instance_mutex = PTHREAD_MUTEX_INITIALIZER; + +-static void instance_mutex_lock(void) ++static void parse_instance_mutex_lock(void) + { +- int status = pthread_mutex_lock(&instance_mutex); ++ int status = pthread_mutex_lock(&parse_instance_mutex); + if (status) + fatal(status); + } + +-static void instance_mutex_unlock(void) ++static void parse_instance_mutex_unlock(void) + { +- int status = pthread_mutex_unlock(&instance_mutex); ++ int status = pthread_mutex_unlock(&parse_instance_mutex); + if (status) + fatal(status); + } +@@ -424,7 +424,7 @@ int parse_init(int argc, const char *con + + /* We only need this once. NFS mounts are so common that we cache + this module. */ +- instance_mutex_lock(); ++ parse_instance_mutex_lock(); + if (mount_nfs) + init_ctr++; + else { +@@ -432,11 +432,11 @@ int parse_init(int argc, const char *con + init_ctr++; + } else { + kill_context(ctxt); +- instance_mutex_unlock(); ++ parse_instance_mutex_unlock(); + return 1; + } + } +- instance_mutex_unlock(); ++ parse_instance_mutex_unlock(); + + *context = (void *) ctxt; + +@@ -1728,12 +1728,12 @@ int parse_done(void *context) + int rv = 0; + struct parse_context *ctxt = (struct parse_context *) context; + +- instance_mutex_lock(); ++ parse_instance_mutex_lock(); + if (--init_ctr == 0) { + rv = close_mount(mount_nfs); + mount_nfs = NULL; + } +- instance_mutex_unlock(); ++ parse_instance_mutex_unlock(); + if (ctxt) + kill_context(ctxt); + diff --git a/autofs-5.1.8-serialise-lookup-module-open-and-reinit.patch b/autofs-5.1.8-serialise-lookup-module-open-and-reinit.patch new file mode 100644 index 0000000..0f7425d --- /dev/null +++ b/autofs-5.1.8-serialise-lookup-module-open-and-reinit.patch @@ -0,0 +1,272 @@ +autofs-5.1.8 - serialise lookup module open and reinit + +From: Ian Kent + +Add a map source lock to serialise map setting and use of module +structure fields such as the context. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + daemon/lookup.c | 35 +++++++++++++++++++++-------------- + daemon/master.c | 43 +++++++++++++++++++++++++++++++++++++++++++ + include/master.h | 5 +++++ + modules/parse_amd.c | 26 +++++++++++++++----------- + 5 files changed, 85 insertions(+), 25 deletions(-) + +--- autofs-5.1.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -105,6 +105,7 @@ + - fix invalid tsv access. + - fix missing unlock in sasl_do_kinit_ext_cc(). + - fix parse module instance mutex naming. ++- serialise lookup module open and reinit. + + 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 +@@ -318,28 +318,27 @@ static int do_read_map(struct autofs_poi + struct lookup_mod *lookup; + int status; + +- lookup = NULL; +- master_source_writelock(ap->entry); ++ pthread_cleanup_push(map_module_lock_cleanup, map); ++ map_module_writelock(map); + if (!map->lookup) { + status = open_lookup(map->type, "", map->format, + map->argc, map->argv, &lookup); +- if (status != NSS_STATUS_SUCCESS) { +- master_source_unlock(ap->entry); ++ if (status == NSS_STATUS_SUCCESS) ++ map->lookup = lookup; ++ else + debug(ap->logopt, + "lookup module %s open failed", map->type); +- return status; +- } +- map->lookup = lookup; + } else { +- lookup = map->lookup; +- status = lookup->lookup_reinit(map->format, +- map->argc, map->argv, +- &lookup->context); ++ status = map->lookup->lookup_reinit(map->format, ++ map->argc, map->argv, ++ &map->lookup->context); + if (status) + warn(ap->logopt, + "lookup module %s reinit failed", map->type); + } +- master_source_unlock(ap->entry); ++ pthread_cleanup_pop(1); ++ if (status != NSS_STATUS_SUCCESS) ++ return status; + + if (!map->stale) + return NSS_STATUS_SUCCESS; +@@ -347,7 +346,11 @@ static int do_read_map(struct autofs_poi + master_source_current_wait(ap->entry); + ap->entry->current = map; + ++ pthread_cleanup_push(map_module_lock_cleanup, map); ++ map_module_readlock(map); ++ lookup = map->lookup; + status = lookup->lookup_read_map(ap, age, lookup->context); ++ pthread_cleanup_pop(1); + + if (status != NSS_STATUS_SUCCESS) + map->stale = 0; +@@ -804,23 +807,27 @@ 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->lookup = lookup; + } +- +- lookup = map->lookup; ++ map_module_unlock(map); + + master_source_current_wait(ap->entry); + ap->entry->current = map; + ++ map_module_readlock(map); ++ lookup = map->lookup; + status = lookup->lookup_mount(ap, name, name_len, lookup->context); ++ map_module_unlock(map); + + return status; + } +--- autofs-5.1.7.orig/daemon/master.c ++++ autofs-5.1.7/daemon/master.c +@@ -65,6 +65,34 @@ void master_mutex_lock_cleanup(void *arg + return; + } + ++void map_module_writelock(struct map_source *map) ++{ ++ int status = pthread_rwlock_wrlock(&map->module_lock); ++ if (status) ++ fatal(status); ++} ++ ++void map_module_readlock(struct map_source *map) ++{ ++ int status = pthread_rwlock_rdlock(&map->module_lock); ++ if (status) ++ fatal(status); ++} ++ ++void map_module_unlock(struct map_source *map) ++{ ++ int status = pthread_rwlock_unlock(&map->module_lock); ++ if (status) ++ fatal(status); ++} ++ ++void map_module_lock_cleanup(void *arg) ++{ ++ struct map_source *map = (struct map_source *) arg; ++ ++ map_module_unlock(map); ++} ++ + int master_add_autofs_point(struct master_mapent *entry, unsigned logopt, + unsigned nobind, unsigned ghost, int submount) + { +@@ -155,6 +183,7 @@ master_add_map_source(struct master_mape + struct map_source *source; + char *ntype, *nformat; + const char **tmpargv; ++ int status; + + source = malloc(sizeof(struct map_source)); + if (!source) +@@ -241,6 +270,10 @@ master_add_map_source(struct master_mape + + master_source_unlock(entry); + ++ status = pthread_rwlock_init(&source->module_lock, NULL); ++ if (status) ++ fatal(status); ++ + return source; + } + +@@ -330,6 +363,8 @@ master_get_map_source(struct master_mape + + static void __master_free_map_source(struct map_source *source, unsigned int free_cache) + { ++ int status; ++ + /* instance map sources are not ref counted */ + if (source->ref && --source->ref) + return; +@@ -365,6 +400,10 @@ static void __master_free_map_source(str + } + } + ++ status = pthread_rwlock_destroy(&source->module_lock); ++ if (status) ++ fatal(status); ++ + free(source); + + return; +@@ -496,6 +535,10 @@ master_add_source_instance(struct map_so + if (status) + fatal(status); + ++ status = pthread_rwlock_init(&new->module_lock, NULL); ++ if (status) ++ fatal(status); ++ + return new; + } + +--- autofs-5.1.7.orig/include/master.h ++++ autofs-5.1.7/include/master.h +@@ -35,6 +35,7 @@ struct map_source { + unsigned int stale; + unsigned int recurse; + unsigned int depth; ++ pthread_rwlock_t module_lock; + struct lookup_mod *lookup; + int argc; + const char **argv; +@@ -126,5 +127,9 @@ int __master_list_empty(struct master *) + int master_list_empty(struct master *); + int master_done(struct master *); + int master_kill(struct master *); ++void map_module_writelock(struct map_source *map); ++void map_module_readlock(struct map_source *map); ++void map_module_unlock(struct map_source *map); ++void map_module_lock_cleanup(void *arg); + + #endif +--- autofs-5.1.7.orig/modules/parse_amd.c ++++ autofs-5.1.7/modules/parse_amd.c +@@ -1358,14 +1358,6 @@ static int do_host_mount(struct autofs_p + argc = 1; + } + +- parse_instance_mutex_lock(); +- status = open_lookup("hosts", MODPREFIX, NULL, argc, pargv, &lookup); +- if (status != NSS_STATUS_SUCCESS) { +- debug(ap->logopt, "open lookup module hosts failed"); +- parse_instance_mutex_unlock(); +- goto out; +- } +- + instance = master_find_source_instance(source, + "hosts", "sun", argc, pargv); + if (!instance) { +@@ -1374,13 +1366,22 @@ static int do_host_mount(struct autofs_p + if (!instance) { + error(ap->logopt, MODPREFIX + "failed to create source instance for hosts map"); +- parse_instance_mutex_unlock(); + close_lookup(lookup); + goto out; + } + } +- instance->lookup = lookup; +- parse_instance_mutex_unlock(); ++ ++ 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; ++ } ++ map_module_unlock(instance); + + cache_writelock(source->mc); + me = cache_lookup_distinct(source->mc, name); +@@ -1391,8 +1392,11 @@ static int do_host_mount(struct autofs_p + master_source_current_wait(ap->entry); + ap->entry->current = source; + ++ map_module_readlock(instance); ++ lookup = instance->lookup; + ret = lookup->lookup_mount(ap, entry->rhost, + strlen(entry->rhost), lookup->context); ++ map_module_unlock(instance); + + if (!strcmp(name, entry->rhost)) + goto out; diff --git a/autofs.spec b/autofs.spec index 469e199..9cb05c8 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.7 -Release: 33%{?dist} +Release: 34%{?dist} Epoch: 1 License: GPLv2+ Source: https://www.kernel.org/pub/linux/daemons/autofs/v5/autofs-%{version}-2.tar.gz @@ -130,6 +130,12 @@ Patch102: autofs-5.1.8-fix-nfsv4-only-mounts-should-not-use-rpcbind.patch Patch103: autofs-5.1.8-dont-use-initgroups-at-spawn.patch Patch104: autofs-5.1.8-fix-invalid-tsv-access.patch Patch105: autofs-5.1.8-fix-missing-unlock-in-sasl_do_kinit_ext_cc.patch +Patch106: autofs-5.1.8-fix-parse-module-instance-mutex-naming.patch +Patch107: autofs-5.1.8-serialise-lookup-module-open-and-reinit.patch +Patch108: autofs-5.1.8-coverity-fix-for-invalid-access.patch +Patch109: autofs-5.1.8-fix-hosts-map-deadlock-on-restart.patch +Patch110: autofs-5.1.8-fix-deadlock-with-hosts-map-reload.patch +Patch111: autofs-5.1.8-fix-memory-leak-in-update_hosts_mounts.patch %if %{with_systemd} BuildRequires: systemd-units @@ -304,6 +310,12 @@ echo %{version}-%{release} > .version %patch103 -p1 %patch104 -p1 %patch105 -p1 +%patch106 -p1 +%patch107 -p1 +%patch108 -p1 +%patch109 -p1 +%patch110 -p1 +%patch111 -p1 %build LDFLAGS=-Wl,-z,now @@ -412,6 +424,17 @@ fi %dir /etc/auto.master.d %changelog +* Tue Nov 29 2022 Ian Kent - 1:5.1.7-34 +- bz2147491 - segfault due to lookup_mod->context address being freed + and reused while multiple threads were using it + - fix parse module instance mutex naming. + - serialise lookup module open and reinit. + - coverity fix for invalid access. + - fix hosts map deadlock on restart. + - fix deadlock with hosts map reload. + - fix memory leak in update_hosts_mounts(). +- Resolves: rhbz#2147491 + * Mon Oct 31 2022 Ian Kent - 1:5.1.7-33 - bz2131907 - autofs: missing unlock in sasl_do_kinit_ext_cc() - fix missing unlock in sasl_do_kinit_ext_cc().