Blame SOURCES/autofs-5.1.6-fix-a-regression-with-map-instance-lookup.patch

b2d21a
autofs-5.1.6 - fix a regression with map instance lookup
b2d21a
b2d21a
From: Ian Kent <raven@themaw.net>
b2d21a
b2d21a
Commit b66deff4241d ("autofs-5.1.3 - fix possible map instance memory
b2d21a
leak") introduced a regression.
b2d21a
b2d21a
The change didn't fix the memory leak and also failed to fix the race
b2d21a
updating the map instance list that caused it.
b2d21a
b2d21a
To fix this get rid of the horible temporary map usage and update the
b2d21a
instance list in place. Doing this causes some additional allocations
b2d21a
and frees but is somewhat simpler overall and avoids the race.
b2d21a
b2d21a
Fixes: b66deff4241d ("autofs-5.1.3 - fix possible map instance memory leak")
b2d21a
Signed-off-by: Ian Kent <raven@themaw.net>
b2d21a
---
b2d21a
 CHANGELOG       |    1 
b2d21a
 daemon/lookup.c |  180 +++++++++++++++++++++++---------------------------------
b2d21a
 2 files changed, 76 insertions(+), 105 deletions(-)
b2d21a
b2d21a
--- autofs-5.1.4.orig/CHANGELOG
b2d21a
+++ autofs-5.1.4/CHANGELOG
b2d21a
@@ -76,6 +76,7 @@ xx/xx/2018 autofs-5.1.5
b2d21a
 - use local getmntent_r() in get_mnt_list().
b2d21a
 - use local getmntent_r() in tree_make_mnt_list().
b2d21a
 - fix missing initialization of autofs_point flags.
b2d21a
+- fix a regression with map instance lookup.
b2d21a
 
b2d21a
 19/12/2017 autofs-5.1.4
b2d21a
 - fix spec file url.
b2d21a
--- autofs-5.1.4.orig/daemon/lookup.c
b2d21a
+++ autofs-5.1.4/daemon/lookup.c
b2d21a
@@ -64,6 +64,10 @@ static char *find_map_path(struct autofs
b2d21a
 	char *search_path;
b2d21a
 	struct stat st;
b2d21a
 
b2d21a
+	/* Absolute path, just return a copy */
b2d21a
+	if (mname[0] == '/')
b2d21a
+		return strdup(mname);
b2d21a
+
b2d21a
 	/*
b2d21a
 	 * This is different to the way it is in amd.
b2d21a
 	 * autofs will always try to locate maps in AUTOFS_MAP_DIR
b2d21a
@@ -373,14 +377,27 @@ static int read_file_source_instance(str
b2d21a
 	char src_prog[] = "program";
b2d21a
 	struct stat st;
b2d21a
 	char *type, *format;
b2d21a
+	char *path;
b2d21a
+
b2d21a
+	if (map->argc < 1) {
b2d21a
+		error(ap->logopt, "invalid arguments for autofs_point");
b2d21a
+		return NSS_STATUS_UNKNOWN;
b2d21a
+	}
b2d21a
 
b2d21a
-	if (stat(map->argv[0], &st) == -1) {
b2d21a
-		warn(ap->logopt, "file map %s not found", map->argv[0]);
b2d21a
+	path = find_map_path(ap, map);
b2d21a
+	if (!path)
b2d21a
+		return NSS_STATUS_UNKNOWN;
b2d21a
+
b2d21a
+	if (stat(path, &st) == -1) {
b2d21a
+		warn(ap->logopt, "file map %s not found", path);
b2d21a
+		free(path);
b2d21a
 		return NSS_STATUS_NOTFOUND;
b2d21a
 	}
b2d21a
 
b2d21a
-	if (!S_ISREG(st.st_mode))
b2d21a
+	if (!S_ISREG(st.st_mode)) {
b2d21a
+		free(path);
b2d21a
 		return NSS_STATUS_NOTFOUND;
b2d21a
+	}
b2d21a
 
b2d21a
 	if (st.st_mode & __S_IEXEC)
b2d21a
 		type = src_prog;
b2d21a
@@ -391,9 +408,23 @@ static int read_file_source_instance(str
b2d21a
 
b2d21a
 	instance = master_find_source_instance(map, type, format, 0, NULL);
b2d21a
 	if (!instance) {
b2d21a
-		int argc = map->argc;
b2d21a
-		const char **argv = map->argv;
b2d21a
+		const char **argv;
b2d21a
+		int argc;
b2d21a
+
b2d21a
+		argc = map->argc;
b2d21a
+		argv = copy_argv(map->argc, map->argv);
b2d21a
+		if (!argv) {
b2d21a
+			error(ap->logopt, "failed to copy args");
b2d21a
+			free(path);
b2d21a
+			return NSS_STATUS_UNKNOWN;
b2d21a
+		}
b2d21a
+		if (argv[0])
b2d21a
+			free((char *) argv[0]);
b2d21a
+		argv[0] = path;
b2d21a
+		path = NULL;
b2d21a
+
b2d21a
 		instance = master_add_source_instance(map, type, format, age, argc, argv);
b2d21a
+		free_argv(argc, argv);
b2d21a
 		if (!instance)
b2d21a
 			return NSS_STATUS_UNAVAIL;
b2d21a
 		instance->recurse = map->recurse;
b2d21a
@@ -401,6 +432,9 @@ static int read_file_source_instance(str
b2d21a
 	}
b2d21a
 	instance->stale = map->stale;
b2d21a
 
b2d21a
+	if (path)
b2d21a
+		free(path);
b2d21a
+
b2d21a
 	return do_read_map(ap, instance, age);
b2d21a
 }
b2d21a
 
b2d21a
@@ -476,16 +510,11 @@ static int lookup_map_read_map(struct au
b2d21a
 static enum nsswitch_status read_map_source(struct nss_source *this,
b2d21a
 		struct autofs_point *ap, struct map_source *map, time_t age)
b2d21a
 {
b2d21a
-	enum nsswitch_status result;
b2d21a
-	struct map_source tmap;
b2d21a
-	char *path;
b2d21a
-
b2d21a
 	if (strcasecmp(this->source, "files")) {
b2d21a
 		return read_source_instance(ap, map, this->source, age);
b2d21a
 	}
b2d21a
 
b2d21a
 	/* 
b2d21a
-	 * autofs built-in map for nsswitch "files" is "file".
b2d21a
 	 * This is a special case as we need to append the
b2d21a
 	 * normal location to the map name.
b2d21a
 	 * note: It's invalid to specify a relative path.
b2d21a
@@ -496,50 +525,7 @@ static enum nsswitch_status read_map_sou
b2d21a
 		return NSS_STATUS_NOTFOUND;
b2d21a
 	}
b2d21a
 
b2d21a
-	this->source[4] = '\0';
b2d21a
-	tmap.flags = map->flags;
b2d21a
-	tmap.type = this->source;
b2d21a
-	tmap.format = map->format;
b2d21a
-	tmap.name = map->name;
b2d21a
-	tmap.lookup = map->lookup;
b2d21a
-	tmap.mc = map->mc;
b2d21a
-	tmap.instance = map->instance;
b2d21a
-	tmap.exp_timeout = map->exp_timeout;
b2d21a
-	tmap.recurse = map->recurse;
b2d21a
-	tmap.depth = map->depth;
b2d21a
-	tmap.stale = map->stale;
b2d21a
-	tmap.argc = 0;
b2d21a
-	tmap.argv = NULL;
b2d21a
-
b2d21a
-	path = find_map_path(ap, map);
b2d21a
-	if (!path)
b2d21a
-		return NSS_STATUS_UNKNOWN;
b2d21a
-
b2d21a
-	if (map->argc >= 1) {
b2d21a
-		tmap.argc = map->argc;
b2d21a
-		tmap.argv = copy_argv(map->argc, map->argv);
b2d21a
-		if (!tmap.argv) {
b2d21a
-			error(ap->logopt, "failed to copy args");
b2d21a
-			free(path);
b2d21a
-			return NSS_STATUS_UNKNOWN;
b2d21a
-		}
b2d21a
-		if (tmap.argv[0])
b2d21a
-			free((char *) tmap.argv[0]);
b2d21a
-		tmap.argv[0] = path;
b2d21a
-	} else {
b2d21a
-		error(ap->logopt, "invalid arguments for autofs_point");
b2d21a
-		free(path);
b2d21a
-		return NSS_STATUS_UNKNOWN;
b2d21a
-	}
b2d21a
-
b2d21a
-	pthread_cleanup_push(argv_cleanup, &tmap);
b2d21a
-	result = read_file_source_instance(ap, &tmap, age);
b2d21a
-	pthread_cleanup_pop(1);
b2d21a
-
b2d21a
-	if (!map->instance)
b2d21a
-		map->instance = tmap.instance;
b2d21a
-
b2d21a
-	return result;
b2d21a
+	return read_file_source_instance(ap, map, age);
b2d21a
 }
b2d21a
 
b2d21a
 int lookup_nss_read_map(struct autofs_point *ap, struct map_source *source, time_t age)
b2d21a
@@ -925,17 +911,30 @@ static int lookup_name_file_source_insta
b2d21a
 	time_t age = monotonic_time(NULL);
b2d21a
 	struct stat st;
b2d21a
 	char *type, *format;
b2d21a
+	char *path;
b2d21a
 
b2d21a
 	if (*name == '/' && map->flags & MAP_FLAG_FORMAT_AMD)
b2d21a
 		return lookup_amd_instance(ap, map, name, name_len);
b2d21a
 
b2d21a
-	if (stat(map->argv[0], &st) == -1) {
b2d21a
+	if (map->argc < 1) {
b2d21a
+		error(ap->logopt, "invalid arguments for autofs_point");
b2d21a
+		return NSS_STATUS_UNKNOWN;
b2d21a
+	}
b2d21a
+
b2d21a
+	path = find_map_path(ap, map);
b2d21a
+	if (!path)
b2d21a
+		return NSS_STATUS_UNKNOWN;
b2d21a
+
b2d21a
+	if (stat(path, &st) == -1) {
b2d21a
 		debug(ap->logopt, "file map not found");
b2d21a
+		free(path);
b2d21a
 		return NSS_STATUS_NOTFOUND;
b2d21a
 	}
b2d21a
 
b2d21a
-	if (!S_ISREG(st.st_mode))
b2d21a
+	if (!S_ISREG(st.st_mode)) {
b2d21a
+		free(path);
b2d21a
 		return NSS_STATUS_NOTFOUND;
b2d21a
+	}
b2d21a
 
b2d21a
 	if (st.st_mode & __S_IEXEC)
b2d21a
 		type = src_prog;
b2d21a
@@ -946,15 +945,32 @@ static int lookup_name_file_source_insta
b2d21a
 
b2d21a
 	instance = master_find_source_instance(map, type, format, 0, NULL);
b2d21a
 	if (!instance) {
b2d21a
-		int argc = map->argc;
b2d21a
-		const char **argv = map->argv;
b2d21a
+		const char **argv;
b2d21a
+		int argc;
b2d21a
+
b2d21a
+		argc = map->argc;
b2d21a
+		argv = copy_argv(map->argc, map->argv);
b2d21a
+		if (!argv) {
b2d21a
+			error(ap->logopt, "failed to copy args");
b2d21a
+			free(path);
b2d21a
+			return NSS_STATUS_UNKNOWN;
b2d21a
+		}
b2d21a
+		if (argv[0])
b2d21a
+			free((char *) argv[0]);
b2d21a
+		argv[0] = path;
b2d21a
+		path = NULL;
b2d21a
+
b2d21a
 		instance = master_add_source_instance(map, type, format, age, argc, argv);
b2d21a
+		free_argv(argc, argv);
b2d21a
 		if (!instance)
b2d21a
 			return NSS_STATUS_NOTFOUND;
b2d21a
 		instance->recurse = map->recurse;
b2d21a
 		instance->depth = map->depth;
b2d21a
 	}
b2d21a
 
b2d21a
+	if (path)
b2d21a
+		free(path);
b2d21a
+
b2d21a
 	return do_lookup_mount(ap, instance, name, name_len);
b2d21a
 }
b2d21a
 
b2d21a
@@ -1030,10 +1046,6 @@ static enum nsswitch_status lookup_map_n
b2d21a
 			struct autofs_point *ap, struct map_source *map,
b2d21a
 			const char *name, int name_len)
b2d21a
 {
b2d21a
-	enum nsswitch_status result;
b2d21a
-	struct map_source tmap;
b2d21a
-	char *path;
b2d21a
-
b2d21a
 	if (strcasecmp(this->source, "files"))
b2d21a
 		return lookup_name_source_instance(ap, map,
b2d21a
 					this->source, name, name_len);
b2d21a
@@ -1050,49 +1062,7 @@ static enum nsswitch_status lookup_map_n
b2d21a
 		return NSS_STATUS_NOTFOUND;
b2d21a
 	}
b2d21a
 
b2d21a
-	this->source[4] = '\0';
b2d21a
-	tmap.flags = map->flags;
b2d21a
-	tmap.type = this->source;
b2d21a
-	tmap.format = map->format;
b2d21a
-	tmap.name = map->name;
b2d21a
-	tmap.mc = map->mc;
b2d21a
-	tmap.instance = map->instance;
b2d21a
-	tmap.exp_timeout = map->exp_timeout;
b2d21a
-	tmap.recurse = map->recurse;
b2d21a
-	tmap.depth = map->depth;
b2d21a
-	tmap.argc = 0;
b2d21a
-	tmap.argv = NULL;
b2d21a
-
b2d21a
-	path = find_map_path(ap, map);
b2d21a
-	if (!path)
b2d21a
-		return NSS_STATUS_UNKNOWN;
b2d21a
-
b2d21a
-	if (map->argc >= 1) {
b2d21a
-		tmap.argc = map->argc;
b2d21a
-		tmap.argv = copy_argv(map->argc, map->argv);
b2d21a
-		if (!tmap.argv) {
b2d21a
-			error(ap->logopt, "failed to copy args");
b2d21a
-			free(path);
b2d21a
-			return NSS_STATUS_UNKNOWN;
b2d21a
-		}
b2d21a
-		if (tmap.argv[0])
b2d21a
-			free((char *) tmap.argv[0]);
b2d21a
-		tmap.argv[0] = path;
b2d21a
-	} else {
b2d21a
-		error(ap->logopt, "invalid arguments for autofs_point");
b2d21a
-		free(path);
b2d21a
-		return NSS_STATUS_UNKNOWN;
b2d21a
-	}
b2d21a
-
b2d21a
-	result = lookup_name_file_source_instance(ap, &tmap, name, name_len);
b2d21a
-
b2d21a
-	if (!map->instance)
b2d21a
-		map->instance = tmap.instance;
b2d21a
-
b2d21a
-	/* path is freed in free_argv */
b2d21a
-	free_argv(tmap.argc, tmap.argv);
b2d21a
-
b2d21a
-	return result;
b2d21a
+	return lookup_name_file_source_instance(ap, map, name, name_len);
b2d21a
 }
b2d21a
 
b2d21a
 static struct map_source *lookup_get_map_source(struct master_mapent *entry)