rpms/autofs/devel autofs-5.0.4-always-read-file-maps.patch, NONE, 1.1 autofs-5.0.4-code-analysis-corrections.patch, NONE, 1.1 autofs-5.0.4-configure-libtirpc.patch, NONE, 1.1 autofs-5.0.4-easy-alloca-replacements.patch, NONE, 1.1 autofs-5.0.4-fix-hosts-map-use-after-free.patch, NONE, 1.1 autofs-5.0.4-force-unlink-umount.patch, NONE, 1.1 autofs-5.0.4-ipv6-name-and-address-support.patch, NONE, 1.1 autofs-5.0.4-ipv6-parse.patch, NONE, 1.1 autofs-5.0.4-library-reload-fix-update.patch, NONE, 1.1 autofs-5.0.4-make-MAX_ERR_BUF-and-PARSE_MAX_BUF-use-easier-to-audit.patch, NONE, 1.1 autofs-5.0.4-renew-sasl-creds-upon-reconnect-fail.patch, NONE, 1.1 autofs-5.0.4-uris-list-locking-fix.patch, NONE, 1.1 autofs.spec, 1.265, 1.266

Ian Kent iankent at fedoraproject.org
Mon Feb 16 04:01:40 UTC 2009


Author: iankent

Update of /cvs/pkgs/rpms/autofs/devel
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv24816

Modified Files:
	autofs.spec 
Added Files:
	autofs-5.0.4-always-read-file-maps.patch 
	autofs-5.0.4-code-analysis-corrections.patch 
	autofs-5.0.4-configure-libtirpc.patch 
	autofs-5.0.4-easy-alloca-replacements.patch 
	autofs-5.0.4-fix-hosts-map-use-after-free.patch 
	autofs-5.0.4-force-unlink-umount.patch 
	autofs-5.0.4-ipv6-name-and-address-support.patch 
	autofs-5.0.4-ipv6-parse.patch 
	autofs-5.0.4-library-reload-fix-update.patch 
	autofs-5.0.4-make-MAX_ERR_BUF-and-PARSE_MAX_BUF-use-easier-to-audit.patch 
	autofs-5.0.4-renew-sasl-creds-upon-reconnect-fail.patch 
	autofs-5.0.4-uris-list-locking-fix.patch 
Log Message:
* Mon Feb 16 2009 Ian Kent <ikent at redhat.com> - 5.0.4-9
- fix hosts map use after free.
- fix uri list locking (again).
- check for stale SASL credentials upon connect fail.
- add "forcestart" and "forcerestart" init script options to allow
  use of 5.0.3 strartup behavior if required.
- always read entire file map into cache to speed lookups.
- make MAX_ERR_BUF and PARSE_MAX_BUF use easier to audit.
- make some easy alloca replacements.
- update to configure libtirpc if present.
- update to provide ipv6 name and address support.
- update to provide ipv6 address parsing.


autofs-5.0.4-always-read-file-maps.patch:

--- NEW FILE autofs-5.0.4-always-read-file-maps.patch ---
autofs-5.0.4 - always read file maps

From: Ian Kent <raven at themaw.net>

autofs tries to not load an entire map into the internal cache unless it
has to. For maps that do get loaded into the cache it relies on checks to
work out if a map is up to date in order to trigger a map read. This is
fine for maps that can do direct key lookups but file maps need to do a
linear search through the file when locating an entry for a key. For large
maps this can be a huge overhead. This patch make autofs always load file
based maps at start and makes use of the map file mtime to discover if the
cache needs to be refreshed.
---

 CHANGELOG             |    1 +
 daemon/lookup.c       |    9 +++++--
 modules/lookup_file.c |   65 ++++++++++++++++---------------------------------
 3 files changed, 28 insertions(+), 47 deletions(-)


diff --git a/CHANGELOG b/CHANGELOG
index d4dd70b..afd1335 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -14,6 +14,7 @@
 - check for stale SASL credentials upon connect fail.
 - add "forcestart" and "forcerestart" init script options to allow
   use of 5.0.3 strartup behavior if required.
+- always read entire file map into cache to speed lookups.
 
 4/11/2008 autofs-5.0.4
 -----------------------
diff --git a/daemon/lookup.c b/daemon/lookup.c
index 741d846..e034348 100644
--- a/daemon/lookup.c
+++ b/daemon/lookup.c
@@ -283,10 +283,13 @@ static int do_read_map(struct autofs_point *ap, struct map_source *map, time_t a
 	 * for the fail cases to function correctly and to cache the
 	 * lookup handle.
 	 *
-	 * We always need to whole map for direct mounts in order to
-	 * mount the triggers.
+	 * We always need to read the whole map for direct mounts in
+	 * order to mount the triggers. We also want to read the whole
+	 * map if it's a file map to avoid potentially lengthy linear
+	 * file scanning.
 	 */
-	if (!(ap->flags & MOUNT_FLAG_GHOST) && ap->type != LKP_DIRECT)
+	if (strcmp(map->type, "file") &&
+	    !(ap->flags & MOUNT_FLAG_GHOST) && ap->type != LKP_DIRECT)
 		return NSS_STATUS_SUCCESS;
 
 	if (!map->stale)
diff --git a/modules/lookup_file.c b/modules/lookup_file.c
index 95b9f6f..aafeb8b 100644
--- a/modules/lookup_file.c
+++ b/modules/lookup_file.c
@@ -44,7 +44,6 @@ typedef enum { esc_none, esc_char, esc_val, esc_all } ESCAPES;
 
 struct lookup_context {
 	const char *mapname;
-	time_t mtime;
 	struct parse_mod *parse;
 };
 
@@ -54,7 +53,6 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 {
 	struct lookup_context *ctxt;
 	char buf[MAX_ERR_BUF];
-	struct stat st;
 
 	*context = NULL;
 
@@ -87,15 +85,6 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 		return 1;
 	}
 
-	if (stat(ctxt->mapname, &st)) {
-		free(ctxt);
-		logmsg(MODPREFIX "file map %s, could not stat",
-		     argv[0]);
-		return 1;
-	}
-		
-	ctxt->mtime = st.st_mtime;
-
 	if (!mapfmt)
 		mapfmt = MAPFMT_DEFAULT;
 
@@ -391,9 +380,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 	int blen;
 	char *path;
 	char *ent;
-	struct stat st;
 	FILE *f;
-	int fd;
 	unsigned int path_len, ent_len;
 	int entry, cur_state;
 
@@ -428,8 +415,6 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 		return NSS_STATUS_UNAVAIL;
 	}
 
-	fd = fileno(f);
-
 	while(1) {
 		entry = read_one(logopt, f, path, &path_len, ent, &ent_len);
 		if (!entry) {
@@ -504,13 +489,6 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 			break;
 	}
 
-	if (fstat(fd, &st)) {
-		crit(logopt, MODPREFIX "file map %s, could not stat",
-		       ctxt->mapname);
-		return NSS_STATUS_UNAVAIL;
-	}
-	ctxt->mtime = st.st_mtime;
-
 	fclose(f);
 
 	return NSS_STATUS_SUCCESS;
@@ -642,9 +620,7 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
 	struct mapent_cache *mc;
 	char *key;
 	char *mapent;
-	struct stat st;
 	FILE *f;
-	int fd;
 	unsigned int k_len, m_len;
 	int entry;
 
@@ -684,8 +660,6 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
 		return NSS_STATUS_UNAVAIL;
 	}
 
-	fd = fileno(f);
-
 	while(1) {
 		entry = read_one(ap->logopt, f, key, &k_len, mapent, &m_len);
 		if (!entry) {
@@ -748,13 +722,6 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
 			break;
 	}
 
-	if (fstat(fd, &st)) {
-		crit(ap->logopt,
-		     MODPREFIX "file map %s, could not stat",
-		     ctxt->mapname);
-		return NSS_STATUS_UNAVAIL;
-	}
-	ctxt->mtime = st.st_mtime;
 	source->age = age;
 
 	fclose(f);
@@ -951,9 +918,6 @@ static int check_map_indirect(struct autofs_point *ap,
 	if (ret == CHE_FAIL)
 		return NSS_STATUS_NOTFOUND;
 
-	if (ret & CHE_UPDATED)
-		source->stale = 1;
-
 	pthread_cleanup_push(cache_lock_cleanup, mc);
 	cache_writelock(mc);
 	exists = cache_lookup_distinct(mc, key);
@@ -963,7 +927,6 @@ static int check_map_indirect(struct autofs_point *ap,
 			free(exists->mapent);
 			exists->mapent = NULL;
 			exists->status = 0;
-			source->stale = 1;
 		}
 	}
 	pthread_cleanup_pop(1);
@@ -985,14 +948,8 @@ static int check_map_indirect(struct autofs_point *ap,
 		we = cache_lookup_distinct(mc, "*");
 		if (we) {
 			/* Wildcard entry existed and is now gone */
-			if (we->source == source && (wild & CHE_MISSING)) {
+			if (we->source == source && (wild & CHE_MISSING))
 				cache_delete(mc, "*");
-				source->stale = 1;
-			}
-		} else {
-			/* Wildcard not in map but now is */
-			if (wild & (CHE_OK | CHE_UPDATED))
-				source->stale = 1;
 		}
 		pthread_cleanup_pop(1);
 
@@ -1062,9 +1019,28 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 	 * we never know about it.
 	 */
 	if (ap->type == LKP_INDIRECT && *key != '/') {
+		struct stat st;
 		char *lkp_key;
 
+		/*
+		 * We can skip the map lookup and cache update altogether
+		 * if we know the map hasn't been modified since it was
+		 * last read. If it has then we can mark the map stale
+		 * so a re-read is triggered following the lookup.
+		 */
+		if (stat(ctxt->mapname, &st)) {
+			error(ap->logopt, MODPREFIX
+			      "file map %s, could not stat", ctxt->mapname);
+			return NSS_STATUS_UNAVAIL;
+		}
+
 		cache_readlock(mc);
+		me = cache_lookup_first(mc);
+		if (me && st.st_mtime <= me->age)
+			goto do_cache_lookup;
+		else
+			source->stale = 1;
+
 		me = cache_lookup_distinct(mc, key);
 		if (me && me->multi)
 			lkp_key = strdup(me->multi->key);
@@ -1088,6 +1064,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 	}
 
 	cache_readlock(mc);
+do_cache_lookup:
 	me = cache_lookup(mc, key);
 	/* Stale mapent => check for entry in alternate source or wildcard */
 	if (me && !me->mapent) {

autofs-5.0.4-code-analysis-corrections.patch:

--- NEW FILE autofs-5.0.4-code-analysis-corrections.patch ---
autofs-5.0.4 - code analysis corrections

From: Ian Kent <raven at themaw.net>

Several mistakes have been reported by Paul Wankadia <junyer at google.com>:
- a malloc(3) allocation return was not being checked in make_fullpath().
- a double free and a use after free was identified in lookup_prune_cache().
- off-by-one buffer overflow in lib/macros.c:macro_parse_globalvar().
- several potential buffer overflows in modules/parse_hesiod.c.
- double free in daemon/indirect.c:do_mount_autofs_indirect().
- bogus struct name used for sizeof in lib/cache.c:cache_init() and
  lib/cache.c:cache_init_null_cache().
- in daemon/direct.c:handle_packet_expire_direct master_unlock_mutex() not
  needed and mutexes not unlocked for file descriptor fail case.
- in modules/lookup_multi.c:lookup_init() struct module_info array not
  checked before free for allocation failure case.
- in modules/lookup_program.c:lookup_mount() mapent not freed on cache update failure.
- in modules/mount_nfs.c allocation of mount location not checked.
- in modules/parse_sun.c:parse_mapent() mount location not freed on syntax error.
- in modules/parse_sun.c:parse_mount() mount location not freed on syntax error.
- in modules/parse_sun.c:parse_init() a malloc is not checked and the
  handling of the fail case is poor.
- in lib/mounts.c:tree_make_mnt_tree() variable ent is not freed on ent->path
  alloc fail.
- in modules/replicated.c:add_host() NULL pointer dereference.
- add missing pthread_attr_destroy() in lib/alarm.c:alarm_start_handler().
- add missing pthread_attr_destroy() in daemon/state.c:st_start_handler().
- add missing fclose() in lib/defaults.c:*defaults_get_searchdns().
- add missing close()es in modules/mount_changer.c:swapCD().
---

 daemon/direct.c          |    6 ++-
 daemon/indirect.c        |    3 +-
 daemon/lookup.c          |   20 +++++-------
 daemon/state.c           |    6 ++-
 lib/alarm.c              |    6 ++-
 lib/cache.c              |    4 +-
 lib/defaults.c           |    1 +
 lib/macros.c             |    2 +
 lib/mounts.c             |    5 ++-
 modules/lookup_multi.c   |   15 +++++----
 modules/lookup_program.c |    4 ++
 modules/mount_changer.c  |    2 +
 modules/mount_nfs.c      |    5 +++
 modules/parse_hesiod.c   |   79 ++++++++++++++++++++++++++++++++++++++++------
 modules/parse_sun.c      |   18 ++++++----
 modules/replicated.c     |    2 +
 16 files changed, 123 insertions(+), 55 deletions(-)


diff --git a/daemon/direct.c b/daemon/direct.c
index 2d979f1..fc3c969 100644
--- a/daemon/direct.c
+++ b/daemon/direct.c
@@ -1088,7 +1088,6 @@ int handle_packet_expire_direct(struct autofs_point *ap, autofs_packet_expire_di
 		crit(ap->logopt, "can't find map entry for (%lu,%lu)",
 		    (unsigned long) pkt->dev, (unsigned long) pkt->ino);
 		master_source_unlock(ap->entry);
-		master_mutex_unlock();
 		pthread_setcancelstate(state, NULL);
 		return 1;
 	}
@@ -1098,8 +1097,9 @@ int handle_packet_expire_direct(struct autofs_point *ap, autofs_packet_expire_di
 		int ioctlfd;
 		ops->open(ap->logopt, &ioctlfd, me->dev, me->key);
 		if (ioctlfd == -1) {
-			crit(ap->logopt, "can't open ioctlfd for %s",
-			     me->key);
+			crit(ap->logopt, "can't open ioctlfd for %s", me->key);
+			cache_unlock(mc);
+			master_source_unlock(ap->entry);
 			pthread_setcancelstate(state, NULL);
 			return 1;
 		}
diff --git a/daemon/indirect.c b/daemon/indirect.c
index 2ccbc53..f40c393 100644
--- a/daemon/indirect.c
+++ b/daemon/indirect.c
@@ -159,6 +159,7 @@ static int do_mount_autofs_indirect(struct autofs_point *ap, const char *root)
 	}
 
 	free(options);
+	options = NULL;
 
 	ret = stat(root, &st);
 	if (ret == -1) {
@@ -167,8 +168,6 @@ static int do_mount_autofs_indirect(struct autofs_point *ap, const char *root)
 		goto out_umount;
 	}
 
-	options = NULL;
-
 	if (ops->open(ap->logopt, &ap->ioctlfd, st.st_dev, root)) {
 		crit(ap->logopt,
 		     "failed to create ioctl fd for autofs path %s", ap->path);
diff --git a/daemon/lookup.c b/daemon/lookup.c
index e034348..fd2ce55 100644
--- a/daemon/lookup.c
+++ b/daemon/lookup.c
@@ -1001,12 +1001,16 @@ static char *make_fullpath(const char *root, const char *key)
 		if (l > KEY_MAX_LEN)
 			return NULL;
 		path = malloc(l);
+		if (!path)
+			return NULL;
 		strcpy(path, key);
 	} else {
 		l = strlen(key) + 1 + strlen(root) + 1;
 		if (l > KEY_MAX_LEN)
 			return NULL;
 		path = malloc(l);
+		if (!path)
+			return NULL;
 		sprintf(path, "%s/%s", root, key);
 	}
 	return path;
@@ -1076,10 +1080,6 @@ int lookup_prune_cache(struct autofs_point *ap, time_t age)
 			this = cache_lookup_distinct(mc, key);
 			if (!this) {
 				cache_unlock(mc);
-				free(key);
-				if (next_key)
-					free(next_key);
-				free(path);
 				goto next;
 			}
 
@@ -1097,18 +1097,14 @@ int lookup_prune_cache(struct autofs_point *ap, time_t age)
 			}
 			cache_unlock(mc);
 
-			if (!next_key) {
-				free(key);
-				free(path);
-				cache_readlock(mc);
-				continue;
-			}
 next:
 			cache_readlock(mc);
-			me = cache_lookup_distinct(mc, next_key);
+			if (next_key) {
+				me = cache_lookup_distinct(mc, next_key);
+				free(next_key);
+			}
 			free(key);
 			free(path);
-			free(next_key);
 		}
 		pthread_cleanup_pop(1);
 		map->stale = 0;
diff --git a/daemon/state.c b/daemon/state.c
index cd63be1..606743b 100644
--- a/daemon/state.c
+++ b/daemon/state.c
@@ -1140,9 +1140,9 @@ int st_start_handler(void)
 	}
 
 	status = pthread_create(&thid, pattrs, st_queue_handler, NULL);
-	if (status)
-		return 0;
 
-	return 1;
+	pthread_attr_destroy(pattrs);
+
+	return !status;
 }
 
diff --git a/lib/alarm.c b/lib/alarm.c
index 1e32291..46df38a 100755
--- a/lib/alarm.c
+++ b/lib/alarm.c
@@ -238,9 +238,9 @@ int alarm_start_handler(void)
 	}
 
 	status = pthread_create(&thid, pattrs, alarm_handler, NULL);
-	if (status)
-	 	return 0;
 
-	return 1;
+	pthread_attr_destroy(pattrs);
+
+	return !status;
 }
 
diff --git a/lib/cache.c b/lib/cache.c
index edb3192..4cb4582 100644
--- a/lib/cache.c
+++ b/lib/cache.c
@@ -192,7 +192,7 @@ struct mapent_cache *cache_init(struct autofs_point *ap, struct map_source *map)
 
 	mc->size = defaults_get_map_hash_table_size();
 
