From: Ian Kent <ikent@redhat.com>
Subject: autofs-5.1.0 - add a prefix to program map stdvars
Git-commit: 91e42e58b40b34c32250faee5862d185915148ff
Patch-mainline: v5.1.1

When a program map uses an interpreted languages like python it's
possible to load and execute arbitray code from a user home directory.
This is because the standard environment variables are used to locate
and load modules when using these languages.

To avoid that we need to add a prefix to these environment names so
they aren't used for this purpose. The prefix used is "AUTOFS_" and
is not configurable.
---
 include/mounts.h         |    4 +-
 lib/mounts.c             |   84 +++++++++++++++++++++++++++++++++++++++--------
 modules/lookup_program.c |    2 -
 modules/parse_sun.c      |    8 ++--
 4 files changed, 77 insertions(+), 21 deletions(-)

--- a/include/mounts.h
+++ b/include/mounts.h
@@ -85,8 +85,8 @@ unsigned int linux_version_code(void);
 int check_nfs_mount_version(struct nfs_mount_vers *, struct nfs_mount_vers *);
 extern unsigned int nfs_mount_uses_string_options;
 
-struct substvar *addstdenv(struct substvar *sv);
-struct substvar *removestdenv(struct substvar *sv);
+struct substvar *addstdenv(struct substvar *sv, const char *prefix);
+struct substvar *removestdenv(struct substvar *sv, const char *prefix);
 
 unsigned int query_kproto_ver(void);
 unsigned int get_kver_major(void);
--- a/lib/mounts.c
+++ b/lib/mounts.c
@@ -31,6 +31,7 @@
 
 #define MAX_OPTIONS_LEN		80
 #define MAX_MNT_NAME_LEN	30
+#define MAX_ENV_NAME		15
 
 #define EBUFSIZ 1024
 
@@ -303,7 +304,61 @@ int check_nfs_mount_version(struct nfs_m
 }
 #endif
 
