autofs-5.1.0 - add a prefix to program map stdvars From: Ian Kent 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. --- CHANGELOG | 1 + include/mounts.h | 4 +- lib/mounts.c | 84 ++++++++++++++++++++++++++++++++++++++-------- modules/lookup_program.c | 2 + modules/parse_sun.c | 8 ++-- 5 files changed, 78 insertions(+), 21 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 54a4066..f491f74 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -42,6 +42,7 @@ - make negative cache update consistent for all lookup modules. - ensure negative cache isn't updated on remount. - dont add wildcard to negative cache. +- add a prefix to program map stdvars. 04/06/2014 autofs-5.1.0 ======================= diff --git a/include/mounts.h b/include/mounts.h index 17cae31..0b1cbd1 100644 --- a/include/mounts.h +++ b/include/mounts.h @@ -87,8 +87,8 @@ extern unsigned int nfs_mount_uses_string_options; struct amd_entry; -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); void add_std_amd_vars(struct substvar *sv); void remove_std_amd_vars(void); struct amd_entry *new_amd_entry(const struct substvar *sv); diff --git a/lib/mounts.c b/lib/mounts.c index 27ea744..74eb0d5 100644 --- a/lib/mounts.c +++ b/lib/mounts.c @@ -32,6 +32,7 @@ #define MAX_OPTIONS_LEN 80 #define MAX_MNT_NAME_LEN 30 +#define MAX_ENV_NAME 15 #define EBUFSIZ 1024 @@ -328,7 +329,61 @@ int check_nfs_mount_version(struct nfs_mount_vers *vers, } #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; @@ -343,14 +398,14 @@ struct substvar *addstdenv(struct substvar *sv) 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); @@ -358,7 +413,8 @@ struct substvar *addstdenv(struct substvar *sv) 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); } } @@ -366,16 +422,16 @@ struct substvar *addstdenv(struct substvar *sv) 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; } diff --git a/modules/lookup_program.c b/modules/lookup_program.c index 8e8fd49..6fc861a 100644 --- a/modules/lookup_program.c +++ b/modules/lookup_program.c @@ -181,7 +181,7 @@ static char *lookup_one(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); diff --git a/modules/parse_sun.c b/modules/parse_sun.c index a3c736e..334ee93 100644 --- a/modules/parse_sun.c +++ b/modules/parse_sun.c @@ -1214,12 +1214,12 @@ int parse_mount(struct autofs_point *ap, const char *name, 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, const char *name, 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, const char *name, 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);