-	mc->hash = malloc(mc->size * sizeof(struct entry *));
+	mc->hash = malloc(mc->size * sizeof(struct mapent *));
 	if (!mc->hash) {
 		free(mc);
 		return NULL;
@@ -243,7 +243,7 @@ struct mapent_cache *cache_init_null_cache(struct master *master)
 
 	mc->size = NULL_MAP_HASHSIZE;
 
-	mc->hash = malloc(mc->size * sizeof(struct entry *));
+	mc->hash = malloc(mc->size * sizeof(struct mapent *));
 	if (!mc->hash) {
 		free(mc);
 		return NULL;
diff --git a/lib/defaults.c b/lib/defaults.c
index 0d39716..e507a59 100644
--- a/lib/defaults.c
+++ b/lib/defaults.c
@@ -565,6 +565,7 @@ struct ldap_searchdn *defaults_get_searchdns(void)
 
 			if (!new) {
 				defaults_free_searchdns(sdn);
+				fclose(f);
 				return NULL;
 			}
 
diff --git a/lib/macros.c b/lib/macros.c
index 85f9cd3..32b70bf 100644
--- a/lib/macros.c
+++ b/lib/macros.c
@@ -165,7 +165,7 @@ int macro_parse_globalvar(const char *define)
 	char buf[MAX_MACRO_STRING];
 	char *pbuf, *value;
 
-	if (strlen(define) > MAX_MACRO_STRING)
+	if (strlen(define) >= MAX_MACRO_STRING)
 		return 0;
 
 	strcpy(buf, define);
diff --git a/lib/mounts.c b/lib/mounts.c
index b98e1a4..08ca4e3 100644
--- a/lib/mounts.c
+++ b/lib/mounts.c
@@ -257,10 +257,10 @@ struct mnt_list *get_mnt_list(const char *table, const char *path, int include)
 
 		if (mptr == list)
 			list = ent;
+		else
+			last->next = ent;
 
 		ent->next = mptr;
-		if (last)
-			last->next = ent;
 
 		ent->path = malloc(len + 1);
 		if (!ent->path) {
@@ -705,6 +705,7 @@ struct mnt_list *tree_make_mnt_tree(const char *table, const char *path)
 		ent->path = malloc(len + 1);
 		if (!ent->path) {
 			endmntent(tab);
+			free(ent);
 			tree_free_mnt_tree(tree);
 			return NULL;
 		}
diff --git a/modules/lookup_multi.c b/modules/lookup_multi.c
index 1bf2e0a..6ec8434 100644
--- a/modules/lookup_multi.c
+++ b/modules/lookup_multi.c
@@ -212,14 +212,15 @@ nomem:
 	logerr(MODPREFIX "error: %s", estr);
 error_out:
 	if (ctxt) {
-		for (i = 0; i < ctxt->n; i++) {
-			if (ctxt->m[i].mod)
-				close_lookup(ctxt->m[i].mod);
-			if (ctxt->m[i].argv)
-				free_argv(ctxt->m[i].argc, ctxt->m[i].argv);
-		}
-		if (ctxt->m)
+		if (ctxt->m) {
+			for (i = 0; i < ctxt->n; i++) {
+				if (ctxt->m[i].mod)
+					close_lookup(ctxt->m[i].mod);
+				if (ctxt->m[i].argv)
+					free_argv(ctxt->m[i].argc, ctxt->m[i].argv);
+			}
 			free(ctxt->m);
+		}
 		if (ctxt->argl)
 			free(ctxt->argl);
 		free(ctxt);
diff --git a/modules/lookup_program.c b/modules/lookup_program.c
index 9878936..5b295a5 100644
--- a/modules/lookup_program.c
+++ b/modules/lookup_program.c
@@ -396,8 +396,10 @@ next:
 	cache_writelock(mc);
 	ret = cache_update(mc, source, name, mapent, time(NULL));
 	cache_unlock(mc);
-	if (ret == CHE_FAIL)
+	if (ret == CHE_FAIL) {
+		free(mapent);
 		return NSS_STATUS_UNAVAIL;
+	}
 
 	debug(ap->logopt, MODPREFIX "%s -> %s", name, mapent);
 
diff --git a/modules/mount_changer.c b/modules/mount_changer.c
index 92bb72b..c30190d 100644
--- a/modules/mount_changer.c
+++ b/modules/mount_changer.c
@@ -162,6 +162,7 @@ int swapCD(const char *device, const char *slotName)
 		logerr(MODPREFIX
 		      "Device %s is not an ATAPI compliant CD changer.",
 		      device);
+		close(fd);
 		return 1;
 	}
 
@@ -169,6 +170,7 @@ int swapCD(const char *device, const char *slotName)
 	slot = ioctl(fd, CDROM_SELECT_DISC, slot);
 	if (slot < 0) {
 		logerr(MODPREFIX "CDROM_SELECT_DISC failed");
+		close(fd);
 		return 1;
 	}
 
diff --git a/modules/mount_nfs.c b/modules/mount_nfs.c
index 20732f8..6f54f47 100644
--- a/modules/mount_nfs.c
+++ b/modules/mount_nfs.c
@@ -221,6 +221,11 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
 		/* Not a local host - do an NFS mount */
 
 		loc = malloc(strlen(this->name) + 1 + strlen(this->path) + 1);
+		if (!loc) {
+			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+			error(ap->logopt, "malloc: %s", estr);
+			return 1;
+		}
 		strcpy(loc, this->name);
 		strcat(loc, ":");
 		strcat(loc, this->path);
diff --git a/modules/parse_hesiod.c b/modules/parse_hesiod.c
index d5bb0f4..7a6a57d 100644
--- a/modules/parse_hesiod.c
+++ b/modules/parse_hesiod.c
@@ -46,6 +46,12 @@ static int parse_afs(struct autofs_point *ap,
 
 	/* Isolate the source for this AFS fs. */
 	for (i = 0; (!isspace(p[i]) && i < source_len); i++) {
+		if (!p[i]) {
+			error(ap->logopt, MODPREFIX
+			      "unexpeced end of input looking for AFS "
+			      "source: %s", p);
+			return 1;
+		}
 		source[i] = p[i];
 	}
 
@@ -56,8 +62,14 @@ static int parse_afs(struct autofs_point *ap,
 	while ((*p) && (isspace(*p)))
 		p++;
 
-	/* Isolate the source for this AFS fs. */
+	/* Isolate the options for this AFS fs. */
 	for (i = 0; (!isspace(p[i]) && i < options_len); i++) {
+		if (!p[i]) {
+			error(ap->logopt, MODPREFIX
+			      "unexpeced end of input looking for AFS "
+			      "options: %s", p);
+			return 1;
+		}
 		options[i] = p[i];
 	}
 	options[i] = 0;
@@ -106,6 +118,12 @@ static int parse_nfs(struct autofs_point *ap,
 
 	/* Isolate the remote mountpoint for this NFS fs. */
 	for (i = 0; (!isspace(p[i]) && i < (int) sizeof(mount)); i++) {
+		if (!p[i]) {
+			error(ap->logopt, MODPREFIX
+			      "unexpeced end of input looking for NFS "
+			      "mountpoint: %s", p);
+			return 1;
+		}
 		mount[i] = p[i];
 	}
 
@@ -118,15 +136,26 @@ static int parse_nfs(struct autofs_point *ap,
 
 	/* Isolate the remote host. */
 	for (i = 0; (!isspace(p[i]) && i < source_len); i++) {
+		if (!p[i]) {
+			error(ap->logopt, MODPREFIX
+			      "unexpeced end of input looking for NFS "
+			      "host: %s", p);
+			return 1;
+		}
 		source[i] = p[i];
 	}
 
 	source[i] = 0;
 	p += i;
 
+	if (strlen(source) + strlen(mount) + 2 > source_len) {
+		error(ap->logopt, MODPREFIX "entry too log for mount source");
+		return 1;
+	}
+
 	/* Append ":mountpoint" to the source to get "host:mountpoint". */
-	strncat(source, ":", source_len);
-	strncat(source, mount, source_len);
+	strcat(source, ":");
+	strcat(source, mount);
 
 	/* Skip whitespace. */
 	while ((*p) && (isspace(*p)))
@@ -134,6 +163,12 @@ static int parse_nfs(struct autofs_point *ap,
 
 	/* Isolate the mount options. */
 	for (i = 0; (!isspace(p[i]) && i < options_len); i++) {
+		if (!p[i]) {
+			error(ap->logopt, MODPREFIX
+			      "unexpeced end of input looking for NFS "
+			      "mount options: %s", p);
+			return 1;
+		}
 		options[i] = p[i];
 	}
 	options[i] = 0;
@@ -178,6 +213,12 @@ static int parse_generic(struct autofs_point *ap,
 
 	/* Isolate the source for this fs. */
 	for (i = 0; (!isspace(p[i]) && i < source_len); i++) {
+		if (!p[i]) {
+			error(ap->logopt, MODPREFIX
+			      "unexpeced end of input looking for generic "
+			      "mount source: %s", p);
+			return 1;
+		}
 		source[i] = p[i];
 	}
 
@@ -190,6 +231,12 @@ static int parse_generic(struct autofs_point *ap,
 
 	/* Isolate the mount options. */
 	for (i = 0; (!isspace(p[i]) && i < options_len); i++) {
+		if (!p[i]) {
+			error(ap->logopt, MODPREFIX
+			      "unexpeced end of input looking for generic "
+			      "mount options: %s", p);
+			return 1;
+		}
 		options[i] = p[i];
 	}
 	options[i] = 0;
@@ -227,6 +274,7 @@ int parse_mount(struct autofs_point *ap, const char *name,
 	char options[HESIOD_LEN + 1];
 	char *q;
 	const char *p;
+	int ret;
 
 	ap->entry->current = NULL;
 	master_source_current_signal(ap->entry);
@@ -250,19 +298,28 @@ int parse_mount(struct autofs_point *ap, const char *name,
 		return 1;
 	/* If it's an AFS fs... */
 	} else if (!strcasecmp(fstype, "afs"))
-		parse_afs(ap, mapent, name, name_len,
-			  source, sizeof(source), options, sizeof(options));
+		ret = parse_afs(ap, mapent, name, name_len,
+				source, sizeof(source), options,
+				sizeof(options));
 	/* If it's NFS... */
 	else if (!strcasecmp(fstype, "nfs"))
-		parse_nfs(ap, mapent, name, name_len,
-			  source, sizeof(source), options, sizeof(options));
+		ret = parse_nfs(ap, mapent, name, name_len,
+				source, sizeof(source), options,
+				sizeof(options));
 	/* Punt. */
 	else
-		parse_generic(ap, mapent, name, name_len, source, sizeof(source),
-			      options, sizeof(options));
+		ret = parse_generic(ap, mapent, name, name_len,
+				    source, sizeof(source), options,
+				    sizeof(options));
 
-	debug(ap->logopt,
-	      MODPREFIX "mount %s is type %s from %s", name, fstype, source);
+	if (ret) {
+		error(ap->logopt, MODPREFIX "failed to parse entry");
+		return 1;
+	} else {
+		debug(ap->logopt,
+		      MODPREFIX "mount %s is type %s from %s",
+		      name, fstype, source);
+	}
 
 	return do_mount(ap, ap->path, name, name_len, source, fstype, options);
 }
diff --git a/modules/parse_sun.c b/modules/parse_sun.c
index 72e51e2..ed73e46 100644
--- a/modules/parse_sun.c
+++ b/modules/parse_sun.c
@@ -379,15 +379,17 @@ int parse_init(int argc, const char *const *argv, void **context)
 			if (ctxt->optstr) {
 				noptstr =
 				    (char *) realloc(ctxt->optstr, optlen + len + 2);
-				if (!noptstr)
-					break;
-				noptstr[optlen] = ',';
-				strcpy(noptstr + optlen + 1, argv[i] + offset);
-				optlen += len + 1;
+				if (noptstr) {
+					noptstr[optlen] = ',';
+					strcpy(noptstr + optlen + 1, argv[i] + offset);
+					optlen += len + 1;
+				}
 			} else {
 				noptstr = (char *) malloc(len + 1);
-				strcpy(noptstr, argv[i] + offset);
-				optlen = len;
+				if (noptstr) {
+					strcpy(noptstr, argv[i] + offset);
+					optlen = len;
+				}
 			}
 			if (!noptstr) {
 				char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
@@ -895,6 +897,7 @@ static int parse_mapent(const char *ent, char *g_options, char **options, char *
 	if (*p == '/') {
 		warn(logopt, MODPREFIX "error location begins with \"/\"");
 		free(myoptions);
+		free(loc);
 		return 0;
 	}
 
@@ -1636,6 +1639,7 @@ int parse_mount(struct autofs_point *ap, const char *name,
 		/* Location can't begin with a '/' */
 		if (*p == '/') {
 			free(options);
+			free(loc);
 			warn(ap->logopt,
 			      MODPREFIX "error location begins with \"/\"");
 			return 1;
diff --git a/modules/replicated.c b/modules/replicated.c
index 63829a2..835af97 100644
--- a/modules/replicated.c
+++ b/modules/replicated.c
@@ -304,7 +304,7 @@ static int add_host(struct host **list, struct host *host)
 {
 	struct host *this, *last;
 
-	if (!list) {
+	if (!*list) {
 		*list = host;
 		return 1;
 	}

autofs-5.0.4-configure-libtirpc.patch:

--- NEW FILE autofs-5.0.4-configure-libtirpc.patch ---
autofs-5.0.4 - configure libtirpc

From: Ian Kent <raven at themaw.net>

With NFS over ipv6 on the way we need to update autofs to use the
libtirpc library as it provides ipv6 functionality. This change adds
configure checks to look for libtirpc (if it has been requested with
--with-libtirpc) and checks whether it has been built with ipv6
support and uses it if so.
---

 CHANGELOG           |    1 
 Makefile.conf.in    |    3 
 Makefile.rules      |    5 
 aclocal.m4          |   81 +
 autofs.spec         |    2 
 configure           | 2584 +++++++++++++++++++++++++++-------------------------
 configure.in        |    6 
 daemon/automount.c  |   13 
 include/config.h.in |    6 
 9 files changed, 1489 insertions(+), 1212 deletions(-)


--- autofs-5.0.4.orig/Makefile.conf.in
+++ autofs-5.0.4/Makefile.conf.in
@@ -49,6 +49,9 @@ YACC = @PATH_YACC@
 RPCGEN = @PATH_RPCGEN@
 RANLIB = @PATH_RANLIB@
 
+# Use libtirpc if requested and available
+TIRPCLIB = @TIRPCLIB@
+
 # Use dmalloc for memory debuging
 DMALLOCLIB = @DMALLOCLIB@
 
--- autofs-5.0.4.orig/Makefile.rules
+++ autofs-5.0.4/Makefile.rules
@@ -47,6 +47,11 @@ SOLDFLAGS = -shared
 CFLAGS += -D_REENTRANT -D_FILE_OFFSET_BITS=64
 LDFLAGS += -lpthread
 
+ifdef TIRPCLIB
+CFLAGS += -I/usr/include/tirpc
+LDFLAGS += $(TIRPCLIB)
+endif
+
 ifdef DMALLOCLIB
 LDFLAGS += $(DMALLOCLIB)
 endif
--- autofs-5.0.4.orig/aclocal.m4
+++ autofs-5.0.4/aclocal.m4
@@ -304,3 +304,84 @@ fi
 LIBS="$af_check_ldap_parse_page_control_save_libs"
 ])
 
+dnl --------------------------------------------------------------------------
+dnl AF_CHECK_LIBTIRPC_IPV6
+dnl
+dnl Use libtirpc for rpc transport
+dnl --------------------------------------------------------------------------
+AC_DEFUN([AF_CHECK_LIBTIRPC_IPV6],
+[AC_MSG_CHECKING(if libtirpc has IPv6 support)
+
+# save current flags
+af_check_libtirpc_ipv6_save_cflags="$CFLAGS"
+af_check_libtirpc_ipv6_save_ldflags="$LDFLAGS"
+CFLAGS="$CFLAGS -I/usr/include/tirpc"
+LDFLAGS="$LDFLAGS -ltirpc"
+
+AC_TRY_LINK(
+    [ #define INET6
+      #include <rpc/rpc.h> ],
+    [ CLIENT *cl;
+      struct sockaddr_in addr;
+      int fd;
+      unsigned long ul; struct timeval t; unsigned int ui;
+      cl = clntudp6_bufcreate(&addr,ul,ul,t,&fd,ui,ui); ],
+    [ af_have_libtirpc_ipv6=yes
+      AC_MSG_RESULT(yes) ],
+    [ AC_MSG_RESULT(no) ])
+
+if test "$af_have_libtirpc_ipv6" = "yes"; then
+    AC_DEFINE(INET6,1, [Use IPv6 with libtirpc])
+fi
+
+# restore flags
+CFLAGS="$af_check_libtirpc_ipv6_save_cflags"
+LDFLAGS="$af_check_libtirpc_ipv6_save_ldflags"
+])
+
+dnl --------------------------------------------------------------------------
+dnl AF_CHECK_LIBTIRPC
+dnl
+dnl Use libtirpc for rpc transport
+dnl --------------------------------------------------------------------------
+AC_DEFUN([AF_CHECK_LIBTIRPC],
+[
+# save current flags
+af_check_libtirpc_save_cflags="$CFLAGS"
+af_check_libtirpc_save_ldflags="$LDFLAGS"
+CFLAGS="$CFLAGS -I/usr/include/tirpc"
+LDFLAGS="$LDFLAGS -ltirpc"
+
+AC_TRY_LINK(
+    [ #include <rpc/rpc.h> ],
+    [ CLIENT *cl;
+      struct sockaddr_in addr;
+      int fd;
+      unsigned long ul; struct timeval t; unsigned int ui;
+      cl = clntudp_bufcreate(&addr,ul,ul,t,&fd,ui,ui); ],
+    [ af_have_libtirpc=yes
+      AC_MSG_RESULT(yes) ],
+    [ AC_MSG_RESULT(no) ])
+
+if test "$af_have_libtirpc" = "yes"; then
+    AC_DEFINE(TIRPC_WORKAROUND,1, [Use libtirpc tsd usage workaround])
+    TIRPCLIB="-ltirpc"
+fi
+
+# restore flags
+CFLAGS="$af_check_libtirpc_save_cflags"
+LDFLAGS="$af_check_libtirpc_save_ldflags"
+])
+
+AC_DEFUN([AM_WITH_LIBTIRPC],
+[AC_MSG_CHECKING([if libtirpc is requested and available])
+AC_ARG_WITH(libtirpc,
+[  --with-libtirpc         use libtirpc if available],
+[if test "$withval" = yes; then
+  AF_CHECK_LIBTIRPC()
+  AF_CHECK_LIBTIRPC_IPV6()
+else
+  AC_MSG_RESULT(no)
+fi], [AC_MSG_RESULT(no)])
+])
+
--- autofs-5.0.4.orig/autofs.spec
+++ autofs-5.0.4/autofs.spec
@@ -57,7 +57,7 @@ inkludera nätfilsystem, CD-ROM, floppydi
 echo %{version}-%{release} > .version
 
 %build
-CFLAGS="$RPM_OPT_FLAGS -Wall" ./configure --libdir=%{_libdir} --disable-mount-locking --enable-ignore-busy
+CFLAGS="$RPM_OPT_FLAGS -Wall" ./configure --libdir=%{_libdir} --disable-mount-locking --enable-ignore-busy --with-libtirpc
 CFLAGS="$RPM_OPT_FLAGS -Wall" make initdir=/etc/rc.d/init.d DONTSTRIP=1
 
 %install
--- autofs-5.0.4.orig/configure
+++ autofs-5.0.4/configure
@@ -656,6 +656,14 @@ confdir
 mapdir
 fifodir
 flagdir
+CC
+CFLAGS
+LDFLAGS
+CPPFLAGS
+ac_ct_CC
+EXEEXT
+OBJEXT
+TIRPCLIB
 DMALLOCLIB
 MOUNT
 HAVE_MOUNT
@@ -676,13 +684,6 @@ PATH_RANLIB
 RPCGEN
 PATH_RPCGEN
 XML_CONFIG
-CC
-CFLAGS
-LDFLAGS
-CPPFLAGS
-ac_ct_CC
-EXEEXT
-OBJEXT
 LIBNSL
 LIBRESOLV
 HAVE_HESIOD
@@ -1297,6 +1298,7 @@ Optional Packages:
   --with-mapdir=PATH	  look in PATH for mount maps used by the automounter
   --with-fifodir=PATH	   use PATH as the directory for fifos used by the automounter
   --with-flagdir=PATH	   use PATH as the directory for the flag file used by the automounter
+  --with-libtirpc         use libtirpc if available
   --with-dmalloc          use dmalloc, as in
 			  http://www.dmalloc.com/dmalloc.tar.gz
   --with-hesiod=DIR	  enable Hesiod support (libs and includes in DIR)
@@ -1908,60 +1910,32 @@ echo "${ECHO_T}$flagdir" >&6; }
 
 
 #
-# Optional include dmalloc
-#
-{ echo "$as_me:$LINENO: checking if malloc debugging is wanted" >&5
-echo $ECHO_N "checking if malloc debugging is wanted... $ECHO_C" >&6; }
-
-# Check whether --with-dmalloc was given.
-if test "${with_dmalloc+set}" = set; then
-  withval=$with_dmalloc; if test "$withval" = yes; then
-  { echo "$as_me:$LINENO: result: yes" >&5
[...2863 lines suppressed...]
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_XML_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
 done
-rm -f conftest.$ac_ext
-CC=$ac_save_CC
+done
+IFS=$as_save_IFS
 
-fi
-# AC_CACHE_VAL
-case "x$ac_cv_prog_cc_c89" in
-  x)
-    { echo "$as_me:$LINENO: result: none needed" >&5
-echo "${ECHO_T}none needed" >&6; } ;;
-  xno)
-    { echo "$as_me:$LINENO: result: unsupported" >&5
-echo "${ECHO_T}unsupported" >&6; } ;;
-  *)
-    CC="$CC $ac_cv_prog_cc_c89"
-    { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
+  ;;
 esac
+fi
+XML_CONFIG=$ac_cv_path_XML_CONFIG
+if test -n "$XML_CONFIG"; then
+  { echo "$as_me:$LINENO: result: $XML_CONFIG" >&5
+echo "${ECHO_T}$XML_CONFIG" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
 
 
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
+  test -n "$XML_CONFIG" && break
+done
+test -n "$XML_CONFIG" || XML_CONFIG="no"
+
+{ echo "$as_me:$LINENO: checking for libxml2" >&5
+echo $ECHO_N "checking for libxml2... $ECHO_C" >&6; }
+if test "$XML_CONFIG" = "no"
+then
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+  HAVE_LIBXML=0
+else
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+  HAVE_LIBXML=1
+  XML_LIBS=`$XML_CONFIG --libs`
+  XML_FLAGS=`$XML_CONFIG --cflags`
+  XML_VER=`$XML_CONFIG --version`
+  XML_MAJOR=`echo $XML_VER|cut -d\. -f1`
+  if test $XML_MAJOR -le 99
+  then
+    XML_MINOR=`echo $XML_VER|cut -d\. -f2`
+    if test $XML_MINOR -le 99
+    then
+      XML_REV=`echo $XML_VER|cut -d\. -f3`
+      if test $XML_REV -le 99; then
+
+cat >>confdefs.h <<\_ACEOF
+#define LIBXML2_WORKAROUND 1
+_ACEOF
 
+      fi
+    fi
+  fi
+fi
 
+#
+# glibc/libc 6 new libraries
+#
 { echo "$as_me:$LINENO: checking for yp_match in -lnsl" >&5
 echo $ECHO_N "checking for yp_match in -lnsl... $ECHO_C" >&6; }
 if test "${ac_cv_lib_nsl_yp_match+set}" = set; then
@@ -6280,6 +6447,14 @@ confdir!$confdir$ac_delim
 mapdir!$mapdir$ac_delim
 fifodir!$fifodir$ac_delim
 flagdir!$flagdir$ac_delim
+CC!$CC$ac_delim
+CFLAGS!$CFLAGS$ac_delim
+LDFLAGS!$LDFLAGS$ac_delim
+CPPFLAGS!$CPPFLAGS$ac_delim
+ac_ct_CC!$ac_ct_CC$ac_delim
+EXEEXT!$EXEEXT$ac_delim
+OBJEXT!$OBJEXT$ac_delim
+TIRPCLIB!$TIRPCLIB$ac_delim
 DMALLOCLIB!$DMALLOCLIB$ac_delim
 MOUNT!$MOUNT$ac_delim
 HAVE_MOUNT!$HAVE_MOUNT$ac_delim
@@ -6300,13 +6475,6 @@ PATH_RANLIB!$PATH_RANLIB$ac_delim
 RPCGEN!$RPCGEN$ac_delim
 PATH_RPCGEN!$PATH_RPCGEN$ac_delim
 XML_CONFIG!$XML_CONFIG$ac_delim
-CC!$CC$ac_delim
-CFLAGS!$CFLAGS$ac_delim
-LDFLAGS!$LDFLAGS$ac_delim
-CPPFLAGS!$CPPFLAGS$ac_delim
-ac_ct_CC!$ac_ct_CC$ac_delim
-EXEEXT!$EXEEXT$ac_delim
-OBJEXT!$OBJEXT$ac_delim
 LIBNSL!$LIBNSL$ac_delim
 LIBRESOLV!$LIBRESOLV$ac_delim
 HAVE_HESIOD!$HAVE_HESIOD$ac_delim
@@ -6330,7 +6498,7 @@ LIBOBJS!$LIBOBJS$ac_delim
 LTLIBOBJS!$LTLIBOBJS$ac_delim
 _ACEOF
 
-  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 90; then
+  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 91; then
     break
   elif $ac_last_try; then
     { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
--- autofs-5.0.4.orig/configure.in
+++ autofs-5.0.4/configure.in
@@ -113,6 +113,12 @@ AC_MSG_RESULT([$flagdir])
 AC_SUBST(flagdir)
 
 #
+# Use libtirpc
+#
+AM_WITH_LIBTIRPC()
+AC_SUBST(TIRPCLIB)
+
+#
 # Optional include dmalloc
 #
 AM_WITH_DMALLOC()
--- autofs-5.0.4.orig/daemon/automount.c
+++ autofs-5.0.4/daemon/automount.c
@@ -2057,7 +2057,10 @@ int main(int argc, char *argv[])
 	}
 
 #ifdef LIBXML2_WORKAROUND
-	void *dh = dlopen("libxml2.so", RTLD_NOW);
+	void *dh_xml2 = dlopen("libxml2.so", RTLD_NOW);
+#endif
+#ifdef TIRPC_WORKAROUND
+	void *dh_tirpc = dlopen("libitirpc.so", RTLD_NOW);
 #endif
 
 	if (!master_read_master(master_list, age, 0)) {
@@ -2090,9 +2093,13 @@ int main(int argc, char *argv[])
 	closelog();
 	release_flag_file();
 
+#ifdef TIRPC_WORKAROUND
+	if (dh_tirpc)
+		dlclose(dh_tirpc);
+#endif
 #ifdef LIBXML2_WORKAROUND
-	if (dh)
-		dlclose(dh);
+	if (dh_xml2)
+		dlclose(dh_xml2);
 #endif
 	close_ioctl_ctl();
 
--- autofs-5.0.4.orig/include/config.h.in
+++ autofs-5.0.4/include/config.h.in
@@ -66,6 +66,9 @@
 /* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
 
+/* Use IPv6 with libtirpc */
+#undef INET6
+
 /* Use libxml2 tsd usage workaround */
 #undef LIBXML2_WORKAROUND
 
@@ -114,6 +117,9 @@
 /* Define to 1 if you have the ANSI C header files. */
 #undef STDC_HEADERS
 
+/* Use libtirpc tsd usage workaround */
+#undef TIRPC_WORKAROUND
+
 /* Define if using the dmalloc debugging malloc package */
 #undef WITH_DMALLOC
 
--- autofs-5.0.4.orig/CHANGELOG
+++ autofs-5.0.4/CHANGELOG
@@ -17,6 +17,7 @@
 - always read entire file map into cache to speed lookups.
 - make MAX_ERR_BUF and PARSE_MAX_BUF use easier to audit.
 - make some easy alloca replacements (Valerie Aurora Henson).
+- update to configure libtirpc if present.
 
 4/11/2008 autofs-5.0.4
 -----------------------

autofs-5.0.4-easy-alloca-replacements.patch:

--- NEW FILE autofs-5.0.4-easy-alloca-replacements.patch ---
autofs-5.0.4 - easy alloca replacements

From: Valerie Aurora Henson <vaurora at redhat.com>

alloca() is compiler-dependent, non-standard, and has undefined
behavior when it fails (IOW, the program crashes).  Replace with
normal C stack variables where possible and malloc() where not.
---

 CHANGELOG                |    1 
 daemon/automount.c       |   29 ++++++--------
 daemon/direct.c          |   12 ++----
 daemon/flag.c            |   13 +++---
 daemon/indirect.c        |   12 ++----
 daemon/module.c          |   45 +++++++---------------
 lib/cache.c              |   31 +++++----------
 lib/cat_path.c           |    1 
 modules/lookup_file.c    |   82 +++++++++++++----------------------------
 modules/lookup_ldap.c    |   93 +++++++++++++++++++++++++++++------------------
 modules/lookup_nisplus.c |   71 ++++++++++++++++++++---------------
 modules/mount_autofs.c   |    1 
 modules/mount_bind.c     |    7 +--
 modules/mount_changer.c  |    5 --
 modules/mount_ext2.c     |    5 --
 modules/mount_generic.c  |    5 --
 16 files changed, 185 insertions(+), 228 deletions(-)


--- autofs-5.0.4.orig/daemon/automount.c
+++ autofs-5.0.4/daemon/automount.c
@@ -127,8 +127,8 @@ static int do_mkdir(const char *parent, 
 
 int mkdir_path(const char *path, mode_t mode)
 {
-	char *buf = alloca(strlen(path) + 1);
-	char *parent = alloca(strlen(path) + 1);
+	char buf[PATH_MAX];
+	char parent[PATH_MAX];
 	const char *cp = path, *lcp = path;
 	char *bp = buf, *pp = parent;
 
@@ -163,7 +163,7 @@ int mkdir_path(const char *path, mode_t 
 int rmdir_path(struct autofs_point *ap, const char *path, dev_t dev)
 {
 	int len = strlen(path);
-	char *buf = alloca(len + 1);
+	char buf[PATH_MAX];
 	char *cp;
 	int first = 1;
 	struct stat st;
@@ -468,20 +468,17 @@ static int umount_subtree_mounts(struct 
 	pthread_cleanup_push(cache_lock_cleanup, mc);
 
 	if (me->multi) {
-		char *root, *base;
-		size_t ap_len;
+		char root[PATH_MAX];
+		char *base;
 		int cur_state;
 
-		ap_len = strlen(ap->path);
-
-		if (!strchr(me->multi->key, '/')) {
+		if (!strchr(me->multi->key, '/'))
 			/* Indirect multi-mount root */
-			root = alloca(ap_len + strlen(me->multi->key) + 2);
-			strcpy(root, ap->path);
-			strcat(root, "/");
-			strcat(root, me->multi->key);
-		} else
-			root = me->multi->key;
+			/* sprintf okay - if it's mounted, it's
+			 * PATH_MAX or less bytes */
+			sprintf(root, "%s/%s", ap->path, me->multi->key);
+		else
+			strcpy(root, me->multi->key);
 
 		if (is_mm_root)
 			base = NULL;
@@ -929,14 +926,14 @@ static int get_pkt(struct autofs_point *
 
 int do_expire(struct autofs_point *ap, const char *name, int namelen)
 {
-	char buf[PATH_MAX + 1];
+	char buf[PATH_MAX];
 	int len, ret;
 
 	if (*name != '/') {
 		len = ncat_path(buf, sizeof(buf), ap->path, name, namelen);
 	} else {
 		len = snprintf(buf, PATH_MAX, "%s", name);
-		if (len > PATH_MAX)
+		if (len >= PATH_MAX)
 			len = 0;
 	}
 
--- autofs-5.0.4.orig/daemon/direct.c
+++ autofs-5.0.4/daemon/direct.c
@@ -637,7 +637,9 @@ int mount_autofs_offset(struct autofs_po
 	time_t timeout = ap->exp_timeout;
 	struct stat st;
 	int ioctlfd, status, ret;
-	const char *type, *map_name = NULL;
+	const char *hosts_map_name = "-hosts";
+	const char *map_name = hosts_map_name;
+	const char *type;
 	char mountpoint[PATH_MAX];
 
 	if (ops->version && ap->flags & MOUNT_FLAG_REMOUNT) {
@@ -740,13 +742,7 @@ int mount_autofs_offset(struct autofs_po
 	      mp->options, mountpoint);
 
 	type = ap->entry->maps->type;
-	if (type && !strcmp(ap->entry->maps->type, "hosts")) {
-		char *tmp = alloca(7);
-		if (tmp) {
-			strcpy(tmp, "-hosts");
-			map_name = (const char *) tmp;
-		}
-	} else
+	if (!type || strcmp(ap->entry->maps->type, "hosts"))
 		map_name = me->mc->map->argv[0];
 
 	ret = mount(map_name, mountpoint, "autofs", MS_MGC_VAL, mp->options);
--- autofs-5.0.4.orig/daemon/flag.c
+++ autofs-5.0.4/daemon/flag.c
@@ -23,10 +23,10 @@
 #include <sys/stat.h>
 #include <time.h>
 #include <string.h>
-#include <alloca.h>
 #include <stdio.h>
 #include <signal.h>
 #include <errno.h>
+#include <limits.h>
 
 #include "automount.h"
 
@@ -113,12 +113,13 @@ void release_flag_file(void)
 /* * Try to create flag file */
 int aquire_flag_file(void)
 {
-	char *linkf;
-	int len;
+	char linkf[PATH_MAX];
+	size_t len;
 
-	len = strlen(FLAG_FILE) + MAX_PIDSIZE;
-	linkf = alloca(len + 1);
-	snprintf(linkf, len, "%s.%d", FLAG_FILE, getpid());
+	len = snprintf(linkf, sizeof(linkf), "%s.%d", FLAG_FILE, getpid());
+	if (len >= sizeof(linkf))
+		/* Didn't acquire it */
+		return 0;
 
 	/*
 	 * Repeat until it was us who made the link or we find the
--- autofs-5.0.4.orig/daemon/indirect.c
+++ autofs-5.0.4/daemon/indirect.c
@@ -90,7 +90,9 @@ static int do_mount_autofs_indirect(stru
 	struct ioctl_ops *ops = get_ioctl_ops();
 	time_t timeout = ap->exp_timeout;
 	char *options = NULL;
-	const char *type, *map_name = NULL;
+	const char *hosts_map_name = "-hosts";
+	const char *map_name = hosts_map_name;
+	const char *type;
 	struct stat st;
 	struct mnt_list *mnts;
 	int ret;
@@ -142,13 +144,7 @@ static int do_mount_autofs_indirect(stru
 	}
 
 	type = ap->entry->maps->type;
-	if (type && !strcmp(ap->entry->maps->type, "hosts")) {
-		char *tmp = alloca(7);
-		if (tmp) {
-			strcpy(tmp, "-hosts");
-			map_name = (const char *) tmp;
-		}
-	} else
+	if (!type || strcmp(ap->entry->maps->type, "hosts"))
 		map_name = ap->entry->maps->argv[0];
 
 	ret = mount(map_name, root, "autofs", MS_MGC_VAL, options);
--- autofs-5.0.4.orig/daemon/module.c
+++ autofs-5.0.4/daemon/module.c
@@ -58,15 +58,11 @@ struct lookup_mod *open_lookup(const cha
 {
 	struct lookup_mod *mod;
 	char buf[MAX_ERR_BUF];
-	char *fnbuf;
-	size_t size_name;
-	size_t size_fnbuf;
+	char fnbuf[PATH_MAX];
+	size_t size;
 	void *dh;
 	int *ver;
 
-	size_name = _strlen(name, PATH_MAX + 1);
-	if (!size_name)
-		return NULL;
 
 	mod = malloc(sizeof(struct lookup_mod));
 	if (!mod) {
@@ -77,9 +73,9 @@ struct lookup_mod *open_lookup(const cha
 		return NULL;
 	}
 
-	size_fnbuf = size_name + strlen(AUTOFS_LIB_DIR) + 13;
-	fnbuf = alloca(size_fnbuf);
-	if (!fnbuf) {
+	size = snprintf(fnbuf, sizeof(fnbuf),
+			"%s/lookup_%s.so", AUTOFS_LIB_DIR, name);
+	if (size >= sizeof(fnbuf)) {
 		free(mod);
 		if (err_prefix) {
 			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
@@ -87,7 +83,6 @@ struct lookup_mod *open_lookup(const cha
 		}
 		return NULL;
 	}
-	snprintf(fnbuf, size_fnbuf, "%s/lookup_%s.so", AUTOFS_LIB_DIR, name);
 
 	if (!(dh = dlopen(fnbuf, RTLD_NOW))) {
 		if (err_prefix)
@@ -141,15 +136,11 @@ struct parse_mod *open_parse(const char 
 {
 	struct parse_mod *mod;
 	char buf[MAX_ERR_BUF];
-	char *fnbuf;
-	size_t size_name;
-	size_t size_fnbuf;
+	char fnbuf[PATH_MAX];
+	size_t size;
 	void *dh;
 	int *ver;
 
-	size_name = _strlen(name, PATH_MAX + 1);
-	if (!size_name)
-		return NULL;
 
 	mod = malloc(sizeof(struct parse_mod));
 	if (!mod) {
@@ -160,9 +151,9 @@ struct parse_mod *open_parse(const char 
 		return NULL;
 	}
 
-	size_fnbuf = size_name + strlen(AUTOFS_LIB_DIR) + 13;
-	fnbuf = alloca(size_fnbuf);
-	if (!fnbuf) {
+	size = snprintf(fnbuf, sizeof(fnbuf),
+			"%s/parse_%s.so", AUTOFS_LIB_DIR, name);
+	if (size >= sizeof(fnbuf)) {
 		free(mod);
 		if (err_prefix) {
 			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
@@ -170,7 +161,6 @@ struct parse_mod *open_parse(const char 
 		}
 		return NULL;
 	}
-	snprintf(fnbuf, size_fnbuf, "%s/parse_%s.so", AUTOFS_LIB_DIR, name);
 
 	if (!(dh = dlopen(fnbuf, RTLD_NOW))) {
 		if (err_prefix)
@@ -222,15 +212,11 @@ struct mount_mod *open_mount(const char 
 {
 	struct mount_mod *mod;
 	char buf[MAX_ERR_BUF];
-	char *fnbuf;
-	size_t size_name;
-	size_t size_fnbuf;
+	char fnbuf[PATH_MAX];
+	size_t size;
 	void *dh;
 	int *ver;
 
-	size_name = _strlen(name, PATH_MAX + 1);
-	if (!size_name)
-		return NULL;
 
 	mod = malloc(sizeof(struct mount_mod));
 	if (!mod) {
@@ -241,9 +227,9 @@ struct mount_mod *open_mount(const char 
 		return NULL;
 	}
 
-	size_fnbuf = size_name + strlen(AUTOFS_LIB_DIR) + 13;
-	fnbuf = alloca(size_fnbuf);
-	if (!fnbuf) {
+	size = snprintf(fnbuf, sizeof(fnbuf),
+			"%s/mount_%s.so", AUTOFS_LIB_DIR, name);
+	if (size >= sizeof(fnbuf)) {
 		free(mod);
 		if (err_prefix) {
 			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
@@ -251,7 +237,6 @@ struct mount_mod *open_mount(const char 
 		}
 		return NULL;
 	}
-	snprintf(fnbuf, size_fnbuf, "%s/mount_%s.so", AUTOFS_LIB_DIR, name);
 
 	if (!(dh = dlopen(fnbuf, RTLD_NOW))) {
 		if (err_prefix)
--- autofs-5.0.4.orig/lib/cache.c
+++ autofs-5.0.4/lib/cache.c
@@ -482,27 +482,23 @@ struct mapent *cache_lookup_offset(const
 {
 	struct list_head *p;
 	struct mapent *this;
-	int plen = strlen(prefix);
-	char *o_key;
+	/* Keys for direct maps may be as long as a path name */
+	char o_key[PATH_MAX];
+	/* Avoid "//" at the beginning of paths */
+	const char *path_prefix = strlen(prefix) > 1 ? prefix : "";
+	size_t size;
 
 	/* root offset duplicates "/" */
-	if (plen > 1) {
-		o_key = alloca(plen + strlen(offset) + 1);
-		strcpy(o_key, prefix);
-		strcat(o_key, offset);
-	} else {
-		o_key = alloca(strlen(offset) + 1);
-		strcpy(o_key, offset);
-	}
+	size = snprintf(o_key, sizeof(o_key), "%s%s", path_prefix, offset);
+	if (size >= sizeof(o_key))
+		return NULL;
 
 	list_for_each(p, head) {
 		this = list_entry(p, struct mapent, multi_list);
 		if (!strcmp(&this->key[start], o_key))
-			goto done;
+			return this;
 	}
-	this = NULL;
-done:
-	return this;
+	return NULL;
 }
 
 /* cache must be read locked by caller */
@@ -759,13 +755,8 @@ int cache_delete(struct mapent_cache *mc
 	struct mapent *me = NULL, *pred;
 	u_int32_t hashval = hash(key, mc->size);
 	int status, ret = CHE_OK;
-	char *this;
+	char this[PATH_MAX];
 
-	this = alloca(strlen(key) + 1);
-	if (!this) {
-		ret = CHE_FAIL;
-		goto done;
-	}
 	strcpy(this, key);
 
 	me = mc->hash[hashval];
--- autofs-5.0.4.orig/lib/cat_path.c
+++ autofs-5.0.4/lib/cat_path.c
@@ -12,7 +12,6 @@
  *
  * ----------------------------------------------------------------------- */
 
-#include <alloca.h>
 #include <string.h>
 #include <limits.h>
 #include <ctype.h>
--- autofs-5.0.4.orig/modules/lookup_file.c
+++ autofs-5.0.4/modules/lookup_file.c
@@ -378,8 +378,8 @@ int lookup_read_master(struct master *ma
 	unsigned int logopt = master->logopt;
 	char *buffer;
 	int blen;
-	char *path;
-	char *ent;
+	char path[KEY_MAX_LEN + 1];
+	char ent[MAPENT_MAX_LEN + 1];
 	FILE *f;
 	unsigned int path_len, ent_len;
 	int entry, cur_state;
@@ -393,20 +393,6 @@ int lookup_read_master(struct master *ma
 		return NSS_STATUS_UNAVAIL;
 	}
 
-	path = alloca(KEY_MAX_LEN + 1);
-	if (!path) {
-		error(logopt,
-		      MODPREFIX "could not malloc storage for path");
-		return NSS_STATUS_UNAVAIL;
-	}
-
-	ent = alloca(MAPENT_MAX_LEN + 1);
-	if (!ent) {
-		error(logopt,
-		      MODPREFIX "could not malloc storage for mapent");
-		return NSS_STATUS_UNAVAIL;
-	}
-
 	f = open_fopen_r(ctxt->mapname);
 	if (!f) {
 		error(logopt,
@@ -618,8 +604,8 @@ int lookup_read_map(struct autofs_point 
 	struct lookup_context *ctxt = (struct lookup_context *) context;
 	struct map_source *source;
 	struct mapent_cache *mc;
-	char *key;
-	char *mapent;
+	char key[KEY_MAX_LEN + 1];
+	char mapent[MAPENT_MAX_LEN + 1];
 	FILE *f;
 	unsigned int k_len, m_len;
 	int entry;
@@ -639,20 +625,6 @@ int lookup_read_map(struct autofs_point 
 		return NSS_STATUS_UNAVAIL;
 	}
 
-	key = alloca(KEY_MAX_LEN + 1);
-	if (!key) {
-		error(ap->logopt,
-		      MODPREFIX "could not malloc storage for key");
-		return NSS_STATUS_UNAVAIL;
-	}
-
-	mapent = alloca(MAPENT_MAX_LEN + 1);
-	if (!mapent) {
-		error(ap->logopt,
-		      MODPREFIX "could not malloc storage for mapent");
-		return NSS_STATUS_UNAVAIL;
-	}
-
 	f = open_fopen_r(ctxt->mapname);
 	if (!f) {
 		error(ap->logopt,
@@ -972,7 +944,7 @@ int lookup_mount(struct autofs_point *ap
 	char key[KEY_MAX_LEN + 1];
 	int key_len;
 	char *mapent = NULL;
-	int mapent_len;
+	char mapent_buf[MAPENT_MAX_LEN + 1];
 	int status = 0;
 	int ret = 1;
 
@@ -1076,38 +1048,36 @@ do_cache_lookup:
 	}
 	if (me && (me->source == source || *me->key == '/')) {
 		pthread_cleanup_push(cache_lock_cleanup, mc);
-		mapent_len = strlen(me->mapent);
-		mapent = alloca(mapent_len + 1);
-		strcpy(mapent, me->mapent);
+		strcpy(mapent_buf, me->mapent);
+		mapent = mapent_buf;
 		pthread_cleanup_pop(0);
 	}
 	cache_unlock(mc);
 
-	if (mapent) {
-		master_source_current_wait(ap->entry);
-		ap->entry->current = source;
+	if (!mapent)
+		return NSS_STATUS_TRYAGAIN;
 
-		debug(ap->logopt, MODPREFIX "%s -> %s", key, mapent);
-		ret = ctxt->parse->parse_mount(ap, key, key_len,
-					mapent, ctxt->parse->context);
-		if (ret) {
-			time_t now = time(NULL);
-			int rv = CHE_OK;
+	master_source_current_wait(ap->entry);
+	ap->entry->current = source;
 
-			cache_writelock(mc);
+	debug(ap->logopt, MODPREFIX "%s -> %s", key, mapent);
+	ret = ctxt->parse->parse_mount(ap, key, key_len,
+				       mapent, ctxt->parse->context);
+	if (ret) {
+		time_t now = time(NULL);
+		int rv = CHE_OK;
+
+		cache_writelock(mc);
+		me = cache_lookup_distinct(mc, key);
+		if (!me)
+			rv = cache_update(mc, source, key, NULL, now);
+		if (rv != CHE_FAIL) {
 			me = cache_lookup_distinct(mc, key);
-			if (!me)
-				rv = cache_update(mc, source, key, NULL, now);
-			if (rv != CHE_FAIL) {
-				me = cache_lookup_distinct(mc, key);
-				me->status = now + ap->negative_timeout;
-			}
-			cache_unlock(mc);
+			me->status = now + ap->negative_timeout;
 		}
-	}
-
-	if (ret)
+		cache_unlock(mc);
 		return NSS_STATUS_TRYAGAIN;
+	}
 
 	return NSS_STATUS_SUCCESS;
 }
--- autofs-5.0.4.orig/modules/lookup_ldap.c
+++ autofs-5.0.4/modules/lookup_ldap.c
@@ -294,10 +294,10 @@ static int get_query_dn(unsigned logopt,
 	if (ctxt->mapname)
 		l += strlen(key) + strlen(ctxt->mapname) + strlen("(&(=))");
 
-	query = alloca(l);
+	query = malloc(l);
 	if (query == NULL) {
 		char *estr = strerror_r(errno, buf, sizeof(buf));
-		crit(logopt, MODPREFIX "alloca: %s", estr);
+		crit(logopt, MODPREFIX "malloc: %s", estr);
 		return NSS_STATUS_UNAVAIL;
 	}
 
@@ -310,6 +310,7 @@ static int get_query_dn(unsigned logopt,
 		     key, (int) strlen(ctxt->mapname), ctxt->mapname) >= l) {
 			debug(logopt,
 			      MODPREFIX "error forming query string");
+			free(query);
 			return 0;
 		}
 		scope = LDAP_SCOPE_SUBTREE;
@@ -317,6 +318,7 @@ static int get_query_dn(unsigned logopt,
 		if (sprintf(query, "(objectclass=%s)", class) >= l) {
 			debug(logopt,
 			      MODPREFIX "error forming query string");
+			free(query);
 			return 0;
 		}
 		scope = LDAP_SCOPE_SUBTREE;
@@ -340,6 +342,7 @@ static int get_query_dn(unsigned logopt,
 			error(logopt,
 			      MODPREFIX "query failed for %s: %s",
 			      query, ldap_err2string(rv));
+			free(query);
 			return 0;
 		}
 
@@ -353,6 +356,7 @@ static int get_query_dn(unsigned logopt,
 			      MODPREFIX "query succeeded, no matches for %s",
 			      query);
 			ldap_msgfree(result);
+			free(query);
 			return 0;
 		}
 	} else {
@@ -395,10 +399,12 @@ static int get_query_dn(unsigned logopt,
 			ldap_msgfree(result);
 			error(logopt,
 			      MODPREFIX "failed to find query dn under search base dns");
+			free(query);
 			return 0;
 		}
 	}
 
+	free(query);
 	qdn = strdup(dn);
 	ldap_memfree(dn);
 	ldap_msgfree(result);
@@ -1181,7 +1187,7 @@ static int parse_server_string(unsigned 
 			else {
 				char *estr;
 				estr = strerror_r(errno, buf, sizeof(buf));
-				logerr(MODPREFIX "malloc: %s", estr);
+				logerr(MODPREFIX "strdup: %s", estr);
 				if (ctxt->server)
 					free(ctxt->server);
 				return 0;
@@ -1441,23 +1447,26 @@ int lookup_read_master(struct master *ma
 
 	l = strlen("(objectclass=)") + strlen(class) + 1;
 
-	query = alloca(l);
+	query = malloc(l);
 	if (query == NULL) {
 		char *estr = strerror_r(errno, buf, sizeof(buf));
-		logerr(MODPREFIX "alloca: %s", estr);
+		logerr(MODPREFIX "malloc: %s", estr);
 		return NSS_STATUS_UNAVAIL;
 	}
 
 	if (sprintf(query, "(objectclass=%s)", class) >= l) {
 		error(logopt, MODPREFIX "error forming query string");
+		free(query);
 		return NSS_STATUS_UNAVAIL;
 	}
 	query[l] = '\0';
 
 	/* Initialize the LDAP context. */
 	ldap = do_reconnect(logopt, ctxt);
-	if (!ldap)
+	if (!ldap) {
+		free(query);
 		return NSS_STATUS_UNAVAIL;
+	}
 
 	/* Look around. */
 	debug(logopt,
@@ -1469,6 +1478,7 @@ int lookup_read_master(struct master *ma
 		error(logopt, MODPREFIX "query failed for %s: %s",
 		      query, ldap_err2string(rv));
 		unbind_ldap_connection(logging, ldap, ctxt);
+		free(query);
 		return NSS_STATUS_NOTFOUND;
 	}
 
@@ -1479,6 +1489,7 @@ int lookup_read_master(struct master *ma
 		      query);
 		ldap_msgfree(result);
 		unbind_ldap_connection(logging, ldap, ctxt);
+		free(query);
 		return NSS_STATUS_NOTFOUND;
 	} else
 		debug(logopt, MODPREFIX "examining entries");
@@ -1548,6 +1559,7 @@ next:
 	/* Clean up. */
 	ldap_msgfree(result);
 	unbind_ldap_connection(logopt, ldap, ctxt);
+	free(query);
 
 	return NSS_STATUS_SUCCESS;
 }
@@ -2174,7 +2186,7 @@ static int read_one_map(struct autofs_po
 	/* Build a query string. */
 	l = strlen("(objectclass=)") + strlen(class) + 1;
 
-	sp.query = alloca(l);
+	sp.query = malloc(l);
 	if (sp.query == NULL) {
 		char *estr = strerror_r(errno, buf, sizeof(buf));
 		logerr(MODPREFIX "malloc: %s", estr);
@@ -2183,14 +2195,17 @@ static int read_one_map(struct autofs_po
 
 	if (sprintf(sp.query, "(objectclass=%s)", class) >= l) {
 		error(ap->logopt, MODPREFIX "error forming query string");
+		free(sp.query);
 		return NSS_STATUS_UNAVAIL;
 	}
 	sp.query[l] = '\0';
 
 	/* Initialize the LDAP context. */
 	sp.ldap = do_reconnect(ap->logopt, ctxt);
-	if (!sp.ldap)
+	if (!sp.ldap) {
+		free(sp.query);
 		return NSS_STATUS_UNAVAIL;
+	}
 
 	/* Look around. */
 	debug(ap->logopt,
@@ -2215,6 +2230,7 @@ static int read_one_map(struct autofs_po
 		if (rv != LDAP_SUCCESS || !sp.result) {
 			unbind_ldap_connection(ap->logopt, sp.ldap, ctxt);
 			*result_ldap = rv;
+			free(sp.query);
 			return NSS_STATUS_UNAVAIL;
 		}
 
@@ -2223,6 +2239,7 @@ static int read_one_map(struct autofs_po
 			ldap_msgfree(sp.result);
 			unbind_ldap_connection(ap->logopt, sp.ldap, ctxt);
 			*result_ldap = rv;
+			free(sp.query);
 			return NSS_STATUS_NOTFOUND;
 		}
 		ldap_msgfree(sp.result);
@@ -2233,6 +2250,7 @@ static int read_one_map(struct autofs_po
 	unbind_ldap_connection(ap->logopt, sp.ldap, ctxt);
 
 	source->age = age;
+	free(sp.query);
 
 	return NSS_STATUS_SUCCESS;
 }
@@ -2328,7 +2346,7 @@ static int lookup_one(struct autofs_poin
 	if (enc_len1)
 		l += 2*strlen(entry) + enc_len1 + enc_len2 + 6;
 
-	query = alloca(l);
+	query = malloc(l);
 	if (query == NULL) {
 		char *estr = strerror_r(errno, buf, sizeof(buf));
 		crit(ap->logopt, MODPREFIX "malloc: %s", estr);
@@ -2336,6 +2354,7 @@ static int lookup_one(struct autofs_poin
 			free(enc_key1);
 			free(enc_key2);
 		}
+		free(query);
 		return CHE_FAIL;
 	}
 
@@ -2367,14 +2386,17 @@ static int lookup_one(struct autofs_poin
 	if (ql >= l) {
 		error(ap->logopt,
 		      MODPREFIX "error forming query string");
+		free(query);
 		return CHE_FAIL;
 	}
 	query[ql] = '\0';
 
 	/* Initialize the LDAP context. */
 	ldap = do_reconnect(ap->logopt, ctxt);
-	if (!ldap)
+	if (!ldap) {
+		free(query);
 		return CHE_UNAVAIL;
+	}
 
 	debug(ap->logopt,
 	      MODPREFIX "searching for \"%s\" under \"%s\"", query, ctxt->qdn);
@@ -2384,6 +2406,7 @@ static int lookup_one(struct autofs_poin
 	if ((rv != LDAP_SUCCESS) || !result) {
 		crit(ap->logopt, MODPREFIX "query failed for %s", query);
 		unbind_ldap_connection(ap->logopt, ldap, ctxt);
+		free(query);
 		return CHE_FAIL;
 	}
 
@@ -2396,6 +2419,7 @@ static int lookup_one(struct autofs_poin
 		     MODPREFIX "got answer, but no entry for %s", query);
 		ldap_msgfree(result);
 		unbind_ldap_connection(ap->logopt, ldap, ctxt);
+		free(query);
 		return CHE_MISSING;
 	}
 
@@ -2610,6 +2634,7 @@ next:
 		}
 	}
 	pthread_cleanup_pop(1);
+	free(query);
 
 	return ret;
 }
@@ -2696,7 +2721,7 @@ int lookup_mount(struct autofs_point *ap
 	char key[KEY_MAX_LEN + 1];
 	int key_len;
 	char *mapent = NULL;
-	int mapent_len;
+	char mapent_buf[MAPENT_MAX_LEN + 1];
 	int status = 0;
 	int ret = 1;
 
@@ -2766,38 +2791,36 @@ int lookup_mount(struct autofs_point *ap
 			me = cache_lookup_distinct(mc, "*");
 	}
 	if (me && (me->source == source || *me->key == '/')) {
-		mapent_len = strlen(me->mapent);
-		mapent = alloca(mapent_len + 1);
-		strcpy(mapent, me->mapent);
+		strcpy(mapent_buf, me->mapent);
+		mapent = mapent_buf;
 	}
 	cache_unlock(mc);
 
-	if (mapent) {
-		master_source_current_wait(ap->entry);
-		ap->entry->current = source;
+	if (!mapent)
+		return NSS_STATUS_TRYAGAIN;
 
-		debug(ap->logopt, MODPREFIX "%s -> %s", key, mapent);
-		ret = ctxt->parse->parse_mount(ap, key, key_len,
-					 mapent, ctxt->parse->context);
-		if (ret) {
-			time_t now = time(NULL);
-			int rv = CHE_OK;
+	master_source_current_wait(ap->entry);
+	ap->entry->current = source;
 
-			/* Record the the mount fail in the cache */
-			cache_writelock(mc);
+	debug(ap->logopt, MODPREFIX "%s -> %s", key, mapent);
+	ret = ctxt->parse->parse_mount(ap, key, key_len,
+				       mapent, ctxt->parse->context);
+	if (ret) {
+		time_t now = time(NULL);
+		int rv = CHE_OK;
+
+		/* Record the the mount fail in the cache */
+		cache_writelock(mc);
+		me = cache_lookup_distinct(mc, key);
+		if (!me)
+			rv = cache_update(mc, source, key, NULL, now);
+		if (rv != CHE_FAIL) {
 			me = cache_lookup_distinct(mc, key);
-			if (!me)
-				rv = cache_update(mc, source, key, NULL, now);
-			if (rv != CHE_FAIL) {
-				me = cache_lookup_distinct(mc, key);
-				me->status = now + ap->negative_timeout;
-			}
-			cache_unlock(mc);
+			me->status = now + ap->negative_timeout;
 		}
-	}
-
-	if (ret)
+		cache_unlock(mc);
 		return NSS_STATUS_TRYAGAIN;
+	}
 
 	return NSS_STATUS_SUCCESS;
 }
--- autofs-5.0.4.orig/modules/lookup_nisplus.c
+++ autofs-5.0.4/modules/lookup_nisplus.c
@@ -92,10 +92,10 @@ int lookup_read_master(struct master *ma
 	int cur_state, len;
 
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
-	tablename = alloca(strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20);
+	tablename = malloc(strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20);
 	if (!tablename) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		logerr(MODPREFIX "alloca: %s", estr);
+		logerr(MODPREFIX "malloc: %s", estr);
 		pthread_setcancelstate(cur_state, NULL);
 		return NSS_STATUS_UNAVAIL;
 	}
@@ -107,6 +107,7 @@ int lookup_read_master(struct master *ma
 		nis_freeresult(result);
 		crit(logopt,
 		     MODPREFIX "couldn't locate nis+ table %s", ctxt->mapname);
+		free(tablename);
 		pthread_setcancelstate(cur_state, NULL);
 		return NSS_STATUS_NOTFOUND;
 	}
@@ -118,6 +119,7 @@ int lookup_read_master(struct master *ma
 		nis_freeresult(result);
 		crit(logopt,
 		     MODPREFIX "couldn't enumrate nis+ map %s", ctxt->mapname);
+		free(tablename);
 		pthread_setcancelstate(cur_state, NULL);
 		return NSS_STATUS_UNAVAIL;
 	}
@@ -155,6 +157,7 @@ int lookup_read_master(struct master *ma
 	}
 
 	nis_freeresult(result);
+	free(tablename);
 	pthread_setcancelstate(cur_state, NULL);
 
 	return NSS_STATUS_SUCCESS;
@@ -180,10 +183,10 @@ int lookup_read_map(struct autofs_point 
 	mc = source->mc;
 
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
-	tablename = alloca(strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20);
+	tablename = malloc(strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20);
 	if (!tablename) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		logerr(MODPREFIX "alloca: %s", estr);
+		logerr(MODPREFIX "malloc: %s", estr);
 		pthread_setcancelstate(cur_state, NULL);
 		return NSS_STATUS_UNAVAIL;
 	}
@@ -195,6 +198,7 @@ int lookup_read_map(struct autofs_point 
 		nis_freeresult(result);
 		crit(ap->logopt,
 		     MODPREFIX "couldn't locate nis+ table %s", ctxt->mapname);
+		free(tablename);
 		pthread_setcancelstate(cur_state, NULL);
 		return NSS_STATUS_NOTFOUND;
 	}
@@ -206,6 +210,7 @@ int lookup_read_map(struct autofs_point 
 		nis_freeresult(result);
 		crit(ap->logopt,
 		     MODPREFIX "couldn't enumrate nis+ map %s", ctxt->mapname);
+		free(tablename);
 		pthread_setcancelstate(cur_state, NULL);
 		return NSS_STATUS_UNAVAIL;
 	}
@@ -245,6 +250,7 @@ int lookup_read_map(struct autofs_point 
 
 	source->age = age;
 
+	free(tablename);
 	pthread_setcancelstate(cur_state, NULL);
 
 	return NSS_STATUS_SUCCESS;
@@ -271,11 +277,11 @@ static int lookup_one(struct autofs_poin
 	mc = source->mc;
 
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
-	tablename = alloca(strlen(key) +
-			strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20);
+	tablename = malloc(strlen(key) + strlen(ctxt->mapname) +
+			   strlen(ctxt->domainname) + 20);
 	if (!tablename) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		logerr(MODPREFIX "alloca: %s", estr);
+		logerr(MODPREFIX "malloc: %s", estr);
 		pthread_setcancelstate(cur_state, NULL);
 		return -1;
 	}
@@ -286,6 +292,7 @@ static int lookup_one(struct autofs_poin
 	if (result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) {
 		nis_error rs = result->status;
 		nis_freeresult(result);
+		free(tablename);
 		pthread_setcancelstate(cur_state, NULL);
 		if (rs == NIS_NOTFOUND ||
 		    rs == NIS_S_NOTFOUND ||
@@ -303,6 +310,7 @@ static int lookup_one(struct autofs_poin
 	cache_unlock(mc);
 
 	nis_freeresult(result);
+	free(tablename);
 	pthread_setcancelstate(cur_state, NULL);
 
 	return ret;
@@ -327,10 +335,10 @@ static int lookup_wild(struct autofs_poi
 	mc = source->mc;
 
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
-	tablename = alloca(strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20);
+	tablename = malloc(strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20);
 	if (!tablename) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		logerr(MODPREFIX "alloca: %s", estr);
+		logerr(MODPREFIX "malloc: %s", estr);
 		pthread_setcancelstate(cur_state, NULL);
 		return -1;
 	}
@@ -341,6 +349,7 @@ static int lookup_wild(struct autofs_poi
 	if (result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) {
 		nis_error rs = result->status;
 		nis_freeresult(result);
+		free(tablename);
 		pthread_setcancelstate(cur_state, NULL);
 		if (rs == NIS_NOTFOUND ||
 		    rs == NIS_S_NOTFOUND ||
@@ -357,6 +366,7 @@ static int lookup_wild(struct autofs_poi
 	cache_unlock(mc);
 
 	nis_freeresult(result);
+	free(tablename);
 	pthread_setcancelstate(cur_state, NULL);
 
 	return ret;
@@ -546,36 +556,37 @@ int lookup_mount(struct autofs_point *ap
 	}
 	if (me && (me->source == source || *me->key == '/')) {
 		mapent_len = strlen(me->mapent);
-		mapent = alloca(mapent_len + 1);
+		mapent = malloc(mapent_len + 1);
 		strcpy(mapent, me->mapent);
 	}
 	cache_unlock(mc);
 
-	if (mapent) {
-		master_source_current_wait(ap->entry);
-		ap->entry->current = source;
+	if (!mapent)
+		return NSS_STATUS_TRYAGAIN;
 
-		debug(ap->logopt, MODPREFIX "%s -> %s", key, mapent);
-		ret = ctxt->parse->parse_mount(ap, key, key_len,
-					       mapent, ctxt->parse->context);
-		if (ret) {
-			time_t now = time(NULL);
-			int rv = CHE_OK;
+	master_source_current_wait(ap->entry);
+	ap->entry->current = source;
+
+	debug(ap->logopt, MODPREFIX "%s -> %s", key, mapent);
+	ret = ctxt->parse->parse_mount(ap, key, key_len,
+				       mapent, ctxt->parse->context);
+	if (ret) {
+		time_t now = time(NULL);
+		int rv = CHE_OK;
 
-			cache_writelock(mc);
+		cache_writelock(mc);
+		me = cache_lookup_distinct(mc, key);
+		if (!me)
+			rv = cache_update(mc, source, key, NULL, now);
+		if (rv != CHE_FAIL) {
 			me = cache_lookup_distinct(mc, key);
-			if (!me)
-				rv = cache_update(mc, source, key, NULL, now);
-			if (rv != CHE_FAIL) {
-				me = cache_lookup_distinct(mc, key);
-				me->status = time(NULL) + ap->negative_timeout;
-			}
-			cache_unlock(mc);
+			me->status = time(NULL) + ap->negative_timeout;
 		}
-	}
-
-	if (ret)
+		cache_unlock(mc);
+		free(mapent);
 		return NSS_STATUS_TRYAGAIN;
+	}
+	free(mapent);
 
 	return NSS_STATUS_SUCCESS;
 }
--- autofs-5.0.4.orig/modules/mount_autofs.c
+++ autofs-5.0.4/modules/mount_autofs.c
@@ -18,7 +18,6 @@
 #include <malloc.h>
 #include <string.h>
 #include <signal.h>
-#include <alloca.h>
 #include <sys/param.h>
 #include <sys/types.h>
 #include <sys/stat.h>
--- autofs-5.0.4.orig/modules/mount_bind.c
+++ autofs-5.0.4/modules/mount_bind.c
@@ -69,7 +69,7 @@ out:
 int mount_mount(struct autofs_point *ap, const char *root, const char *name, int name_len,
 		const char *what, const char *fstype, const char *options, void *context)
 {
-	char *fullpath;
+	char fullpath[PATH_MAX];
 	char buf[MAX_ERR_BUF];
 	int err;
 	int i, len;
@@ -80,14 +80,11 @@ int mount_mount(struct autofs_point *ap,
 	/* Root offset of multi-mount */
 	len = strlen(root);
 	if (root[len - 1] == '/') {
-		fullpath = alloca(len);
 		len = snprintf(fullpath, len, "%s", root);
 	/* Direct mount name is absolute path so don't use root */
 	} else if (*name == '/') {
-		fullpath = alloca(len + 1);
 		len = sprintf(fullpath, "%s", root);
 	} else {
-		fullpath = alloca(len + name_len + 2);
 		len = sprintf(fullpath, "%s/%s", root, name);
 	}
 	fullpath[len] = '\0';
@@ -141,7 +138,7 @@ int mount_mount(struct autofs_point *ap,
 		}
 	} else {
 		char *cp;
-		char *basepath = alloca(strlen(fullpath) + 1);
+		char basepath[PATH_MAX];
 		int status;
 		struct stat st;
 
--- autofs-5.0.4.orig/modules/mount_changer.c
+++ autofs-5.0.4/modules/mount_changer.c
@@ -44,7 +44,7 @@ int mount_init(void **context)
 int mount_mount(struct autofs_point *ap, const char *root, const char *name, int name_len,
 		const char *what, const char *fstype, const char *options, void *context)
 {
-	char *fullpath;
+	char fullpath[PATH_MAX];
 	char buf[MAX_ERR_BUF];
 	int err;
 	int len, status, existed = 1;
@@ -57,14 +57,11 @@ int mount_mount(struct autofs_point *ap,
 	/* Root offset of multi-mount */
 	len = strlen(root);
 	if (root[len - 1] == '/') {
-		fullpath = alloca(len);
 		len = snprintf(fullpath, len, "%s", root);
 	/* Direct mount name is absolute path so don't use root */
 	} else if (*name == '/') {
-		fullpath = alloca(len + 1);
 		len = sprintf(fullpath, "%s", root);
 	} else {
-		fullpath = alloca(len + name_len + 2);
 		len = sprintf(fullpath, "%s/%s", root, name);
 	}
 	fullpath[len] = '\0';
--- autofs-5.0.4.orig/modules/mount_ext2.c
+++ autofs-5.0.4/modules/mount_ext2.c
@@ -36,7 +36,7 @@ int mount_init(void **context)
 int mount_mount(struct autofs_point *ap, const char *root, const char *name, int name_len,
 		const char *what, const char *fstype, const char *options, void *context)
 {
-	char *fullpath;
+	char fullpath[PATH_MAX];
 	char buf[MAX_ERR_BUF];
 	const char *p, *p1;
 	int err, ro = 0;
@@ -49,14 +49,11 @@ int mount_mount(struct autofs_point *ap,
 	/* Root offset of multi-mount */
 	len = strlen(root);
 	if (root[len - 1] == '/') {
-		fullpath = alloca(len);
 		len = snprintf(fullpath, len, "%s", root);
 	/* Direct mount name is absolute path so don't use root */
 	} else if (*name == '/') {
-		fullpath = alloca(len + 1);
 		len = sprintf(fullpath, "%s", root);
 	} else {
-		fullpath = alloca(len + name_len + 2);
 		len = sprintf(fullpath, "%s/%s", root, name);
 	}
 	fullpath[len] = '\0';
--- autofs-5.0.4.orig/modules/mount_generic.c
+++ autofs-5.0.4/modules/mount_generic.c
@@ -37,7 +37,7 @@ int mount_mount(struct autofs_point *ap,
 		const char *what, const char *fstype, const char *options,
 		void *context)
 {
-	char *fullpath;
+	char fullpath[PATH_MAX];
 	char buf[MAX_ERR_BUF];
 	int err;
 	int len, status, existed = 1;
@@ -48,14 +48,11 @@ int mount_mount(struct autofs_point *ap,
 	/* Root offset of multi-mount */
 	len = strlen(root);
 	if (root[len - 1] == '/') {
-		fullpath = alloca(len);
 		len = snprintf(fullpath, len, "%s", root);
 	/* Direct mount name is absolute path so don't use root */
 	} else if (*name == '/') {
-		fullpath = alloca(len + 1);
 		len = sprintf(fullpath, "%s", root);
 	} else {
-		fullpath = alloca(len + name_len + 2);
 		len = sprintf(fullpath, "%s/%s", root, name);
 	}
 	fullpath[len] = '\0';
--- autofs-5.0.4.orig/CHANGELOG
+++ autofs-5.0.4/CHANGELOG
@@ -16,6 +16,7 @@
   use of 5.0.3 strartup behavior if required.
 - always read entire file map into cache to speed lookups.
 - make MAX_ERR_BUF and PARSE_MAX_BUF use easier to audit.
+- make some easy alloca replacements (Valerie Aurora Henson).
 
 4/11/2008 autofs-5.0.4
 -----------------------

autofs-5.0.4-fix-hosts-map-use-after-free.patch:

--- NEW FILE autofs-5.0.4-fix-hosts-map-use-after-free.patch ---
autofs-5.0.4 - fix hosts map use after free

From: Ian Kent <raven at themaw.net>

This patch fixed use a map entry after it has been freed in the
hosts map lookup module.
---

 CHANGELOG              |    1 +
 modules/lookup_hosts.c |    8 +++++---
 2 files changed, 6 insertions(+), 3 deletions(-)


diff --git a/CHANGELOG b/CHANGELOG
index eb4a189..3199e4d 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -9,6 +9,7 @@
   Valerie Aurora Henson).
 - clear the quoted flag after each character from program map input.
 - use CLOEXEC flag for setmntent also.
+- fix hosts map use after free.
 
 4/11/2008 autofs-5.0.4
 -----------------------
diff --git a/modules/lookup_hosts.c b/modules/lookup_hosts.c
index 93b975a..d3ae0e2 100644
--- a/modules/lookup_hosts.c
+++ b/modules/lookup_hosts.c
@@ -138,17 +138,19 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 	/* Check if we recorded a mount fail for this key anywhere */
 	me = lookup_source_mapent(ap, name, LKP_DISTINCT);
 	if (me) {
+		struct mapent_cache *fmc = me->mc;
+
 		if (me->status >= time(NULL)) {
-			cache_unlock(me->mc);
+			cache_unlock(fmc);
 			return NSS_STATUS_NOTFOUND;
 		}
 
 		if (!me->mapent) {
-			cache_delete(me->mc, name);
+			cache_delete(fmc, name);
 			me = NULL;
 		}
 
-		cache_unlock(me->mc);
+		cache_unlock(fmc);
 	}
 
 	cache_readlock(mc);

autofs-5.0.4-force-unlink-umount.patch:

--- NEW FILE autofs-5.0.4-force-unlink-umount.patch ---
autofs-5.0.4 - force unlink umount at startup

From: Ian Kent <raven at themaw.net>

Version 5.0.3 autofs would unlink existing mounts at startup. This
functioned OK most of the time but caused processes whose working
directory was within unlinked automounted directories to not get a
correct pwd reported by the system.

There can be situations where the unlink umounting is desirable, such
as when the daemon is forceably killed and we want to get rid of any
existing mounts at startup. This change provides a way to force this
old behavior by passing the "--force" option to the daemon. This can
also be done by using the "forcestart" and "forcerestart" actions to
the init script.

Note that the old behavior will always be used if the kernel does not
include the iotcl re-implementation which provides the ability to
re-connect to existing mounts.
---

 CHANGELOG             |    2 ++
 daemon/automount.c    |   14 +++++++++++++-
 daemon/direct.c       |    2 +-
 daemon/indirect.c     |    2 +-
 include/automount.h   |    3 +++
 man/automount.8       |   13 +++++++++++++
 redhat/autofs.init.in |   10 +++++++++-
 samples/rc.autofs.in  |   10 +++++++++-
 8 files changed, 51 insertions(+), 5 deletions(-)


diff --git a/CHANGELOG b/CHANGELOG
index 7dee674..d4dd70b 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -12,6 +12,8 @@
 - fix hosts map use after free.
 - fix uri list locking (again).
 - check for stale SASL credentials upon connect fail.
+- add "forcestart" and "forcerestart" init script options to allow
+  use of 5.0.3 strartup behavior if required.
 
 4/11/2008 autofs-5.0.4
 -----------------------
diff --git a/daemon/automount.c b/daemon/automount.c
index f04273f..e20e7c9 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -57,6 +57,7 @@ static char *pid_file = NULL;		/* File in which to keep pid */
 unsigned int global_random_selection;	/* use random policy when selecting
 					 * which multi-mount host to mount */
 long global_negative_timeout = -1;
+int do_force_unlink = 0;		/* Forceably unlink mount tree at startup */
 
 static int start_pipefd[2];
 static int st_stat = 0;
@@ -1798,6 +1799,7 @@ int main(int argc, char *argv[])
 		{"version", 0, 0, 'V'},
 		{"set-log-priority", 1, 0, 'l'},
 		{"dont-check-daemon", 0, 0, 'C'},
+		{"force", 0, 0, 'F'},
 		{0, 0, 0, 0}
 	};
 
@@ -1819,7 +1821,7 @@ int main(int argc, char *argv[])
 	daemon_check = 1;
 
 	opterr = 0;
-	while ((opt = getopt_long(argc, argv, "+hp:t:vdD:fVrO:l:n:C", long_options, NULL)) != EOF) {
+	while ((opt = getopt_long(argc, argv, "+hp:t:vdD:fVrO:l:n:CF", long_options, NULL)) != EOF) {
 		switch (opt) {
 		case 'h':
 			usage();
@@ -1892,6 +1894,10 @@ int main(int argc, char *argv[])
 			daemon_check = 0;
 			break;
 
+		case 'F':
+			do_force_unlink = 1;
+			break;
+
 		case '?':
 		case ':':
 			printf("%s: Ambiguous or unknown options\n", program);
@@ -2066,6 +2072,12 @@ int main(int argc, char *argv[])
 		exit(3);
 	}
 
+	/*
+	 * Mmm ... reset force unlink umount so we don't also do this
+	 * in future when we receive a HUP signal.
+	 */
+	do_force_unlink = 0;
+
 	res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
 	close(start_pipefd[1]);
 
diff --git a/daemon/direct.c b/daemon/direct.c
index d9dda3d..2d979f1 100644
--- a/daemon/direct.c
+++ b/daemon/direct.c
@@ -335,7 +335,7 @@ int do_mount_autofs_direct(struct autofs_point *ap, struct mnt_list *mnts, struc
 	/* Calculate the timeouts */
 	ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
 
-	if (ops->version) {
+	if (ops->version && !do_force_unlink) {
 		ap->flags |= MOUNT_FLAG_REMOUNT;
 		ret = try_remount(ap, me, t_direct);
 		ap->flags &= ~MOUNT_FLAG_REMOUNT;
diff --git a/daemon/indirect.c b/daemon/indirect.c
index 0721707..2ccbc53 100644
--- a/daemon/indirect.c
+++ b/daemon/indirect.c
@@ -97,7 +97,7 @@ static int do_mount_autofs_indirect(struct autofs_point *ap, const char *root)
 
 	ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
 
-	if (ops->version) {
+	if (ops->version && !do_force_unlink) {
 		ap->flags |= MOUNT_FLAG_REMOUNT;
 		ret = try_remount(ap, NULL, t_indirect);
 		ap->flags &= ~MOUNT_FLAG_REMOUNT;
diff --git a/include/automount.h b/include/automount.h
index 46cb6c6..1f14d5b 100644
--- a/include/automount.h
+++ b/include/automount.h
@@ -428,6 +428,9 @@ struct autofs_point {
 	struct list_head submounts;	/* List of child submounts */
 };
 
+/* Foreably unlink existing mounts at startup. */
+extern int do_force_unlink;
+
 /* Standard functions used by daemon or modules */
 
 #define	MOUNT_OFFSET_OK		0
diff --git a/man/automount.8 b/man/automount.8
index d9285bf..9fcaaf4 100644
--- a/man/automount.8
+++ b/man/automount.8
@@ -84,6 +84,11 @@ path name as specified in the master map.
 .TP
 .I "\-C, \-\-dont-check-daemon"
 Don't check if the daemon is currently running (see NOTES).
+.TP
+.I "\-F, \-\-force"
+Force an unlink umount of existing mounts under autofs managed mount points
+during startup. This can cause problems for processes with working directories
+within these mounts (see NOTES).
 .SH ARGUMENTS
 \fBautomount\fP takes one optional argument, the name of the master map to
 use.
@@ -132,6 +137,14 @@ for certain types of automount maps. The mounts of the seperate daemons
 might interfere with one another. The implications of running multiple
 daemon instances needs to be checked and tested before we can say this
 is supported.
+.P
+If the option to force an unlink of mounts at startup is used then processes
+whose working directory is within unlinked automounted directories will not
+get the correct pwd from the system. This is because, after the mount is
+unlinked from the mount tree, anything that needs to walk back up the mount
+tree to construct a path, such as getcwd(2) and the proc filesystem
+/proc/<pid>/cwd, cannot work because the point from which the path is
+constructed has been detached from the mount tree.
 .SH "SEE ALSO"
 .BR autofs (5),
 .BR autofs (8),
diff --git a/redhat/autofs.init.in b/redhat/autofs.init.in
index 65c786e..471667e 100644
--- a/redhat/autofs.init.in
+++ b/redhat/autofs.init.in
@@ -137,6 +137,10 @@ case "$1" in
 	start)
 		start
 		;;
+	forcestart)
+		OPTIONS="$OPTIONS --force"
+		start
+		;;
 	stop)
 		stop
 		;;
@@ -146,6 +150,10 @@ case "$1" in
 	restart)
 		restart
 		;;
+	forcerestart)
+		OPTIONS="$OPTIONS --force"
+		restart
+		;;
 	reload)
 		reload
 		;;
@@ -155,7 +163,7 @@ case "$1" in
 		fi
 		;;
 	*)
-		echo $"Usage: $0 {start|stop|status|restart|reload|condrestart}"
+		echo $"Usage: $0 {start|forcestart|stop|status|restart|orcerestart|reload|condrestart}"
 		exit 1;
 		;;
 esac
diff --git a/samples/rc.autofs.in b/samples/rc.autofs.in
index 51f5b02..2877fe2 100644
--- a/samples/rc.autofs.in
+++ b/samples/rc.autofs.in
@@ -117,17 +117,25 @@ case "$1" in
 	start)
 		start
 		;;
+	forcestart)
+		OPTIONS="$OPTIONS --force"
+		start
+		;;
 	stop)
 		stop
 		;;
 	restart)
 		restart
 		;;
+	forcerestart)
+		OPTIONS="$OPTIONS --force"
+		restart
+		;;
 	reload)
 		reload
 		;;
 	*)
-		echo $"Usage: $0 {start|stop|restart|reload}"
+		echo $"Usage: $0 {start|forcestart|stop|restart|forcerestart|reload}"
 		exit 1;
 		;;
 esac

autofs-5.0.4-ipv6-name-and-address-support.patch:

--- NEW FILE autofs-5.0.4-ipv6-name-and-address-support.patch ---
autofs-5.0.4 - ipv6 name and address support

From: Ian Kent <raven at themaw.net>

For ipv6 we need to convert all ipv4 specific function calls to ipv6
compatible function calls and update the rpc code to deal with ipv6
addresses. The host proximity calculation also needes to be updated.

I'm sure this isn't completely correct yet and it will need more work
as I become more familiar with how ipv6 and subneting with it is used.
The changes so far function correctly for the current autofs
connectathon test suite maps so I hope there aren't any regressions
with current map configurations.
---

 CHANGELOG            |    1 
 include/replicated.h |    2 
 include/rpc_subs.h   |    4 
 lib/rpc_subs.c       |  486 +++++++++++++++++++++++++++++++++------------------
 modules/cyrus-sasl.c |   17 +
 modules/replicated.c |  235 +++++++++++++++++-------
 6 files changed, 501 insertions(+), 244 deletions(-)


--- autofs-5.0.4.orig/include/replicated.h
+++ autofs-5.0.4/include/replicated.h
@@ -51,7 +51,7 @@
 
 struct host {
 	char *name;
-	char *addr;
+	struct sockaddr *addr;
 	size_t addr_len;
 	char *path;
 	unsigned int version;
--- autofs-5.0.4.orig/include/rpc_subs.h
+++ autofs-5.0.4/include/rpc_subs.h
@@ -46,7 +46,7 @@
 
 struct conn_info {
 	const char *host;
-	const char *addr;
+	struct sockaddr *addr;
 	size_t addr_len;
 	unsigned short port;
 	unsigned long program;
@@ -63,7 +63,7 @@ int rpc_udp_getclient(struct conn_info *
 void rpc_destroy_udp_client(struct conn_info *);
 int rpc_tcp_getclient(struct conn_info *, unsigned int, unsigned int);
 void rpc_destroy_tcp_client(struct conn_info *);
-int rpc_portmap_getclient(struct conn_info *, const char *, const char *, size_t, const char *, unsigned int);
+int rpc_portmap_getclient(struct conn_info *, const char *, struct sockaddr *, size_t, const char *, unsigned int);
 unsigned short rpc_portmap_getport(struct conn_info *, struct pmap *);
 int rpc_ping_proto(struct conn_info *);
 int rpc_ping(const char *, long, long, unsigned int);
--- autofs-5.0.4.orig/lib/rpc_subs.c
+++ autofs-5.0.4/lib/rpc_subs.c
@@ -17,10 +17,11 @@
 #define _GNU_SOURCE
 #endif
 
+#include "config.h"
+
 #include <rpc/types.h>
 #include <rpc/rpc.h>
 #include <rpc/pmap_prot.h>
-
 #include <sys/socket.h>
 #include <netdb.h>
 #include <net/if.h>
@@ -54,145 +55,76 @@
 
 inline void dump_core(void);
 
-/*
- * Create a UDP RPC client
- */
-static CLIENT *create_udp_client(struct conn_info *info)
+static CLIENT *rpc_clntudp_create(struct sockaddr *addr, struct conn_info *info, int *fd)
 {
-	int fd, ret, ghn_errno;
-	CLIENT *client;
-	struct sockaddr_in laddr, raddr;
-	struct hostent hp;
-	struct hostent *php = &hp;
-	struct hostent *result;
-	char buf[HOST_ENT_BUF_SIZE];
-	size_t len;
-
-	if (info->proto->p_proto != IPPROTO_UDP)
-		return NULL;
-
-	if (info->client) {
-		if (!clnt_control(info->client, CLGET_FD, (char *) &fd)) {
-			fd = -1;
-			clnt_destroy(info->client);
-			info->client = NULL;
-		} else {
-			clnt_control(info->client, CLSET_FD_NCLOSE, NULL);
-			clnt_destroy(info->client);
-		}
-	}
-
-	memset(&laddr, 0, sizeof(laddr));
-	memset(&raddr, 0, sizeof(raddr));
-
-	raddr.sin_family = AF_INET;
-	if (info->addr) {
-		memcpy(&raddr.sin_addr.s_addr, info->addr, info->addr_len);
-		goto got_addr;
-	}
-
-	if (inet_aton(info->host, &raddr.sin_addr))
-		goto got_addr;
-
-	memset(&hp, 0, sizeof(struct hostent));
-
-	ret = gethostbyname_r(info->host, php,
-			buf, HOST_ENT_BUF_SIZE, &result, &ghn_errno);
-	if (ret || !result) {
-		int err = ghn_errno == -1 ? errno : ghn_errno;
-		char *estr = strerror_r(err, buf, HOST_ENT_BUF_SIZE);
-		logerr("hostname lookup failed: %s", estr);
-		goto out_close;
-	}
-	memcpy(&raddr.sin_addr.s_addr, php->h_addr, php->h_length);
-
-got_addr:
-	raddr.sin_port = htons(info->port);
-
-	if (!info->client) {
-		/*
-		 * bind to any unused port.  If we left this up to the rpc
-		 * layer, it would bind to a reserved port, which has been shown
-		 * to exhaust the reserved port range in some situations.
-		 */
-		fd = open_sock(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
-		if (fd < 0)
-			return NULL;
-
-		laddr.sin_family = AF_INET;
-		laddr.sin_port = 0;
-		laddr.sin_addr.s_addr = htonl(INADDR_ANY);
-
-		len = sizeof(struct sockaddr_in);
-		if (bind(fd, (struct sockaddr *)&laddr, len) < 0) {
-			close(fd);
-			fd = RPC_ANYSOCK;
-			/* FALLTHROUGH */
-		}
-	}
-
-	client = clntudp_bufcreate(&raddr,
-				   info->program, info->version,
-				   info->timeout, &fd,
-				   info->send_sz, info->recv_sz);
+	struct sockaddr_in *in4_raddr;
+	struct sockaddr_in6 *in6_raddr;
+	CLIENT *client = NULL;
+
+	switch (addr->sa_family) {
+	case AF_INET:
+		in4_raddr = (struct sockaddr_in *) addr;
+		in4_raddr->sin_port = htons(info->port);
+		client = clntudp_bufcreate(in4_raddr,
+					   info->program, info->version,
+					   info->timeout, fd,
+					   info->send_sz, info->recv_sz);
+		break;
 
-	if (!client) {
-		info->client = NULL;
-		goto out_close;
-	}
+	case AF_INET6:
+#ifndef INET6
+		/* Quiet compile warning */
+		in6_raddr = NULL;
+#else
+		in6_raddr = (struct sockaddr_in6 *) addr;
+		in6_raddr->sin6_port = htons(info->port);
+		client = clntudp6_bufcreate(in6_raddr,
+					    info->program, info->version,
+					    info->timeout, fd,
+					    info->send_sz, info->recv_sz);
+#endif
+		break;
 
-	/* Close socket fd on destroy, as is default for rpcowned fds */
-	if  (!clnt_control(client, CLSET_FD_CLOSE, NULL)) {
-		clnt_destroy(client);
-		info->client = NULL;
-		goto out_close;
+	default:
+		break;
 	}
 
 	return client;
-
-out_close:
-	if (fd != -1)
-		close(fd);
-	return NULL;
 }
 
-int rpc_udp_getclient(struct conn_info *info,
-		      unsigned int program, unsigned int version)
+static CLIENT *rpc_clnttcp_create(struct sockaddr *addr, struct conn_info *info, int *fd)
 {
-	struct protoent *pe_proto;
-	CLIENT *client;
+	struct sockaddr_in *in4_raddr;
+	struct sockaddr_in6 *in6_raddr;
+	CLIENT *client = NULL;
+
+	switch (addr->sa_family) {
+	case AF_INET:
+		in4_raddr = (struct sockaddr_in *) addr;
+		in4_raddr->sin_port = htons(info->port);
+		client = clnttcp_create(in4_raddr,
+					info->program, info->version, fd,
+					info->send_sz, info->recv_sz);
+		break;
 
-	if (!info->client) {
-		pe_proto = getprotobyname("udp");
-		if (!pe_proto)
-			return 0;
+	case AF_INET6:
+#ifndef INET6
+		/* Quiet compile warning */
+		in6_raddr = NULL;
+#else
+		in6_raddr = (struct sockaddr_in6 *) addr;
+		in6_raddr->sin6_port = htons(info->port);
+		client = clnttcp6_create(in6_raddr,
+					 info->program, info->version, fd,
+					 info->send_sz, info->recv_sz);
+#endif
+		break;
 
-		info->proto = pe_proto;
-		info->send_sz = UDPMSGSIZE;
-		info->recv_sz = UDPMSGSIZE;
+	default:
+		break;
 	}
 
-	info->program = program;
-	info->version = version;
-
-	client = create_udp_client(info);
-
-	if (!client)
-		return 0;
-
-	info->client = client;
-
-	return 1;
-}
-
-void rpc_destroy_udp_client(struct conn_info *info)
-{
-	if (!info->client)
-		return;
-
-	clnt_destroy(info->client);
-	info->client = NULL;
-	return;
+	return client;
 }
 
 /*
@@ -201,12 +133,11 @@ void rpc_destroy_udp_client(struct conn_
  *  The input struct timeval always has tv_nsec set to zero,
  *  we only ever use tv_sec for timeouts.
  */
-static int connect_nb(int fd, struct sockaddr_in *addr, struct timeval *tout)
+static int connect_nb(int fd, struct sockaddr *addr, socklen_t len, struct timeval *tout)
 {
 	struct pollfd pfd[1];
 	int timeout = tout->tv_sec;
 	int flags, ret;
-	socklen_t len;
 
 	flags = fcntl(fd, F_GETFL, 0);
 	if (flags < 0)
@@ -221,8 +152,7 @@ static int connect_nb(int fd, struct soc
 	 * we set ret = -errno to capture it in case we decide to
 	 * use it later.
 	 */
-	len = sizeof(struct sockaddr);
-	ret = connect(fd, (struct sockaddr *)addr, len);
+	ret = connect(fd, addr, len);
 	if (ret < 0 && errno != EINPROGRESS) {
 		ret = -errno;
 		goto done;
@@ -277,26 +207,117 @@ done:
 	return ret;
 }
 
+static CLIENT *rpc_do_create_client(struct sockaddr *addr, struct conn_info *info, int *fd)
+{
+	CLIENT *client = NULL;
+	struct sockaddr *laddr;
+	struct sockaddr_in in4_laddr;
+	struct sockaddr_in6 in6_laddr;
+	int type, proto;
+	socklen_t slen;
+
+	proto = info->proto->p_proto;
+	if (proto == IPPROTO_UDP)
+		type = SOCK_DGRAM;
+	else
+		type = SOCK_STREAM;
+
+	/*
+	 * bind to any unused port.  If we left this up to the rpc
+	 * layer, it would bind to a reserved port, which has been shown
+	 * to exhaust the reserved port range in some situations.
+	 */
+	switch (addr->sa_family) {
+	case AF_INET:
+		in4_laddr.sin_family = AF_INET;
+		in4_laddr.sin_port = htons(0);
+		in4_laddr.sin_addr.s_addr = htonl(INADDR_ANY);
+		slen = sizeof(struct sockaddr_in);
+		laddr = (struct sockaddr *) &in4_laddr;
+		break;
+
+	case AF_INET6:
+#ifndef INET6
+		/* Quiet compiler */
+		in6_laddr.sin6_family = AF_INET6;
+		return NULL;
+#else
+		in6_laddr.sin6_family = AF_INET6;
+		in6_laddr.sin6_port = htons(0);
+		in6_laddr.sin6_addr = in6addr_any;
+		slen = sizeof(struct sockaddr_in6);
+		laddr = (struct sockaddr *) &in6_laddr;
+		break;
+#endif
+	default:
+		return NULL;
+	}
+
+	if (!info->client) {
+		*fd = open_sock(addr->sa_family, type, proto);
+		if (*fd < 0)
+			return NULL;
+
+		if (bind(*fd, laddr, slen) < 0) {
+			close(*fd);
+			return NULL;
+		}
+	}
+
+	switch (info->proto->p_proto) {
+	case IPPROTO_UDP:
+		if (!info->client) {
+			*fd = open_sock(addr->sa_family, type, proto);
+			if (*fd < 0)
+				return NULL;
+
+			if (bind(*fd, laddr, slen) < 0) {
+				close(*fd);
+				return NULL;
+			}
+		}
+		client = rpc_clntudp_create(addr, info, fd);
+		break;
+
+	case IPPROTO_TCP:
+		if (!info->client) {
+			*fd = open_sock(addr->sa_family, type, proto);
+			if (*fd < 0)
+				return NULL;
+
+			if (connect_nb(*fd, laddr, slen, &info->timeout) < 0) {
+				close(*fd);
+				return NULL;
+			}
+		}
+		client = rpc_clnttcp_create(addr, info, fd);
+		break;
+
+	default:
+		break;
+	}
+
+	return client;
+}
+
 /*
- * Create a TCP RPC client using non-blocking connect
+ * Create a UDP RPC client
  */
-static CLIENT *create_tcp_client(struct conn_info *info)
+static CLIENT *create_udp_client(struct conn_info *info)
 {
-	int fd, ghn_errno;
-	CLIENT *client;
-	struct sockaddr_in addr;
-	struct hostent hp;
-	struct hostent *php = &hp;
-	struct hostent *result;
-	char buf[HOST_ENT_BUF_SIZE];
-	int ret;
+	CLIENT *client = NULL;
+	struct addrinfo *ai, *haddr;
+	struct addrinfo hints;
+	int fd, ret;
 
-	if (info->proto->p_proto != IPPROTO_TCP)
+	if (info->proto->p_proto != IPPROTO_UDP)
 		return NULL;
 
+	fd = RPC_ANYSOCK;
+
 	if (info->client) {
 		if (!clnt_control(info->client, CLGET_FD, (char *) &fd)) {
-			fd = -1;
+			fd = RPC_ANYSOCK;
 			clnt_destroy(info->client);
 			info->client = NULL;
 		} else {
@@ -305,51 +326,174 @@ static CLIENT *create_tcp_client(struct 
 		}
 	}
 
-	memset(&addr, 0, sizeof(addr));
-
-	addr.sin_family = AF_INET;
 	if (info->addr) {
-		memcpy(&addr.sin_addr.s_addr, info->addr, info->addr_len);
-		goto got_addr;
+		client = rpc_do_create_client(info->addr, info, &fd);
+		if (client)
+			goto done;
+
+		if (!info->client) {
+			close(fd);
+			fd = RPC_ANYSOCK;
+		}
 	}
 
-	if (inet_aton(info->host, &addr.sin_addr))
-		goto got_addr;
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_flags = AI_ADDRCONFIG;
+	hints.ai_family = AF_UNSPEC;
+	hints.ai_socktype = SOCK_DGRAM;
+
+	ret = getaddrinfo(info->host, NULL, &hints, &ai);
+	if (ret) {
+		error(LOGOPT_ANY,
+		      "hostname lookup failed: %s", gai_strerror(ret));
+		goto out_close;
+	}
+
+	haddr = ai;
+	while (haddr) {
+		client = rpc_do_create_client(haddr->ai_addr, info, &fd);
+		if (client)
+			break;
+
+		if (!info->client) {
+			close(fd);
+			fd = RPC_ANYSOCK;
+		}
+
+		haddr = haddr->ai_next;
+	}
 
-	memset(&hp, 0, sizeof(struct hostent));
+	freeaddrinfo(ai);
 
-	ret = gethostbyname_r(info->host, php,
-			buf, HOST_ENT_BUF_SIZE, &result, &ghn_errno);
-	if (ret || !result) {
-		int err = ghn_errno == -1 ? errno : ghn_errno;
-		char *estr =  strerror_r(err, buf, HOST_ENT_BUF_SIZE);
-		logerr("hostname lookup failed: %s", estr);
+	if (!client) {
+		info->client = NULL;
+		goto out_close;
+	}
+done:
+	/* Close socket fd on destroy, as is default for rpcowned fds */
+	if  (!clnt_control(client, CLSET_FD_CLOSE, NULL)) {
+		clnt_destroy(client);
+		info->client = NULL;
 		goto out_close;
 	}
-	memcpy(&addr.sin_addr.s_addr, php->h_addr, php->h_length);
 
-got_addr:
-	addr.sin_port = htons(info->port);
+	return client;
+
+out_close:
+	if (fd != -1)
+		close(fd);
+	return NULL;
+}
+
+int rpc_udp_getclient(struct conn_info *info,
+		      unsigned int program, unsigned int version)
+{
+	struct protoent *pe_proto;
+	CLIENT *client;
 
 	if (!info->client) {
-		fd = open_sock(PF_INET, SOCK_STREAM, info->proto->p_proto);
-		if (fd < 0)
-			return NULL;
+		pe_proto = getprotobyname("udp");
+		if (!pe_proto)
+			return 0;
+
+		info->proto = pe_proto;
+		info->send_sz = UDPMSGSIZE;
+		info->recv_sz = UDPMSGSIZE;
+	}
+
+	info->program = program;
+	info->version = version;
+
+	client = create_udp_client(info);
+
+	if (!client)
+		return 0;
+
+	info->client = client;
+
+	return 1;
+}
+
+void rpc_destroy_udp_client(struct conn_info *info)
+{
+	if (!info->client)
+		return;
+
+	clnt_destroy(info->client);
+	info->client = NULL;
+	return;
+}
+
+/*
+ * Create a TCP RPC client using non-blocking connect
+ */
+static CLIENT *create_tcp_client(struct conn_info *info)
+{
+	CLIENT *client = NULL;
+	struct addrinfo *ai, *haddr;
+	struct addrinfo hints;
+	int fd, ret;
+
+	if (info->proto->p_proto != IPPROTO_TCP)
+		return NULL;
+
+	fd = RPC_ANYSOCK;
+
+	if (info->client) {
+		if (!clnt_control(info->client, CLGET_FD, (char *) &fd)) {
+			fd = RPC_ANYSOCK;
+			clnt_destroy(info->client);
+			info->client = NULL;
+		} else {
+			clnt_control(info->client, CLSET_FD_NCLOSE, NULL);
+			clnt_destroy(info->client);
+		}
+	}
+
+	if (info->addr) {
+		client = rpc_do_create_client(info->addr, info, &fd);
+		if (client)
+			goto done;
 
-		ret = connect_nb(fd, &addr, &info->timeout);
-		if (ret < 0)
-			goto out_close;
+		if (!info->client) {
+			close(fd);
+			fd = RPC_ANYSOCK;
+		}
+	}
+
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_flags = AI_ADDRCONFIG;
+	hints.ai_family = AF_UNSPEC;
+	hints.ai_socktype = SOCK_STREAM;
+
+	ret = getaddrinfo(info->host, NULL, &hints, &ai);
+	if (ret) {
+		error(LOGOPT_ANY,
+		      "hostname lookup failed: %s", gai_strerror(ret));
+		goto out_close;
+	}
+
+	haddr = ai;
+	while (haddr) {
+		client = rpc_do_create_client(haddr->ai_addr, info, &fd);
+		if (client)
+			break;
+
+		if (!info->client) {
+			close(fd);
+			fd = RPC_ANYSOCK;
+		}
+
+		haddr = haddr->ai_next;
 	}
 
-	client = clnttcp_create(&addr,
-				info->program, info->version, &fd,
-				info->send_sz, info->recv_sz);
+	freeaddrinfo(ai);
 
 	if (!client) {
 		info->client = NULL;
 		goto out_close;
 	}
-
+done:
 	/* Close socket fd on destroy, as is default for rpcowned fds */
 	if  (!clnt_control(client, CLSET_FD_CLOSE, NULL)) {
 		clnt_destroy(client);
@@ -420,7 +564,7 @@ void rpc_destroy_tcp_client(struct conn_
 }
 
 int rpc_portmap_getclient(struct conn_info *info,
-			  const char *host, const char *addr, size_t addr_len,
+			  const char *host, struct sockaddr *addr, size_t addr_len,
 			  const char *proto, unsigned int option)
 {
 	struct protoent *pe_proto;
--- autofs-5.0.4.orig/modules/cyrus-sasl.c
+++ autofs-5.0.4/modules/cyrus-sasl.c
@@ -732,16 +732,25 @@ sasl_bind_mech(unsigned logopt, LDAP *ld
 	debug(logopt, "Attempting sasl bind with mechanism %s", mech);
 
 	result = ldap_get_option(ldap, LDAP_OPT_HOST_NAME, &host);
-	if (result != LDAP_SUCCESS || !host) {
+	if (result != LDAP_OPT_SUCCESS || !host) {
 		debug(logopt, "failed to get hostname for connection");
 		return NULL;
 	}
 
-	if ((tmp = strchr(host, ':')))
-		*tmp = '\0';
+	if ((tmp = strrchr(host, ':'))) {
+		if (*(tmp - 1) != ']') {
+			*tmp = '\0';
+			tmp = host;
+		} else {
+			*(tmp - 1) = '\0';
+			tmp = host;
+			if (*tmp == '[')
+				tmp++;
+		}
+	}
 
 	/* Create a new authentication context for the service. */
-	result = sasl_client_new("ldap", host, NULL, NULL, NULL, 0, &conn);
+	result = sasl_client_new("ldap", tmp, NULL, NULL, NULL, 0, &conn);
 	if (result != SASL_OK) {
 		error(logopt, "sasl_client_new failed with error %d",
 		      result);
--- autofs-5.0.4.orig/modules/replicated.c
+++ autofs-5.0.4/modules/replicated.c
@@ -45,7 +45,7 @@
 #include <stdlib.h>
 #include <sys/errno.h>
 #include <sys/types.h>
-#include <netinet/in.h>
+#include <stdint.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <arpa/inet.h>
@@ -75,6 +75,20 @@ static int volatile ifc_last_len = 0;
 #define max(x, y)	(x >= y ? x : y)
 #define mmax(x, y, z)	(max(x, y) == x ? max(x, z) : max(y, z))
 
+unsigned int ipv6_mask_cmp(uint32_t *host, uint32_t *iface, uint32_t *mask)
+{
+	unsigned int ret = 1;
+	unsigned int i;
+
+	for (i = 0; i < 4; i++) {
+		if ((host[i] & mask[i]) != (iface[i] & mask[i])) {
+			ret = 0;
+			break;
+		}
+	}
+	return ret;
+}
+
 void seed_random(void)
 {
 	int fd;
@@ -136,20 +150,49 @@ static int alloc_ifreq(struct ifconf *if
 	return 1;
 }
 
-static unsigned int get_proximity(const char *host_addr, int addr_len)
+static unsigned int get_proximity(struct sockaddr *host_addr)
 {
-	struct sockaddr_in *msk_addr, *if_addr;
+	struct sockaddr_in *addr, *msk_addr, *if_addr;
+	struct sockaddr_in6 *addr6, *msk6_addr, *if6_addr;
 	struct in_addr *hst_addr;
-	char tmp[20], buf[MAX_ERR_BUF], *ptr;
+	struct in6_addr *hst6_addr;
+	int addr_len;
+	char buf[MAX_ERR_BUF], *ptr;
 	struct ifconf ifc;
 	struct ifreq *ifr, nmptr;
 	int sock, ret, i;
-	uint32_t mask, ha, ia;
+	uint32_t mask, ha, ia, *mask6, *ha6, *ia6;
 
-	memcpy(tmp, host_addr, addr_len);
-	hst_addr = (struct in_addr *) tmp;
+	addr = NULL;
+	addr6 = NULL;
+	hst_addr = NULL;
+	hst6_addr = NULL;
+	mask6 = NULL;
+	ha6 = NULL;
+	ia6 = NULL;
+
+	switch (host_addr->sa_family) {
+	case AF_INET:
+		addr = (struct sockaddr_in *) host_addr;
+		hst_addr = (struct in_addr *) &addr->sin_addr;
+		ha = ntohl((uint32_t) hst_addr->s_addr);
+		addr_len = sizeof(hst_addr);
+		break;
 
-	ha = ntohl((uint32_t) hst_addr->s_addr);
+	case AF_INET6:
+#ifndef INET6
+		return PROXIMITY_ERROR;
+#else
+		addr6 = (struct sockaddr_in6 *) host_addr;
+		hst6_addr = (struct in6_addr *) &addr6->sin6_addr;
+		ha6 = &hst6_addr->s6_addr32[0];
+		addr_len = sizeof(hst6_addr);
+		break;
+#endif
+
+	default:
+		return PROXIMITY_ERROR;
+	}
 
 	sock = open_sock(AF_INET, SOCK_DGRAM, 0);
 	if (sock < 0) {
@@ -174,6 +217,10 @@ static unsigned int get_proximity(const 
 
 		switch (ifr->ifr_addr.sa_family) {
 		case AF_INET:
+#ifndef INET6
+			if (host_addr->sa_family == AF_INET6)
+				break;
+#endif
 			if_addr = (struct sockaddr_in *) &ifr->ifr_addr;
 			ret = memcmp(&if_addr->sin_addr, hst_addr, addr_len);
 			if (!ret) {
@@ -183,6 +230,20 @@ static unsigned int get_proximity(const 
 			}
 			break;
 
+		case AF_INET6:
+#ifndef INET6
+			if (host_addr->sa_family == AF_INET)
+				break;
+
+			if6_addr = (struct sockaddr_in6 *) &ifr->ifr_addr;
+			ret = memcmp(&if6_addr->sin6_addr, hst6_addr, addr_len);
+			if (!ret) {
+				close(sock);
+				free(ifc.ifc_req);
+				return PROXIMITY_LOCAL;
+			}
+#endif
+
 		default:
 			break;
 		}
@@ -197,23 +258,27 @@ static unsigned int get_proximity(const 
 	while (ptr < (char *) ifc.ifc_req + ifc.ifc_len) {
 		ifr = (struct ifreq *) ptr;
 
+		nmptr = *ifr;
+		ret = ioctl(sock, SIOCGIFNETMASK, &nmptr);
+		if (ret == -1) {
+			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+			logerr("ioctl: %s", estr);
+			close(sock);
+			free(ifc.ifc_req);
+			return PROXIMITY_ERROR;
+		}
+
 		switch (ifr->ifr_addr.sa_family) {
 		case AF_INET:
+#ifndef INET6
+			if (host_addr->sa_family == AF_INET6)
+				break;
+#endif
 			if_addr = (struct sockaddr_in *) &ifr->ifr_addr;
 			ia =  ntohl((uint32_t) if_addr->sin_addr.s_addr);
 
 			/* Is the address within a localiy attached subnet */
 
-			nmptr = *ifr;
-			ret = ioctl(sock, SIOCGIFNETMASK, &nmptr);
-			if (ret == -1) {
-				char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-				logerr("ioctl: %s", estr);
-				close(sock);
-				free(ifc.ifc_req);
-				return PROXIMITY_ERROR;
-			}
-
 			msk_addr = (struct sockaddr_in *) &nmptr.ifr_netmask;
 			mask = ntohl((uint32_t) msk_addr->sin_addr.s_addr);
 
@@ -247,6 +312,29 @@ static unsigned int get_proximity(const 
 			}
 			break;
 
+		case AF_INET6:
+#ifndef INET6
+			if (host_addr->sa_family == AF_INET)
+				break;
+
+			if6_addr = (struct sockaddr_in6 *) &ifr->ifr_addr;
+			ia6 = &if6_addr->sin6_addr.s6_addr32[0];
+
+			/* Is the address within the network of the interface */
+
+			msk6_addr = (struct sockaddr_in6 *) &nmptr.ifr_netmask;
+			mask6 = &msk6_addr->sin6_addr.s6_addr32[0];
+
+			if (ipv6_mask_cmp(ha6, ia6, mask6)) {
+				close(sock);
+				free(ifc.ifc_req);
+				return PROXIMITY_SUBNET;
+			}
+
+			/* How do we define "local network" in ipv6? */
+#endif
+			break;
+
 		default:
 			break;
 		}
@@ -262,11 +350,12 @@ static unsigned int get_proximity(const 
 }
 
 static struct host *new_host(const char *name,
-			     const char *addr, size_t addr_len,
+			     struct sockaddr *addr, size_t addr_len,
 			     unsigned int proximity, unsigned int weight)
 {
 	struct host *new;
-	char *tmp1, *tmp2;
+	struct sockaddr *tmp2;
+	char *tmp1;
 
 	if (!name || !addr)
 		return NULL;
@@ -950,65 +1039,78 @@ int prune_host_list(unsigned logopt, str
 	return 1;
 }
 
-static int add_host_addrs(struct host **list, const char *host, unsigned int weight)
+static int add_new_host(struct host **list,
+			const char *host, unsigned int weight,
+			struct addrinfo *host_addr)
 {
-	struct hostent he;
-	struct hostent *phe = &he;
-	struct hostent *result;
-	struct sockaddr_in saddr;
-	char buf[MAX_IFC_BUF], **haddr;
-	int ghn_errno, ret;
 	struct host *new;
 	unsigned int prx;
+	int addr_len;
 
-	saddr.sin_family = AF_INET;
-	if (inet_aton(host, &saddr.sin_addr)) {
-		const char *thost = (const char *) &saddr.sin_addr;
-
-		prx = get_proximity(thost, sizeof(saddr.sin_addr));
-		if (prx == PROXIMITY_ERROR)
-			return 0;
-
-		if (!(new = new_host(host, thost, sizeof(saddr.sin_addr), prx, weight)))
-			return 0;
-
-		if (!add_host(list, new))
-			free_host(new);
-
-		return 1;
-	}
+	prx = get_proximity(host_addr->ai_addr);
+	if (prx == PROXIMITY_ERROR)
+		return 0;
 
-	memset(buf, 0, MAX_IFC_BUF);
-	memset(&he, 0, sizeof(struct hostent));
+	addr_len = sizeof(struct sockaddr);
+	new = new_host(host, host_addr->ai_addr, addr_len, prx, weight);
+	if (!new)
+		return 0;
 
-	ret = gethostbyname_r(host, phe,
-			buf, MAX_IFC_BUF, &result, &ghn_errno);
-	if (ret || !result) {
-		if (ghn_errno == -1)
-			logmsg("host %s: lookup failure %d", host, errno);
-		else
-			logmsg("host %s: lookup failure %d", host, ghn_errno);
+	if (!add_host(list, new)) {
+		free_host(new);
 		return 0;
 	}
 
-	for (haddr = phe->h_addr_list; *haddr; haddr++) {
-		struct in_addr tt;
+	return 1;
+}
 
-		prx = get_proximity(*haddr, phe->h_length);
-		if (prx == PROXIMITY_ERROR)
-			return 0;
+static int add_host_addrs(struct host **list, const char *host, unsigned int weight)
+{
+	struct addrinfo hints, *ni, *this;
+	int ret;
 
-		memcpy(&tt, *haddr, sizeof(struct in_addr));
-		if (!(new = new_host(host, *haddr, phe->h_length, prx, weight)))
-			return 0;
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_flags = AI_NUMERICHOST;
+	hints.ai_family = AF_UNSPEC;
+	hints.ai_socktype = SOCK_DGRAM;
+
+	ret = getaddrinfo(host, NULL, &hints, &ni);
+	if (ret)
+		goto try_name;
 
-		if (!add_host(list, new)) {
-			free_host(new);
-			continue;
-		}
+	this = ni;
+	while (this) {
+		ret = add_new_host(list, host, weight, this);
+		if (!ret)
+			break;
+		this = this->ai_next;
 	}
+	freeaddrinfo(ni);
+	goto done;
 
-	return 1;
+try_name:
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_flags = AI_ADDRCONFIG;
+	hints.ai_family = AF_UNSPEC;
+	hints.ai_socktype = SOCK_DGRAM;
+
+	ret = getaddrinfo(host, NULL, &hints, &ni);
+	if (ret) {
+		error(LOGOPT_ANY, "hostname lookup failed: %s",
+		      gai_strerror(ret));
+		return 0;
+	}
+
+	this = ni;
+	while (this) {
+		ret = add_new_host(list, host, weight, this);
+		if (!ret)
+			break;
+		this = this->ai_next;
+	}
+	freeaddrinfo(ni);
+done:
+	return ret;
 }
 
 static int add_path(struct host *hosts, const char *path, int len)
@@ -1057,7 +1159,8 @@ static int add_local_path(struct host **
 	new->path = tmp;
 	new->proximity = PROXIMITY_LOCAL;
 	new->version = NFS_VERS_MASK;
-	new->name = new->addr = NULL;
+	new->name = NULL;
+	new->addr = NULL;
 	new->weight = new->cost = 0;
 
 	add_host(hosts, new);
--- autofs-5.0.4.orig/CHANGELOG
+++ autofs-5.0.4/CHANGELOG
@@ -18,6 +18,7 @@
 - make MAX_ERR_BUF and PARSE_MAX_BUF use easier to audit.
 - make some easy alloca replacements (Valerie Aurora Henson).
 - update to configure libtirpc if present.
+- update to provide ipv6 name and address support.
 
 4/11/2008 autofs-5.0.4
 -----------------------

autofs-5.0.4-ipv6-parse.patch:

--- NEW FILE autofs-5.0.4-ipv6-parse.patch ---
autofs-5.0.4 - ipv6 parse

From: Ian Kent <raven at themaw.net>

Since ipv6 addresses use a colon separator and we use the colon quite a
bit as a delimiting character we need to distinguish between when the
colon is the delimeter we are looking for and when it is part of an ipv6
address. Since there is widespread use of "[" and "]" to provide the
ability to separate a port specification from an ipv6 address this
convention has also been used in autofs.
---

 CHANGELOG              |    1 
 include/parse_subs.h   |    8 +++
 lib/master_tok.l       |   10 ++--
 lib/parse_subs.c       |   99 ++++++++++++++++++++++++++++++++++++++++++++++---
 modules/lookup_file.c  |   40 +++++++------------
 modules/lookup_ldap.c  |   21 ++++++++--
 modules/mount_autofs.c |   29 +++++---------
 modules/parse_sun.c    |   16 ++++---
 modules/replicated.c   |   26 +++++++++++-
 9 files changed, 187 insertions(+), 63 deletions(-)


--- autofs-5.0.4.orig/include/parse_subs.h
+++ autofs-5.0.4/include/parse_subs.h
@@ -20,6 +20,12 @@
 
 struct mapent;
 
+struct map_type_info {
+	char *type;
+	char *format;
+	char *map;
+};
+
 const char *skipspace(const char *);
 int check_colon(const char *);
 int chunklen(const char *, int);
@@ -27,5 +33,7 @@ int strmcmp(const char *, const char *, 
 char *dequote(const char *, int, unsigned int);
 int span_space(const char *, unsigned int);
 char *sanitize_path(const char *, int, unsigned int, unsigned int);
+void free_map_type_info(struct map_type_info *);
+struct map_type_info *parse_map_type_info(const char *);
 
 #endif
--- autofs-5.0.4.orig/lib/master_tok.l
+++ autofs-5.0.4/lib/master_tok.l
@@ -96,10 +96,12 @@ SLASHIFYSTR	(--(no-)?slashify-colons)
 NUMBER		[0-9]+
 
 DNSERVSTR1	([[:alpha:]][[:alnum:]\-.]*(:[0-9]+)?:)
-DNSERVSTR2	(\/\/[[:alpha:]][[:alnum:]\-.]*(:[0-9]+)?\/)
-DNSERVSTR3	(([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?:)
-DNSERVSTR4	(\/\/([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?\/)
-DNSERVERSTR	({DNSERVSTR1}|{DNSERVSTR2}|{DNSERVSTR3}|{DNSERVSTR4})
+DNSERVSTR2	(\[([[:xdigit:]]:.)+\](:[0-9]+)?:)
+DNSERVSTR3	(\/\/[[:alpha:]][[:alnum:]\-.]*(:[0-9]+)?\/)
+DNSERVSTR4	(\/\/\[([[:xdigit:]]:.)+\](:[0-9]+)?\/)
+DNSERVSTR5	(([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?:)
+DNSERVSTR6	(\/\/([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?\/)
+DNSERVERSTR	({DNSERVSTR1}|{DNSERVSTR2}|{DNSERVSTR3}|{DNSERVSTR4}|{DNSERVSTR5}|{DNSERVSTR6})
 
 AT_CN		([cC][[nN])
 AT_NMN		([nN][iI][sS][Mm][aA][pP][Nn][aA][mM][eE])
--- autofs-5.0.4.orig/lib/parse_subs.c
+++ autofs-5.0.4/lib/parse_subs.c
@@ -56,14 +56,13 @@ int check_colon(const char *str)
 	char *ptr = (char *) str;
 
 	/* Colon escape */
-	if (*ptr == ':')
+	if (!strncmp(ptr, ":/", 2))
 		return 1;
 
-	while (*ptr && *ptr != ':' && *ptr != '/') {
+	while (*ptr && strncmp(ptr, ":/", 2))
 		ptr++;
-	}
 
-	if (!*ptr || *ptr == '/')
+	if (!*ptr)
 		return 0;
 
 	return 1;
@@ -93,12 +92,12 @@ int chunklen(const char *whence, int exp
 				n++;
 				if (*str == '"')
 					break;
-				if (*str == ':')
+				if (!strncmp(str, ":/", 2))
 					expect_colon = 0;
 			}
 			break;
 		case ':':
-			if (expect_colon)
+			if (expect_colon && !strncmp(str, ":/", 2))
 				expect_colon = 0;
 			continue;
 		case ' ':
@@ -300,3 +299,91 @@ char *sanitize_path(const char *path, in
 	return s_path;
 }
 
+void free_map_type_info(struct map_type_info *info)
+{
+	if (info->type)
+		free(info->type);
+	if (info->format)
+		free(info->format);
+	if (info->map)
+		free(info->map);
+	free(info);
+	return;
+}
+
+struct map_type_info *parse_map_type_info(const char *str)
+{
+	struct map_type_info *info;
+	char *buf, *type, *fmt, *map, *tmp;
+
+	buf = strdup(str);
+	if (!buf)
+		return NULL;
+
+	info = malloc(sizeof(struct map_type_info));
+	if (!info) {
+		free(buf);
+		return NULL;
+	}
+	memset(info, 0, sizeof(struct map_type_info));
+
+	type = fmt = NULL;
+
+	/* Look for space terminator - ignore local options */
+	map = buf;
+	for (tmp = buf; *tmp; tmp++) {
+		if (*tmp == ' ') {
+			*tmp = '\0';
+			break;
+		} else if (*tmp == ',') {
+			type = buf;
+			*tmp++ = '\0';
+			fmt = tmp;
+		} else if (*tmp == ':') {
+			if (!fmt)
+				type = buf;
+			*tmp++ = '\0';
+			map = tmp;
+		} else if (*tmp == '[') {
+			/*
+			 * Unescaped '[' is a syntax error here as only
+			 * an ldap map with a type specified should contain
+			 * them. 
+			 */
+			free(buf);
+			return 0;
+		}
+		if (*tmp == '\\')
+			tmp++;
+	}
+
+	if (type) {
+		info->type = strdup(type);
+		if (!info->type) {
+			free(buf);
+			free_map_type_info(info);
+			return NULL;
+		}
+	}
+
+	if (fmt) {
+		info->format = strdup(fmt);
+		if (!info->format) {
+			free(buf);
+			free_map_type_info(info);
+			return NULL;
+		}
+	}
+
+	info->map = strdup(map);
+	if (!info->map) {
+		free(buf);
+		free_map_type_info(info);
+		return NULL;
+	}
+
+	free(buf);
+
+	return info;
+}
+
--- autofs-5.0.4.orig/modules/lookup_file.c
+++ autofs-5.0.4/modules/lookup_file.c
@@ -523,10 +523,10 @@ prepare_plus_include(struct autofs_point
 {
 	struct map_source *current;
 	struct map_source *source;
-	char *type, *map, *fmt;
+	struct map_type_info *info;
 	const char *argv[2];
 	int argc;
-	char *buf, *tmp;
+	char *buf;
 
 	current = ap->entry->current;
 	ap->entry->current = NULL;
@@ -548,33 +548,19 @@ prepare_plus_include(struct autofs_point
 		return NULL;
 	}
 
-	type = fmt = NULL;
-
-	/* Look for space terminator - ignore local options */
-	map = buf;
-	for (tmp = buf; *tmp; tmp++) {
-		if (*tmp == ' ') {
-			*tmp = '\0';
-			break;
-		} else if (*tmp == ',') {
-			type = buf;
-			*tmp++ = '\0';
-			fmt = tmp;
-		} else if (*tmp == ':') {
-			if (!fmt)
-				type = buf;
-			*tmp++ = '\0';
-			map = tmp;
-		}
-		if (*tmp == '\\')
-			tmp++;
+	if (!(info = parse_map_type_info(buf))) {
+		error(ap->logopt, MODPREFIX "failed to parse map info");
+		free(buf);
+		return NULL;
 	}
 
 	argc = 1;
-	argv[0] = map;
+	argv[0] = info->map;
 	argv[1] = NULL;
 
-	source = master_find_source_instance(current, type, fmt, argc, argv);
+	source = master_find_source_instance(current,
+					     info->type, info->format,
+					     argc, argv);
 	if (source)
 		/*
 		 * Make sure included map age is in sync with its owner
@@ -582,8 +568,11 @@ prepare_plus_include(struct autofs_point
 		 */
 		source->age = age;
 	else {
-		source = master_add_source_instance(current, type, fmt, age, argc, argv);
+		source = master_add_source_instance(current,
+						    info->type, info->format,
+						    age, argc, argv);
 		if (!source) {
+			free_map_type_info(info);
 			free(buf);
 			error(ap->logopt, "failed to add included map instance");
 			return NULL;
@@ -594,6 +583,7 @@ prepare_plus_include(struct autofs_point
 	if (inc)
 		source->recurse = 1;
 
+	free_map_type_info(info);
 	free(buf);
 
 	return source;
--- autofs-5.0.4.orig/modules/lookup_ldap.c
+++ autofs-5.0.4/modules/lookup_ldap.c
@@ -1119,11 +1119,26 @@ static int parse_server_string(unsigned 
 			memcpy(ctxt->server, s, l);
 */
 		}
-	} else if (strchr(ptr, ':') != NULL) {
-		char *q = NULL;
+	} else if (strchr(ptr, ':') != NULL || *ptr == '[') {
+		const char *q = NULL;
 
 		/* Isolate the server. Include the port spec */
-		q = strchr(ptr, ':');
+		if (*ptr != '[')
+			q = strchr(ptr, ':');
+		else {
+			q = ++ptr;
+			while (*q == ':' || isxdigit(*q))
+				q++;
+			if (*q != ']') {
+				crit(logopt, MODPREFIX
+				     "invalid LDAP map syntax %s", ptr);
+				return 0;
+			}
+			q++;
+			if (*q == ':')
+				q++;
+		}
+
 		if (isdigit(*q))
 			while (isdigit(*q))
 				q++;
--- autofs-5.0.4.orig/modules/mount_autofs.c
+++ autofs-5.0.4/modules/mount_autofs.c
@@ -50,7 +50,7 @@ int mount_mount(struct autofs_point *ap,
 	int argc, status, ghost = ap->flags & MOUNT_FLAG_GHOST;
 	time_t timeout = ap->exp_timeout;
 	unsigned logopt = ap->logopt;
-	char *type, *format, *tmp, *tmp2;
+	struct map_type_info *info;
 	struct master *master;
 	struct master_mapent *entry;
 	struct map_source *source;
@@ -174,21 +174,12 @@ int mount_mount(struct autofs_point *ap,
 
 	argc = 1;
 
-	type = NULL;
-	format = NULL;
-
-	tmp = strchr(what, ':');
-	if (tmp) {
-		*tmp++ = '\0';
-		tmp2 = strchr(what, ',');
-		if (tmp2) {
-			*tmp2++ = '\0';
-			format = tmp2;
-		}
-		type = (char *) what;
-		argv[0] = tmp;
-	} else
-		argv[0] = (char *) what;
+	if (!(info = parse_map_type_info(what))) {
+		error(ap->logopt, MODPREFIX "failed to parse map info");
+		master_free_mapent(entry);
+		return 1;
+	}
+	argv[0] = info->map;
 
 	if (options) {
 		p = options;
@@ -202,13 +193,17 @@ int mount_mount(struct autofs_point *ap,
 	}
 	argv[argc] = NULL;
 
-	source = master_add_map_source(entry, type, format, time(NULL), argc, argv);
+	source = master_add_map_source(entry,
+				       info->type, info->format,
+				       time(NULL), argc, argv);
 	if (!source) {
 		error(ap->logopt,
 		      MODPREFIX "failed to add map source to entry");
 		master_free_mapent(entry);
+		free_map_type_info(info);
 		return 1;
 	}
+	free_map_type_info(info);
 
 	source->mc = cache_init(entry->ap, source);
 	if (!source->mc) {
--- autofs-5.0.4.orig/modules/parse_sun.c
+++ autofs-5.0.4/modules/parse_sun.c
@@ -245,7 +245,9 @@ int expandsunent(const char *src, char *
 				*(dst++) = 
 				  (seen_colons && slashify_colons) ? '/' : ':';
 			len++;
-			seen_colons = 1;
+			/* Were looking for the colon preceeding a path */
+			if (*src == '/')
+				seen_colons = 1;
 			break;
 
 		default:
@@ -814,21 +816,23 @@ static int validate_location(char *loc)
 		return 1;
 
 	/*
-	 * If a ':' is present now it must be a host name, except
+	 * If a ':/' is present now it must be a host name, except
 	 * for those special file systems like sshfs which use "#"
-	 * and "@" in the host name part.
+	 * and "@" in the host name part and ipv6 addresses that
+	 * have ":", "[" and "]".
 	 */
 	if (check_colon(ptr)) {
-		while (*ptr && *ptr != ':') {
+		while (*ptr && strncmp(ptr, ":/", 2)) {
 			if (!(isalnum(*ptr) ||
 			    *ptr == '-' || *ptr == '.' || *ptr == '_' ||
 			    *ptr == ',' || *ptr == '(' || *ptr == ')' ||
-			    *ptr == '#' || *ptr == '@'))
+			    *ptr == '#' || *ptr == '@' || *ptr == ':' ||
+			    *ptr == '[' || *ptr == ']'))
 				return 0;
 			ptr++;
 		}
 
-		if (*ptr && *ptr == ':')
+		if (*ptr && !strncmp(ptr, ":/", 2))
 			ptr++;
 	}
 
--- autofs-5.0.4.orig/modules/replicated.c
+++ autofs-5.0.4/modules/replicated.c
@@ -1168,6 +1168,28 @@ static int add_local_path(struct host **
 	return 1;
 }
 
+static char *seek_delim(const char *s)
+{
+	const char *p = s;
+	char *delim;
+
+	delim = strpbrk(p, "(, \t:");
+	if (delim && *delim != ':')
+		return delim;
+
+	while (*p) {
+		if (*p != ':') {
+			p++;
+			continue;
+		}
+		if (!strncmp(p, ":/", 2))
+			return (char *) p;
+		p++;
+	}
+
+	return NULL;
+}
+
 int parse_location(unsigned logopt, struct host **hosts, const char *list)
 {
 	char *str, *p, *delim;
@@ -1187,7 +1209,7 @@ int parse_location(unsigned logopt, stru
 		int weight = 0;
 
 		p += strspn(p, " \t,");
-		delim = strpbrk(p, "(, \t:");
+		delim = seek_delim(p);
 
 		if (delim) {
 			if (*delim == '(') {
@@ -1211,7 +1233,7 @@ int parse_location(unsigned logopt, stru
 
 				/* Oh boy - might have spaces in the path */
 				next = path;
-				while (*next && *next != ':')
+				while (*next && strncmp(next, ":/", 2))
 					next++;
 
 				/* No spaces in host names at least */
--- autofs-5.0.4.orig/CHANGELOG
+++ autofs-5.0.4/CHANGELOG
@@ -19,6 +19,7 @@
 - make some easy alloca replacements (Valerie Aurora Henson).
 - update to configure libtirpc if present.
 - update to provide ipv6 name and address support.
+- update to provide ipv6 address parsing.
 
 4/11/2008 autofs-5.0.4
 -----------------------

autofs-5.0.4-library-reload-fix-update.patch:

--- NEW FILE autofs-5.0.4-library-reload-fix-update.patch ---
autofs-5.0.4 - library reload fix update

From: Ian Kent <raven at themaw.net>

We still have a problem with libxml2 being unloaded before its thread
specific data destructor is called. This is due to the main thread
exiting (closing the handle we hold open to prevent this) before all
the mount handling threads have actually completed. This patch makes
the mount handling threads joinable (and joins with them as they exit)
to ensure that the mount handling threads have completed before allowing
the main thread to complete.
---

 daemon/automount.c     |   35 +++++++++++++++++++++++------------
 daemon/direct.c        |    7 ++++---
 daemon/indirect.c      |    7 ++++---
 daemon/state.c         |    7 ++++---
 include/master.h       |    3 +++
 lib/master.c           |   38 ++++++++++++++++++++++++++++++++++----
 modules/mount_autofs.c |    4 ++--
 7 files changed, 74 insertions(+), 27 deletions(-)


diff --git a/daemon/automount.c b/daemon/automount.c
index e120f50..f04273f 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -69,8 +69,9 @@ static size_t kpkt_len;
 /* Does kernel know about SOCK_CLOEXEC and friends */
 static int cloexec_works = 0;
 
-/* Attribute to create detached thread */
-pthread_attr_t thread_attr;
+/* Attributes for creating detached and joinable threads */
+pthread_attr_t th_attr;
+pthread_attr_t th_attr_detached;
 
 struct master_readmap_cond mrc = {
 	PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, NULL, 0, 0, 0, 0};
@@ -1192,7 +1193,7 @@ static pthread_t do_signals(struct master *master, int sig)
 	if (status)
 		fatal(status);
 
-	status = pthread_create(&thid, &thread_attr, do_notify_state, &r_sig);
+	status = pthread_create(&thid, &th_attr_detached, do_notify_state, &r_sig);
 	if (status) {
 		error(master->logopt,
 		      "mount state notify thread create failed");
@@ -1281,7 +1282,7 @@ static int do_hup_signal(struct master *master, time_t age)
 
 	master->reading = 1;
 
-	status = pthread_create(&thid, &thread_attr, do_read_master, NULL);
+	status = pthread_create(&thid, &th_attr_detached, do_read_master, NULL);
 	if (status) {
 		error(logopt,
 		      "master read map thread create failed");
@@ -1327,7 +1328,7 @@ static void *statemachine(void *arg)
 		case SIGTERM:
 		case SIGINT:
 		case SIGUSR2:
-			if (master_list_empty(master_list))
+			if (master_done(master_list))
 				return NULL;
 		case SIGUSR1:
 			do_signals(master_list, sig);
@@ -1448,8 +1449,6 @@ static void handle_mounts_cleanup(void *arg)
 	master_mutex_unlock();
 
 	destroy_logpri_fifo(ap);
-	master_free_mapent_sources(ap->entry, 1);
-	master_free_mapent(ap->entry);
 
 	if (clean) {
 		if (rmdir(path) == -1) {
@@ -1461,8 +1460,12 @@ static void handle_mounts_cleanup(void *arg)
 
 	info(logopt, "shut down path %s", path);
 
-	/* If we are the last tell the state machine to shutdown */
-	if (!submount && master_list_empty(master_list))
+	/*
+	 * If we are not a submount send a signal to the signal handler
+	 * so it can join with any completed handle_mounts() threads and
+	 * perform final cleanup.
+	 */
+	if (!submount)
 		pthread_kill(state_mach_thid, SIGTERM);
 	
 	return;
@@ -1980,7 +1983,15 @@ int main(int argc, char *argv[])
 		exit(1);
 	}
 
-	if (pthread_attr_init(&thread_attr)) {
+	if (pthread_attr_init(&th_attr)) {
+		logerr("%s: failed to init thread attribute struct!",
+		     program);
+		close(start_pipefd[1]);
+		release_flag_file();
+		exit(1);
+	}
+
+	if (pthread_attr_init(&th_attr_detached)) {
 		logerr("%s: failed to init thread attribute struct!",
 		     program);
 		close(start_pipefd[1]);
@@ -1989,7 +2000,7 @@ int main(int argc, char *argv[])
 	}
 
 	if (pthread_attr_setdetachstate(
-			&thread_attr, PTHREAD_CREATE_DETACHED)) {
+			&th_attr_detached, PTHREAD_CREATE_DETACHED)) {
 		logerr("%s: failed to set detached thread attribute!",
 		     program);
 		close(start_pipefd[1]);
@@ -1999,7 +2010,7 @@ int main(int argc, char *argv[])
 
 #ifdef _POSIX_THREAD_ATTR_STACKSIZE
 	if (pthread_attr_setstacksize(
-			&thread_attr, PTHREAD_STACK_MIN*64)) {
+			&th_attr_detached, PTHREAD_STACK_MIN*64)) {
 		logerr("%s: failed to set stack size thread attribute!",
 		       program);
 		close(start_pipefd[1]);
diff --git a/daemon/direct.c b/daemon/direct.c
index c0243c4..d9dda3d 100644
--- a/daemon/direct.c
+++ b/daemon/direct.c
@@ -37,7 +37,8 @@
 
 #include "automount.h"
 
-extern pthread_attr_t thread_attr;
+/* Attribute to create detached thread */
+extern pthread_attr_t th_attr_detached;
 
 struct mnt_params {
 	char *options;
@@ -1142,7 +1143,7 @@ int handle_packet_expire_direct(struct autofs_point *ap, autofs_packet_expire_di
 	debug(ap->logopt, "token %ld, name %s",
 		  (unsigned long) pkt->wait_queue_token, mt->name);
 
-	status = pthread_create(&thid, &thread_attr, do_expire_direct, mt);
+	status = pthread_create(&thid, &th_attr_detached, do_expire_direct, mt);
 	if (status) {
 		error(ap->logopt, "expire thread create failed");
 		ops->send_fail(ap->logopt,
@@ -1451,7 +1452,7 @@ int handle_packet_missing_direct(struct autofs_point *ap, autofs_packet_missing_
 	mt->gid = pkt->gid;
 	mt->wait_queue_token = pkt->wait_queue_token;
 
-	status = pthread_create(&thid, &thread_attr, do_mount_direct, mt);
+	status = pthread_create(&thid, &th_attr_detached, do_mount_direct, mt);
 	if (status) {
 		error(ap->logopt, "missing mount thread create failed");
 		ops->send_fail(ap->logopt,
diff --git a/daemon/indirect.c b/daemon/indirect.c
index 9d3745c..0721707 100644
--- a/daemon/indirect.c
+++ b/daemon/indirect.c
@@ -36,7 +36,8 @@
 
 #include "automount.h"
 
-extern pthread_attr_t thread_attr;
+/* Attribute to create detached thread */
+extern pthread_attr_t th_attr_detached;
 
 static pthread_mutex_t ea_mutex = PTHREAD_MUTEX_INITIALIZER;
 
@@ -647,7 +648,7 @@ int handle_packet_expire_indirect(struct autofs_point *ap, autofs_packet_expire_
 	mt->len = pkt->len;
 	mt->wait_queue_token = pkt->wait_queue_token;
 
-	status = pthread_create(&thid, &thread_attr, do_expire_indirect, mt);
+	status = pthread_create(&thid, &th_attr_detached, do_expire_indirect, mt);
 	if (status) {
 		error(ap->logopt, "expire thread create failed");
 		ops->send_fail(ap->logopt,
@@ -835,7 +836,7 @@ int handle_packet_missing_indirect(struct autofs_point *ap, autofs_packet_missin
 	mt->gid = pkt->gid;
 	mt->wait_queue_token = pkt->wait_queue_token;
 
-	status = pthread_create(&thid, &thread_attr, do_mount_indirect, mt);
+	status = pthread_create(&thid, &th_attr_detached, do_mount_indirect, mt);
 	if (status) {
 		error(ap->logopt, "expire thread create failed");
 		ops->send_fail(ap->logopt,
diff --git a/daemon/state.c b/daemon/state.c
index 87c16a6..cd63be1 100644
--- a/daemon/state.c
+++ b/daemon/state.c
@@ -16,7 +16,8 @@
 
 #include "automount.h"
 
-extern pthread_attr_t thread_attr;
+/* Attribute to create detached thread */
+extern pthread_attr_t th_attr_detached;
 
 struct state_queue {
 	pthread_t thid;
@@ -292,7 +293,7 @@ static enum expire expire_proc(struct autofs_point *ap, int now)
 	else
 		expire = expire_proc_direct;
 
-	status = pthread_create(&thid, &thread_attr, expire, ea);
+	status = pthread_create(&thid, &th_attr_detached, expire, ea);
 	if (status) {
 		error(ap->logopt,
 		      "expire thread create for %s failed", ap->path);
@@ -519,7 +520,7 @@ static unsigned int st_readmap(struct autofs_point *ap)
 	ra->ap = ap;
 	ra->now = now;
 
-	status = pthread_create(&thid, &thread_attr, do_readmap, ra);
+	status = pthread_create(&thid, &th_attr_detached, do_readmap, ra);
 	if (status) {
 		error(ap->logopt, "read map thread create failed");
 		st_readmap_cleanup(ra);
diff --git a/include/master.h b/include/master.h
index 6d801a9..c519e97 100644
--- a/include/master.h
+++ b/include/master.h
@@ -48,6 +48,7 @@ struct master_mapent {
 	struct map_source *maps;
 	struct autofs_point *ap;
 	struct list_head list;
+	struct list_head join;
 };
 
 struct master {
@@ -61,6 +62,7 @@ struct master {
 	unsigned int logopt;
 	struct mapent_cache *nc;
 	struct list_head mounts;
+	struct list_head completed;
 };
 
 /* From the yacc master map parser */
@@ -109,6 +111,7 @@ void master_notify_state_change(struct master *, int);
 int master_mount_mounts(struct master *, time_t, int);
 extern inline unsigned int master_get_logopt(void);
 int master_list_empty(struct master *);
+int master_done(struct master *);
 int master_kill(struct master *);
 
 #endif
diff --git a/lib/master.c b/lib/master.c
index e1cc062..762094f 100644
--- a/lib/master.c
+++ b/lib/master.c
@@ -32,8 +32,8 @@ struct master *master_list = NULL;
 
 extern long global_negative_timeout;
 
-/* Attribute to create detached thread */
-extern pthread_attr_t thread_attr;
+/* Attribute to create a joinable thread */
+extern pthread_attr_t th_attr;
 
 extern struct startup_cond suc;
 
@@ -704,11 +704,16 @@ void master_add_mapent(struct master *master, struct master_mapent *entry)
 
 void master_remove_mapent(struct master_mapent *entry)
 {
+	struct master *master = entry->master;
+
 	if (entry->ap->submount)
 		return;
 
-	if (!list_empty(&entry->list))
+	if (!list_empty(&entry->list)) {
 		list_del_init(&entry->list);
+		list_add(&entry->join, &master->completed);
+	}
+
 	return;
 }
 
@@ -786,6 +791,7 @@ struct master *master_new(const char *name, unsigned int timeout, unsigned int g
 	master->logopt = master->default_logging;
 
 	INIT_LIST_HEAD(&master->mounts);
+	INIT_LIST_HEAD(&master->completed);
 
 	return master;
 }
@@ -993,7 +999,7 @@ static int master_do_mount(struct master_mapent *entry)
 
 	debug(ap->logopt, "mounting %s", entry->path);
 
-	status = pthread_create(&thid, &thread_attr, handle_mounts, &suc);
+	status = pthread_create(&thid, &th_attr, handle_mounts, &suc);
 	if (status) {
 		crit(ap->logopt,
 		     "failed to create mount handler thread for %s",
@@ -1170,6 +1176,30 @@ int master_list_empty(struct master *master)
 	return res;
 }
 
+int master_done(struct master *master)
+{
+	struct list_head *head, *p;
+	struct master_mapent *entry;
+	int res = 0;
+
+	master_mutex_lock();
+	head = &master->completed;
+	p = head->next;
+	while (p != head) {
+		entry = list_entry(p, struct master_mapent, join);
+		p = p->next;
+		list_del(&entry->join);
+		pthread_join(entry->thid, NULL);
+		master_free_mapent_sources(entry, 1);
+		master_free_mapent(entry);
+	}
+	if (list_empty(&master->mounts))
+		res = 1;
+	master_mutex_unlock();
+
+	return res;
+}
+
 inline unsigned int master_get_logopt(void)
 {
 	return master_list ? master_list->logopt : LOGOPT_NONE;
diff --git a/modules/mount_autofs.c b/modules/mount_autofs.c
index 82a5ef3..44fc043 100644
--- a/modules/mount_autofs.c
+++ b/modules/mount_autofs.c
@@ -30,7 +30,7 @@
 #define MODPREFIX "mount(autofs): "
 
 /* Attribute to create detached thread */
-extern pthread_attr_t thread_attr;
+extern pthread_attr_t th_attr_detached;
 extern struct startup_cond suc;
 
 int mount_version = AUTOFS_MOUNT_VERSION;	/* Required by protocol */
@@ -235,7 +235,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name,
 	suc.done = 0;
 	suc.status = 0;
 
-	if (pthread_create(&thid, &thread_attr, handle_mounts, &suc)) {
+	if (pthread_create(&thid, &th_attr_detached, handle_mounts, &suc)) {
 		crit(ap->logopt,
 		     MODPREFIX
 		     "failed to create mount handler thread for %s",

autofs-5.0.4-make-MAX_ERR_BUF-and-PARSE_MAX_BUF-use-easier-to-audit.patch:

--- NEW FILE autofs-5.0.4-make-MAX_ERR_BUF-and-PARSE_MAX_BUF-use-easier-to-audit.patch ---
autofs-5.0.4 - make MAX_ERR_BUF and PARSE_MAX_BUF use easier to audit

From: Valerie Aurora Henson <vaurora at redhat.com>

Non-critical changes to make auditing buffer lengths easier.

* Some buffers were the wrong (too big) size, some were used twice for
  different purposes.
* Use sizeof(buf) instead of repeating the *MAX* define in functions
  that need to know the size of a statically allocated buffer.
* Fix a compiler warning about discarding the const on a string.
---

 CHANGELOG             |    1 +
 modules/lookup_ldap.c |   51 ++++++++++++++++++++++---------------------------
 2 files changed, 24 insertions(+), 28 deletions(-)


diff --git a/CHANGELOG b/CHANGELOG
index afd1335..417a001 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -15,6 +15,7 @@
 - add "forcestart" and "forcerestart" init script options to allow
   use of 5.0.3 strartup behavior if required.
 - always read entire file map into cache to speed lookups.
+- make MAX_ERR_BUF and PARSE_MAX_BUF use easier to audit.
 
 4/11/2008 autofs-5.0.4
 -----------------------
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index bee97ae..d8a60d3 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -272,7 +272,7 @@ LDAP *init_ldap_connection(unsigned logopt, const char *uri, struct lookup_conte
 
 static int get_query_dn(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt, const char *class, const char *key)
 {
-	char buf[PARSE_MAX_BUF];
+	char buf[MAX_ERR_BUF];
 	char *query, *dn, *qdn;
 	LDAPMessage *result, *e;
 	struct ldap_searchdn *sdns = NULL;
@@ -296,7 +296,7 @@ static int get_query_dn(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt
 
 	query = alloca(l);
 	if (query == NULL) {
-		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+		char *estr = strerror_r(errno, buf, sizeof(buf));
 		crit(logopt, MODPREFIX "alloca: %s", estr);
 		return NSS_STATUS_UNAVAIL;
 	}
@@ -1082,7 +1082,7 @@ static int parse_server_string(unsigned logopt, const char *url, struct lookup_c
 			}
 			if (!tmp) {
 				char *estr;
-				estr = strerror_r(errno, buf, MAX_ERR_BUF);
+				estr = strerror_r(errno, buf, sizeof(buf));
 				logerr(MODPREFIX "malloc: %s", estr);
 				return 0;
 			}
@@ -1104,7 +1104,7 @@ static int parse_server_string(unsigned logopt, const char *url, struct lookup_c
 			tmp = malloc(l + 1);
 			if (!tmp) {
 				char *estr;
-				estr = strerror_r(errno, buf, MAX_ERR_BUF);
+				estr = strerror_r(errno, buf, sizeof(buf));
 				crit(logopt, MODPREFIX "malloc: %s", estr);
 				return 0;
 			}
@@ -1139,7 +1139,7 @@ static int parse_server_string(unsigned logopt, const char *url, struct lookup_c
 		/* Isolate the server's name. */
 		if (!tmp) {
 			char *estr;
-			estr = strerror_r(errno, buf, MAX_ERR_BUF);
+			estr = strerror_r(errno, buf, sizeof(buf));
 			logerr(MODPREFIX "malloc: %s", estr);
 			return 0;
 		}
@@ -1180,7 +1180,7 @@ static int parse_server_string(unsigned logopt, const char *url, struct lookup_c
 				ctxt->mapname = map;
 			else {
 				char *estr;
-				estr = strerror_r(errno, buf, MAX_ERR_BUF);
+				estr = strerror_r(errno, buf, sizeof(buf));
 				logerr(MODPREFIX "malloc: %s", estr);
 				if (ctxt->server)
 					free(ctxt->server);
@@ -1191,7 +1191,7 @@ static int parse_server_string(unsigned logopt, const char *url, struct lookup_c
 			base = malloc(l + 1);
 			if (!base) {
 				char *estr;
-				estr = strerror_r(errno, buf, MAX_ERR_BUF);
+				estr = strerror_r(errno, buf, sizeof(buf));
 				logerr(MODPREFIX "malloc: %s", estr);
 				if (ctxt->server)
 					free(ctxt->server);
@@ -1205,7 +1205,7 @@ static int parse_server_string(unsigned logopt, const char *url, struct lookup_c
 		char *map = malloc(l + 1);
 		if (!map) {
 			char *estr;
-			estr = strerror_r(errno, buf, MAX_ERR_BUF);
+			estr = strerror_r(errno, buf, sizeof(buf));
 			logerr(MODPREFIX "malloc: %s", estr);
 			if (ctxt->server)
 				free(ctxt->server);
@@ -1318,7 +1318,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 	/* If we can't build a context, bail. */
 	ctxt = malloc(sizeof(struct lookup_context));
 	if (!ctxt) {
-		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+		char *estr = strerror_r(errno, buf, sizeof(buf));
 		logerr(MODPREFIX "malloc: %s", estr);
 		return 1;
 	}
@@ -1419,8 +1419,9 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 	unsigned int timeout = master->default_timeout;
 	unsigned int logging = master->default_logging;
 	unsigned int logopt = master->logopt;
-	int rv, l, count, blen;
-	char buf[PARSE_MAX_BUF];
+	int rv, l, count;
+	char buf[MAX_ERR_BUF];
+	char parse_buf[PARSE_MAX_BUF];
 	char *query;
 	LDAPMessage *result, *e;
 	char *class, *info, *entry;
@@ -1442,7 +1443,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 
 	query = alloca(l);
 	if (query == NULL) {
-		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+		char *estr = strerror_r(errno, buf, sizeof(buf));
 		logerr(MODPREFIX "alloca: %s", estr);
 		return NSS_STATUS_UNAVAIL;
 	}
@@ -1532,19 +1533,13 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 			goto next;
 		}
 
-		blen = strlen(*keyValue) + 1 + strlen(*values) + 2;
-		if (blen > PARSE_MAX_BUF) {
+		if (snprintf(parse_buf, sizeof(parse_buf), "%s %s",
+			     *keyValue, *values) >= sizeof(parse_buf)) {
 			error(logopt, MODPREFIX "map entry too long");
 			ldap_value_free(values);
 			goto next;
 		}
-		memset(buf, 0, PARSE_MAX_BUF);
-
-		strcpy(buf, *keyValue);
-		strcat(buf, " ");
-		strcat(buf, *values);
-
-		master_parse_entry(buf, timeout, logging, age);
+		master_parse_entry(parse_buf, timeout, logging, age);
 next:
 		ldap_value_free(keyValue);
 		e = ldap_next_entry(ldap, e);
@@ -1561,7 +1556,7 @@ static int get_percent_decoded_len(const char *name)
 {
 	int escapes = 0;
 	int escaped = 0;
-	char *tmp = name;
+	const char *tmp = name;
 	int look_for_close = 0;
 
 	while (*tmp) {
@@ -2060,7 +2055,7 @@ static int do_get_entries(struct ldap_search_params *sp, struct map_source *sour
 				mapent = malloc(v_len + 1);
 				if (!mapent) {
 					char *estr;
-					estr = strerror_r(errno, buf, MAX_ERR_BUF);
+					estr = strerror_r(errno, buf, sizeof(buf));
 					logerr(MODPREFIX "malloc: %s", estr);
 					ldap_value_free_len(bvValues);
 					goto next;
@@ -2080,7 +2075,7 @@ static int do_get_entries(struct ldap_search_params *sp, struct map_source *sour
 					mapent_len = new_size;
 				} else {
 					char *estr;
-					estr = strerror_r(errno, buf, MAX_ERR_BUF);
+					estr = strerror_r(errno, buf, sizeof(buf));
 					logerr(MODPREFIX "realloc: %s", estr);
 				}
 			}
@@ -2181,7 +2176,7 @@ static int read_one_map(struct autofs_point *ap,
 
 	sp.query = alloca(l);
 	if (sp.query == NULL) {
-		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+		char *estr = strerror_r(errno, buf, sizeof(buf));
 		logerr(MODPREFIX "malloc: %s", estr);
 		return NSS_STATUS_UNAVAIL;
 	}
@@ -2335,7 +2330,7 @@ static int lookup_one(struct autofs_point *ap,
 
 	query = alloca(l);
 	if (query == NULL) {
-		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+		char *estr = strerror_r(errno, buf, sizeof(buf));
 		crit(ap->logopt, MODPREFIX "malloc: %s", estr);
 		if (enc_len1) {
 			free(enc_key1);
@@ -2507,7 +2502,7 @@ static int lookup_one(struct autofs_point *ap,
 				mapent = malloc(v_len + 1);
 				if (!mapent) {
 					char *estr;
-					estr = strerror_r(errno, buf, MAX_ERR_BUF);
+					estr = strerror_r(errno, buf, sizeof(buf));
 					logerr(MODPREFIX "malloc: %s", estr);
 					ldap_value_free_len(bvValues);
 					goto next;
@@ -2527,7 +2522,7 @@ static int lookup_one(struct autofs_point *ap,
 					mapent_len = new_size;
 				} else {
 					char *estr;
-					estr = strerror_r(errno, buf, MAX_ERR_BUF);
+					estr = strerror_r(errno, buf, sizeof(buf));
 					logerr(MODPREFIX "realloc: %s", estr);
 				}
 			}

autofs-5.0.4-renew-sasl-creds-upon-reconnect-fail.patch:

--- NEW FILE autofs-5.0.4-renew-sasl-creds-upon-reconnect-fail.patch ---
autofs-5.0.4 - renew sasl creds upon reconnect fail

From: Ian Kent <raven at themaw.net>

If a server re-connect fails it could be due to the authentication
credentail having timed out. So we need to dispose of this and retry
the connection including refreshing re-authenticating.
---

 CHANGELOG             |    1 +
 modules/lookup_ldap.c |   17 +++++++++++++++++
 2 files changed, 18 insertions(+), 0 deletions(-)


diff --git a/CHANGELOG b/CHANGELOG
index b093451..7dee674 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -11,6 +11,7 @@
 - use CLOEXEC flag for setmntent also.
 - fix hosts map use after free.
 - fix uri list locking (again).
+- check for stale SASL credentials upon connect fail.
 
 4/11/2008 autofs-5.0.4
 -----------------------
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index b6784e1..bee97ae 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -675,6 +675,13 @@ static LDAP *do_reconnect(unsigned logopt, struct lookup_context *ctxt)
 
 	if (ctxt->server || !ctxt->uris) {
 		ldap = do_connect(logopt, ctxt->server, ctxt);
+#ifdef WITH_SASL
+		/* Dispose of the sasl authentication connection and try again. */
+		if (!ldap) {
+			autofs_sasl_dispose(ctxt);
+			ldap = connect_to_server(logopt, ctxt->server, ctxt);
+		}
+#endif
 		return ldap;
 	}
 
@@ -682,6 +689,16 @@ static LDAP *do_reconnect(unsigned logopt, struct lookup_context *ctxt)
 	this = ctxt->uri;
 	uris_mutex_unlock(ctxt);
 	ldap = do_connect(logopt, this->uri, ctxt);
+#ifdef WITH_SASL
+	/*
+	 * Dispose of the sasl authentication connection and try the
+	 * current server again before trying other servers in the list.
+	 */
+	if (!ldap) {
+		autofs_sasl_dispose(ctxt);
+		ldap = connect_to_server(logopt, this->uri, ctxt);
+	}
+#endif
 	if (ldap)
 		return ldap;
 

autofs-5.0.4-uris-list-locking-fix.patch:

--- NEW FILE autofs-5.0.4-uris-list-locking-fix.patch ---
autofs-5.0.4 - uris list locking fix

From: Ian Kent <raven at themaw.net>

The ldap uris list doesn't need to change we just need to keep
track of current server uri in the list and try to connect in
a round robin order. Also it's possible multiple concurrent
connection attempts may not be able to use the full list of
servers (if one is present).
---

 CHANGELOG             |    1 +
 include/lookup_ldap.h |    3 +-
 modules/lookup_ldap.c |   68 ++++++++++++++++++++++---------------------------
 3 files changed, 33 insertions(+), 39 deletions(-)


diff --git a/CHANGELOG b/CHANGELOG
index 3199e4d..b093451 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -10,6 +10,7 @@
 - clear the quoted flag after each character from program map input.
 - use CLOEXEC flag for setmntent also.
 - fix hosts map use after free.
+- fix uri list locking (again).
 
 4/11/2008 autofs-5.0.4
 -----------------------
diff --git a/include/lookup_ldap.h b/include/lookup_ldap.h
index f9ed778..b47bf5d 100644
--- a/include/lookup_ldap.h
+++ b/include/lookup_ldap.h
@@ -55,7 +55,8 @@ struct lookup_context {
  	 * given in configuration.
  	 */
 	pthread_mutex_t uris_mutex;
-	struct list_head *uri;
+	struct list_head *uris;
+	struct ldap_uri *uri;
 	char *cur_host;
 	struct ldap_searchdn *sdns;
 
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index 6ba80eb..b6784e1 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -137,7 +137,7 @@ static void uris_mutex_unlock(struct lookup_context *ctxt)
 	return;
 }
 
-int bind_ldap_anonymous(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt)
+int bind_ldap_anonymous(unsigned logopt, LDAP *ldap, const char *uri, struct lookup_context *ctxt)
 {
 	int rv;
 
@@ -147,16 +147,14 @@ int bind_ldap_anonymous(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt
 		rv = ldap_simple_bind_s(ldap, NULL, NULL);
 
 	if (rv != LDAP_SUCCESS) {
-		if (!ctxt->uri) {
+		if (!ctxt->uris) {
 			crit(logopt, MODPREFIX
 			     "Unable to bind to the LDAP server: "
 			     "%s, error %s", ctxt->server ? "" : "(default)",
 			     ldap_err2string(rv));
 		} else {
-			struct ldap_uri *uri;
-			uri = list_entry(ctxt->uri->next, struct ldap_uri, list);
 			info(logopt, MODPREFIX "Unable to bind to the LDAP server: "
-			     "%s, error %s", uri->uri, ldap_err2string(rv));
+			     "%s, error %s", uri, ldap_err2string(rv));
 		}
 		return -1;
 	}
@@ -498,7 +496,7 @@ static int find_query_dn(unsigned logopt, LDAP *ldap, struct lookup_context *ctx
 	return 0;
 }
 
-static int do_bind(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt)
+static int do_bind(unsigned logopt, LDAP *ldap, const char *uri, struct lookup_context *ctxt)
 {
 	char *host = NULL, *nhost;
 	int rv, need_base = 1;
@@ -511,11 +509,11 @@ static int do_bind(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt)
 		rv = autofs_sasl_bind(logopt, ldap, ctxt);
 		debug(logopt, MODPREFIX "autofs_sasl_bind returned %d", rv);
 	} else {
-		rv = bind_ldap_anonymous(logopt, ldap, ctxt);
+		rv = bind_ldap_anonymous(logopt, ldap, uri, ctxt);
 		debug(logopt, MODPREFIX "ldap anonymous bind returned %d", rv);
 	}
 #else
-	rv = bind_ldap_anonymous(logopt, ldap, ctxt);
+	rv = bind_ldap_anonymous(logopt, ldap, uri, ctxt);
 	debug(logopt, MODPREFIX "ldap anonymous bind returned %d", rv);
 #endif
 
@@ -584,7 +582,7 @@ static LDAP *do_connect(unsigned logopt, const char *uri, struct lookup_context
 	if (!ldap)
 		return NULL;
 
-	if (!do_bind(logopt, ldap, ctxt)) {
+	if (!do_bind(logopt, ldap, uri, ctxt)) {
 		unbind_ldap_connection(logopt, ldap, ctxt);
 		return NULL;
 	}
@@ -612,7 +610,7 @@ static LDAP *connect_to_server(unsigned logopt, const char *uri, struct lookup_c
 			return NULL;
 		}
 
-		if (!do_bind(logopt, ldap, ctxt)) {
+		if (!do_bind(logopt, ldap, uri, ctxt)) {
 			unbind_ldap_connection(logopt, ldap, ctxt);
 			autofs_sasl_dispose(ctxt);
 			error(logopt, MODPREFIX "cannot bind to server");
@@ -638,36 +636,34 @@ static LDAP *find_server(unsigned logopt, struct lookup_context *ctxt)
 {
 	LDAP *ldap = NULL;
 	struct ldap_uri *this;
-	struct list_head *p;
-	LIST_HEAD(tmp);
+	struct list_head *p, *first;
 
 	/* Try each uri in list, add connect fails to tmp list */
 	uris_mutex_lock(ctxt);
-	p = ctxt->uri->next;
-	while(p != ctxt->uri) {
+	if (!ctxt->uri)
+		first = ctxt->uris;
+	else
+		first = &ctxt->uri->list;
+	uris_mutex_unlock(ctxt);
+	p = first->next;
+	while(p != first) {
+		/* Skip list head */
+		if (p == ctxt->uris) {
+			p = p->next;
+			continue;
+		}
 		this = list_entry(p, struct ldap_uri, list);
-		uris_mutex_unlock(ctxt);
 		debug(logopt, "trying server %s", this->uri);
 		ldap = connect_to_server(logopt, this->uri, ctxt);
 		if (ldap) {
 			info(logopt, "connected to uri %s", this->uri);
 			uris_mutex_lock(ctxt);
+			ctxt->uri = this;
+			uris_mutex_unlock(ctxt);
 			break;
 		}
-		uris_mutex_lock(ctxt);
 		p = p->next;
-		list_del_init(&this->list);
-		list_add_tail(&this->list, &tmp);
 	}
-	/*
-	 * Successfuly connected uri (head of list) and untried uris are
-	 * in ctxt->uri list. Make list of remainder and failed uris with
-	 * failed uris at end and assign back to ctxt-uri.
-	 */
-	list_splice(ctxt->uri, &tmp);
-	INIT_LIST_HEAD(ctxt->uri);
-	list_splice(&tmp, ctxt->uri);
-	uris_mutex_unlock(ctxt);
 
 	return ldap;
 }
@@ -677,23 +673,19 @@ static LDAP *do_reconnect(unsigned logopt, struct lookup_context *ctxt)
 	struct ldap_uri *this;
 	LDAP *ldap;
 
-	if (ctxt->server || !ctxt->uri) {
+	if (ctxt->server || !ctxt->uris) {
 		ldap = do_connect(logopt, ctxt->server, ctxt);
 		return ldap;
 	}
 
 	uris_mutex_lock(ctxt);
-	this = list_entry(ctxt->uri->next, struct ldap_uri, list);
+	this = ctxt->uri;
 	uris_mutex_unlock(ctxt);
 	ldap = do_connect(logopt, this->uri, ctxt);
 	if (ldap)
 		return ldap;
 
-	/* Failed to connect, put at end of list */
-	uris_mutex_lock(ctxt);
-	list_del_init(&this->list);
-	list_add_tail(&this->list, ctxt->uri);
-	uris_mutex_unlock(ctxt);
+	/* Failed to connect, try to find a new server */
 
 #ifdef WITH_SASL
 	autofs_sasl_dispose(ctxt);
@@ -1259,8 +1251,8 @@ static void free_context(struct lookup_context *ctxt)
 		free(ctxt->cur_host);
 	if (ctxt->base)
 		free(ctxt->base);
-	if (ctxt->uri)
-		defaults_free_uris(ctxt->uri);
+	if (ctxt->uris)
+		defaults_free_uris(ctxt->uris);
 	ret = pthread_mutex_destroy(&ctxt->uris_mutex);
 	if (ret)
 		fatal(ret);
@@ -1344,7 +1336,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 		if (uris) {
 			validate_uris(uris);
 			if (!list_empty(uris))
-				ctxt->uri = uris;
+				ctxt->uris = uris;
 			else {
 				error(LOGOPT_ANY,
 				      "no valid uris found in config list"
@@ -1375,7 +1367,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 	}
 #endif
 
-	if (ctxt->server || !ctxt->uri) {
+	if (ctxt->server || !ctxt->uris) {
 		ldap = connect_to_server(LOGOPT_NONE, ctxt->server, ctxt);
 		if (!ldap) {
 			free_context(ctxt);


Index: autofs.spec
===================================================================
RCS file: /cvs/pkgs/rpms/autofs/devel/autofs.spec,v
retrieving revision 1.265
retrieving revision 1.266
diff -u -r1.265 -r1.266
--- autofs.spec	5 Feb 2009 07:00:17 -0000	1.265
+++ autofs.spec	16 Feb 2009 04:01:39 -0000	1.266
@@ -4,7 +4,7 @@
 Summary: A tool for automatically mounting and unmounting filesystems
 Name: autofs
 Version: 5.0.4
-Release: 8
+Release: 9
 Epoch: 1
 License: GPLv2+
 Group: System Environment/Daemons
@@ -19,6 +19,18 @@
 Patch7: autofs-5.0.4-make-hash-table-scale-to-thousands-of-entries.patch
 Patch8: autofs-5.0.4-fix-quoted-mess.patch
 Patch9: autofs-5.0.4-use-CLOEXEC-flag-setmntent.patch
+Patch10: autofs-5.0.4-fix-hosts-map-use-after-free.patch
+Patch11: autofs-5.0.4-uris-list-locking-fix.patch
+Patch12: autofs-5.0.4-renew-sasl-creds-upon-reconnect-fail.patch
+Patch13: autofs-5.0.4-library-reload-fix-update.patch
+Patch14: autofs-5.0.4-force-unlink-umount.patch
+Patch15: autofs-5.0.4-always-read-file-maps.patch
+Patch16: autofs-5.0.4-code-analysis-corrections.patch
+Patch17: autofs-5.0.4-make-MAX_ERR_BUF-and-PARSE_MAX_BUF-use-easier-to-audit.patch
+Patch18: autofs-5.0.4-easy-alloca-replacements.patch
+Patch19: autofs-5.0.4-configure-libtirpc.patch
+Patch20: autofs-5.0.4-ipv6-name-and-address-support.patch
+Patch21: autofs-5.0.4-ipv6-parse.patch
 Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 BuildRequires: autoconf, hesiod-devel, openldap-devel, bison, flex, libxml2-devel, cyrus-sasl-devel, openssl-devel module-init-tools util-linux nfs-utils e2fsprogs
 Requires: kernel >= 2.6.17
@@ -69,10 +81,22 @@
 %patch7 -p1
 %patch8 -p1
 %patch9 -p1
+%patch10 -p1
+%patch11 -p1
+%patch12 -p1
+%patch13 -p1
+%patch14 -p1
+%patch15 -p1
+%patch16 -p1
+%patch17 -p1
+%patch18 -p1
+%patch19 -p1
+%patch20 -p1
+%patch21 -p1
 
 %build
 #CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=/usr --libdir=%{_libdir}
-%configure --disable-mount-locking --enable-ignore-busy
+%configure --disable-mount-locking --enable-ignore-busy --with-libtirpc
 make initdir=%{_initrddir} DONTSTRIP=1
 
 %install
@@ -121,6 +145,19 @@
 %{_libdir}/autofs/
 
 %changelog
+* Mon Feb 16 2009 Ian Kent <ikent at redhat.com> - 5.0.4-9
+- fix hosts map use after free.
+- fix uri list locking (again).
+- check for stale SASL credentials upon connect fail.
+- add "forcestart" and "forcerestart" init script options to allow
+  use of 5.0.3 strartup behavior if required.
+- always read entire file map into cache to speed lookups.
+- make MAX_ERR_BUF and PARSE_MAX_BUF use easier to audit.
+- make some easy alloca replacements.
+- update to configure libtirpc if present.
+- update to provide ipv6 name and address support.
+- update to provide ipv6 address parsing.
+
 * Thu Feb 5 2009 Ian Kent <ikent at redhat.com> - 5.0.4-8
 - rename program map parsing bug fix patch.
 - use CLOEXEC flag functionality for setmntent also, if present.




More information about the fedora-extras-commits mailing list