-struct substvar *addstdenv(struct substvar *sv)
+static char *set_env_name(const char *prefix, const char *name, char *buf)
+{
+	size_t len;
+
+	len = strlen(name);
+	if (prefix)
+		len += strlen(prefix);
+	len++;
+
+	if (len > MAX_ENV_NAME)
+		return NULL;
+
+	if (!prefix)
+		strcpy(buf, name);
+	else {
+		strcpy(buf, prefix);
+		strcat(buf, name);
+	}
+	return buf;
+}
+
+static struct substvar *do_macro_addvar(struct substvar *list,
+					const char *prefix,
+					const char *name,
+					const char *val)
+{
+	char buf[MAX_ENV_NAME + 1];
+	char *new;
+	size_t len;
+
+	new = set_env_name(prefix, name, buf);
+	if (new) {
+		len = strlen(new);
+		list = macro_addvar(list, new, len, val);
+	}
+	return list;
+}
+
+static struct substvar *do_macro_removevar(struct substvar *list,
+					   const char *prefix,
+					   const char *name)
+{
+	char buf[MAX_ENV_NAME + 1];
+	char *new;
+	size_t len;
+
+	new = set_env_name(prefix, name, buf);
+	if (new) {
+		len = strlen(new);
+		list = macro_removevar(list, new, len);
+	}
+	return list;
+}
+
+struct substvar *addstdenv(struct substvar *sv, const char *prefix)
 {
 	struct substvar *list = sv;
 	struct thread_stdenv_vars *tsv;
@@ -318,14 +373,14 @@ struct substvar *addstdenv(struct substv
 		num = (long) tsv->uid;
 		ret = sprintf(numbuf, "%ld", num);
 		if (ret > 0)
-			list = macro_addvar(list, "UID", 3, numbuf);
+			list = do_macro_addvar(list, prefix, "UID", numbuf);
 		num = (long) tsv->gid;
 		ret = sprintf(numbuf, "%ld", num);
 		if (ret > 0)
-			list = macro_addvar(list, "GID", 3, numbuf);
-		list = macro_addvar(list, "USER", 4, tsv->user);
-		list = macro_addvar(list, "GROUP", 5, tsv->group);
-		list = macro_addvar(list, "HOME", 4, tsv->home);
+			list = do_macro_addvar(list, prefix, "GID", numbuf);
+		list = do_macro_addvar(list, prefix, "USER", tsv->user);
+		list = do_macro_addvar(list, prefix, "GROUP", tsv->group);
+		list = do_macro_addvar(list, prefix, "HOME", tsv->home);
 		mv = macro_findvar(list, "HOST", 4);
 		if (mv) {
 			char *shost = strdup(mv->val);
@@ -333,7 +388,8 @@ struct substvar *addstdenv(struct substv
 				char *dot = strchr(shost, '.');
 				if (dot)
 					*dot = '\0';
-				list = macro_addvar(list, "SHOST", 5, shost);
+				list = do_macro_addvar(list,
+						       prefix, "SHOST", shost);
 				free(shost);
 			}
 		}
@@ -341,16 +397,16 @@ struct substvar *addstdenv(struct substv
 	return list;
 }
 
-struct substvar *removestdenv(struct substvar *sv)
+struct substvar *removestdenv(struct substvar *sv, const char *prefix)
 {
 	struct substvar *list = sv;
 
-	list = macro_removevar(list, "UID", 3);
-	list = macro_removevar(list, "USER", 4);
-	list = macro_removevar(list, "HOME", 4);
-	list = macro_removevar(list, "GID", 3);
-	list = macro_removevar(list, "GROUP", 5);
-	list = macro_removevar(list, "SHOST", 5);
+	list = do_macro_removevar(list, prefix, "UID");
+	list = do_macro_removevar(list, prefix, "USER");
+	list = do_macro_removevar(list, prefix, "HOME");
+	list = do_macro_removevar(list, prefix, "GID");
+	list = do_macro_removevar(list, prefix, "GROUP");
+	list = do_macro_removevar(list, prefix, "SHOST");
 	return list;
 }
 
--- a/modules/lookup_program.c
+++ b/modules/lookup_program.c
@@ -274,7 +274,7 @@ int lookup_mount(struct autofs_point *ap
 		if (ctxt->mapfmt && strcmp(ctxt->mapfmt, "MAPFMT_DEFAULT")) {
 			struct parse_context *pctxt = (struct parse_context *) ctxt->parse->context;
 			/* Add standard environment as seen by sun map parser */
-			pctxt->subst = addstdenv(pctxt->subst);
+			pctxt->subst = addstdenv(pctxt->subst, "AUTOFS_");
 			macro_setenv(pctxt->subst);
 		}
 		execl(ctxt->mapname, ctxt->mapname, name, NULL);
--- a/modules/parse_sun.c
+++ b/modules/parse_sun.c
@@ -1214,12 +1214,12 @@ int parse_mount(struct autofs_point *ap,
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
 	macro_lock();
 
-	ctxt->subst = addstdenv(ctxt->subst);
+	ctxt->subst = addstdenv(ctxt->subst, NULL);
 
 	mapent_len = expandsunent(mapent, NULL, name, ctxt->subst, slashify);
 	if (mapent_len == 0) {
 		error(ap->logopt, MODPREFIX "failed to expand map entry");
-		ctxt->subst = removestdenv(ctxt->subst);
+		ctxt->subst = removestdenv(ctxt->subst, NULL);
 		macro_unlock();
 		pthread_setcancelstate(cur_state, NULL);
 		return 1;
@@ -1229,7 +1229,7 @@ int parse_mount(struct autofs_point *ap,
 	if (!pmapent) {	
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
 		logerr(MODPREFIX "alloca: %s", estr);
-		ctxt->subst = removestdenv(ctxt->subst);
+		ctxt->subst = removestdenv(ctxt->subst, NULL);
 		macro_unlock();
 		pthread_setcancelstate(cur_state, NULL);
 		return 1;
@@ -1237,7 +1237,7 @@ int parse_mount(struct autofs_point *ap,
 	pmapent[mapent_len] = '\0';
 
 	expandsunent(mapent, pmapent, name, ctxt->subst, slashify);
-	ctxt->subst = removestdenv(ctxt->subst);
+	ctxt->subst = removestdenv(ctxt->subst, NULL);
 
 	macro_unlock();
 	pthread_setcancelstate(cur_state, NULL);
