Hi! My initial patches (partially backported), were missing documentation changes for auto,master(5). Attached new patches, and I followed previous patch orders to have upstream patches on top in debian/patches/series (thus as well the need to refresh subsequent patches).
Would you agree or object to a NMU? Would you like to fix this yourself or do the patches look fine as well for you? In any case I would upload to a delayed queue to give some more time for review. Regards, Salvatore
diff -Nru autofs-5.0.8/debian/changelog autofs-5.0.8/debian/changelog --- autofs-5.0.8/debian/changelog 2014-03-07 05:16:25.000000000 +0100 +++ autofs-5.0.8/debian/changelog 2015-03-11 19:49:44.000000000 +0100 @@ -1,3 +1,23 @@ +autofs (5.0.8-1.1) unstable; urgency=medium + + * Non-maintainer upload. + * Add patches for CVE-2014-8169. + When a program map uses an interpreted languages like python it is + 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, a prefix to + these environment names is added so that they aren't used for this + purpose. The prefix used is "AUTOFS_" and is not configurable. + Additionally a configuration option to force the use of program map + standard environment variables is added + (FORCE_STANDARD_PROGRAM_MAP_ENV). + * Refresh manpages.patch patch + * Refresh manpages-hyphen.patch patch + * Refresh default-autofs-remove-USE_MISC_DEVICE.patch patch + * Refresh remove-kernel-mount.nfs-version-check.patch patch + + -- Salvatore Bonaccorso <car...@debian.org> Wed, 11 Mar 2015 19:47:12 +0100 + autofs (5.0.8-1) unstable; urgency=low * New upstream release [October 2013] (Closes: #729023). diff -Nru autofs-5.0.8/debian/patches/CVE-2014-8169-add-a-prefix-to-program-map-stdvars.patch autofs-5.0.8/debian/patches/CVE-2014-8169-add-a-prefix-to-program-map-stdvars.patch --- autofs-5.0.8/debian/patches/CVE-2014-8169-add-a-prefix-to-program-map-stdvars.patch 1970-01-01 01:00:00.000000000 +0100 +++ autofs-5.0.8/debian/patches/CVE-2014-8169-add-a-prefix-to-program-map-stdvars.patch 2015-03-11 19:49:44.000000000 +0100 @@ -0,0 +1,200 @@ +Description: add a prefix to program map stdvars + When a program map uses an interpreted languages like python it is + possible to load and execute arbitrary code from a user home directory. + This is because the standard environment variables are used to locate + and load modules when using these languages. (CVE-2014-8169) + . + 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. +Origin: vendor +Author: Ian Kent <ik...@redhat.com> +Reviewed-by: Salvatore Bonaccorso <car...@debian.org> +Last-Update: 2015-02-28 +--- +--- 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 +@@ -272,7 +272,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 +@@ -1223,12 +1223,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; +@@ -1238,7 +1238,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; +@@ -1246,7 +1246,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); diff -Nru autofs-5.0.8/debian/patches/CVE-2014-8169-add-config-option-to-force-use-of-program-map-stdvars.patch autofs-5.0.8/debian/patches/CVE-2014-8169-add-config-option-to-force-use-of-program-map-stdvars.patch --- autofs-5.0.8/debian/patches/CVE-2014-8169-add-config-option-to-force-use-of-program-map-stdvars.patch 1970-01-01 01:00:00.000000000 +0100 +++ autofs-5.0.8/debian/patches/CVE-2014-8169-add-config-option-to-force-use-of-program-map-stdvars.patch 2015-03-11 19:49:44.000000000 +0100 @@ -0,0 +1,154 @@ +Description: add config option to force use of program map stdvars + Enabling the extended environment (including $HOME, for example) for + program maps opens automount(8) to a privilege escalation. + . + Rather than just removing the entended environment a configuration + option is added to disable it by default so that those who wish to + use it can do so if they wish. +Origin: vendor +Author: Ian Kent <ik...@redhat.com> +Author: Salvatore Bonaccorso <car...@debian.org> +Last-Update: 2015-02-28 +--- +--- a/include/defaults.h ++++ b/include/defaults.h +@@ -28,6 +28,7 @@ + #define DEFAULT_UMOUNT_WAIT 12 + #define DEFAULT_BROWSE_MODE 1 + #define DEFAULT_LOGGING 0 ++#define DEFAULT_FORCE_STD_PROG_MAP_ENV 0 + + #define DEFAULT_LDAP_TIMEOUT -1 + #define DEFAULT_LDAP_NETWORK_TIMEOUT 8 +@@ -62,6 +63,7 @@ unsigned int defaults_get_timeout(void); + unsigned int defaults_get_negative_timeout(void); + unsigned int defaults_get_browse_mode(void); + unsigned int defaults_get_logging(void); ++unsigned int defaults_force_std_prog_map_env(void); + const char *defaults_get_ldap_server(void); + unsigned int defaults_get_ldap_timeout(void); + unsigned int defaults_get_ldap_network_timeout(void); +--- a/lib/defaults.c ++++ b/lib/defaults.c +@@ -35,6 +35,7 @@ + #define ENV_NAME_NEGATIVE_TIMEOUT "NEGATIVE_TIMEOUT" + #define ENV_NAME_BROWSE_MODE "BROWSE_MODE" + #define ENV_NAME_LOGGING "LOGGING" ++#define ENV_NAME_FORCE_STD_PROG_MAP_ENV "FORCE_STANDARD_PROGRAM_MAP_ENV" + + #define LDAP_URI "LDAP_URI" + #define ENV_LDAP_TIMEOUT "LDAP_TIMEOUT" +@@ -519,6 +520,7 @@ unsigned int defaults_read_config(unsign + check_set_config_value(key, ENV_NAME_NEGATIVE_TIMEOUT, value, to_syslog) || + check_set_config_value(key, ENV_NAME_BROWSE_MODE, value, to_syslog) || + check_set_config_value(key, ENV_NAME_LOGGING, value, to_syslog) || ++ check_set_config_value(key, ENV_NAME_FORCE_STD_PROG_MAP_ENV, value, to_syslog) || + check_set_config_value(key, ENV_LDAP_TIMEOUT, value, to_syslog) || + check_set_config_value(key, ENV_LDAP_NETWORK_TIMEOUT, value, to_syslog) || + check_set_config_value(key, ENV_NAME_MAP_OBJ_CLASS, value, to_syslog) || +@@ -629,6 +631,17 @@ unsigned int defaults_get_logging(void) + return logging; + } + ++unsigned int defaults_force_std_prog_map_env(void) ++{ ++ int res; ++ ++ res = get_env_yesno(ENV_NAME_FORCE_STD_PROG_MAP_ENV); ++ if (res < 0) ++ res = DEFAULT_FORCE_STD_PROG_MAP_ENV; ++ ++ return res; ++} ++ + unsigned int defaults_get_ldap_timeout(void) + { + int res; +--- a/man/autofs.5 ++++ b/man/autofs.5 +@@ -174,6 +174,11 @@ SHOST Short hostname (domain part remove + .fi + .RE + .sp ++If a program map is used these standard environment variables will have ++a prefix of "AUTOFS_" to prevent interpreted languages like python from ++being able to load and execute arbitray code from a user home directory. ++.RE ++.sp + Additional entries can be defined with the -Dvariable=Value map-option to + .BR automount (8). + .SS Executable Maps +--- a/modules/lookup_program.c ++++ b/modules/lookup_program.c +@@ -132,6 +132,7 @@ int lookup_mount(struct autofs_point *ap + int ret = 1; + int distance; + int alloci = 1; ++ char *prefix; + + source = ap->entry->current; + ap->entry->current = NULL; +@@ -265,6 +266,17 @@ int lookup_mount(struct autofs_point *ap + warn(ap->logopt, + MODPREFIX "failed to set PWD to %s for map %s", + ap->path, ctxt->mapname); ++ ++ /* ++ * By default use a prefix with standard environment ++ * variables to prevent system subversion by interpreted ++ * languages. ++ */ ++ if (defaults_force_std_prog_map_env()) ++ prefix = NULL; ++ else ++ prefix = "AUTOFS_"; ++ + /* + * MAPFMT_DEFAULT must be "sun" for ->parse_init() to have setup + * the macro table. +@@ -272,7 +284,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, "AUTOFS_"); ++ pctxt->subst = addstdenv(pctxt->subst, prefix); + macro_setenv(pctxt->subst); + } + execl(ctxt->mapname, ctxt->mapname, name, NULL); +--- a/samples/autofs.conf.default.in ++++ b/samples/autofs.conf.default.in +@@ -80,6 +80,17 @@ BROWSE_MODE="no" + # + #LDAP_NETWORK_TIMEOUT=8 + # ++# FORCE_STANDARD_PROGRAM_MAP_ENV - disable the use of the "AUTOFS_" ++# prefix for standard environment variables when ++# executing a program map. Since program maps ++# are run as the privileded user this opens ++# automount(8) to potential user privilege ++# escalation when the program map is written ++# in a language that can load components from, ++# for example, a user home directory. ++# ++#FORCE_STANDARD_PROGRAM_MAP_ENV="no" ++# + # Define base dn for map dn lookup. + # + # SEARCH_BASE - base dn to use for searching for map search dn. +--- a/man/auto.master.5.in ++++ b/man/auto.master.5.in +@@ -250,6 +250,14 @@ options replace the global options (prog + .TP + .B LOGGING + set default log level "none", "verbose" or "debug" (program default "none"). ++.TP ++.B FORCE_STANDARD_PROGRAM_MAP_ENV ++override the use of a prefix with standard environment variables when a ++program map is executed. Since program maps are run as the privileded ++user setting these standard environment variables opens automount(8) to ++potential user privilege escalation when the program map is written in a ++language that can load components from, for example, a user home directory ++(program default "no"). + .SH BUILTIN MAP -hosts + If "-hosts" is given as the map then accessing a key under the mount point + which corresponds to a hostname will allow access to the exports of that diff -Nru autofs-5.0.8/debian/patches/default-autofs-remove-USE_MISC_DEVICE.patch autofs-5.0.8/debian/patches/default-autofs-remove-USE_MISC_DEVICE.patch --- autofs-5.0.8/debian/patches/default-autofs-remove-USE_MISC_DEVICE.patch 2014-03-07 05:16:07.000000000 +0100 +++ autofs-5.0.8/debian/patches/default-autofs-remove-USE_MISC_DEVICE.patch 2015-03-11 19:49:44.000000000 +0100 @@ -8,8 +8,7 @@ --- a/samples/autofs.conf.default.in +++ b/samples/autofs.conf.default.in -@@ -127,11 +127,6 @@ - #MAP_HASH_TABLE_SIZE=1024 +@@ -139,10 +139,5 @@ BROWSE_MODE="no" # # General global options # diff -Nru autofs-5.0.8/debian/patches/manpages-hyphen.patch autofs-5.0.8/debian/patches/manpages-hyphen.patch --- autofs-5.0.8/debian/patches/manpages-hyphen.patch 2014-03-07 05:16:07.000000000 +0100 +++ autofs-5.0.8/debian/patches/manpages-hyphen.patch 2015-03-11 19:49:44.000000000 +0100 @@ -5,8 +5,7 @@ --- a/man/autofs.5 +++ b/man/autofs.5 -@@ -21,9 +21,9 @@ - This is a description of the text file format. Other methods of specifying +@@ -22,7 +22,7 @@ This is a description of the text file f these files may exist. All empty lines or lines beginning with # are ignored. The basic format of one line in such maps is: .P @@ -15,9 +14,7 @@ .SS key For indirect mounts this is the part of the path name between the mount point - and the path into the filesystem when it is mounted. Usually you can think about the -@@ -39,22 +39,22 @@ - from SunOS). The options are a list of comma separated options as +@@ -40,20 +40,20 @@ from SunOS). The options are a list of customary for the .BR mount (8) command. There are two special options @@ -42,9 +39,7 @@ can be used to negate the option if it is present in the master map entry for the map but is not wanted for the given mount. - .SS location -@@ -71,15 +71,15 @@ - .sp +@@ -72,13 +72,13 @@ Indirect map: .RS +.2i .ta 1.0i 3.0i .nf @@ -65,9 +60,7 @@ /usr myserver.me.org:/usr \\ /home myserver.me.org:/home .fi - .RE -@@ -103,9 +103,9 @@ - .sp +@@ -104,7 +104,7 @@ example entry for an autofs map: .RS +.2i .ta 1.0i 3.0i .nf @@ -76,9 +69,7 @@ .fi .RE .sp - Direct map: -@@ -149,14 +149,14 @@ - .sp +@@ -150,12 +150,12 @@ scripts (Curly braces can be used to sep .RS +.2i .ta 1.5i .nf @@ -96,10 +87,8 @@ .fi .RE .sp - autofs provides additional variables that are set based on the -@@ -173,9 +173,9 @@ - SHOST Short hostname (domain part removed if present) - .fi +@@ -179,7 +179,7 @@ a prefix of "AUTOFS_" to prevent interpr + being able to load and execute arbitray code from a user home directory. .RE .sp -Additional entries can be defined with the -Dvariable=Value map-option to @@ -107,14 +96,12 @@ .BR automount (8). .SS Executable Maps A map can be marked as executable. A - .B program --- a/man/auto.master.5.in +++ b/man/auto.master.5.in -@@ -249,19 +249,19 @@ - options replace the global options (program default "yes", append options). - .TP - .B LOGGING - set default log level "none", "verbose" or "debug" (program default "none"). +@@ -258,8 +258,8 @@ user setting these standard environment + potential user privilege escalation when the program map is written in a + language that can load components from, for example, a user home directory + (program default "no"). -.SH BUILTIN MAP -hosts -If "-hosts" is given as the map then accessing a key under the mount point +.SH BUILTIN MAP \-hosts @@ -122,8 +109,7 @@ which corresponds to a hostname will allow access to the exports of that host. The hosts map cannot be dynamically updated and requires a HUP signal to be sent to the daemon for it to check hosts for an update. Due to possible - hierarchic dependencies within a mount tree, it might not be completely - updated during the HUP signal processing. +@@ -268,7 +268,7 @@ updated during the HUP signal processing .P For example, with an entry in the master map of .nh @@ -132,4 +118,3 @@ .hy accessing /net/myserver will mount exports from myserver on directories below /net/myserver. - .P diff -Nru autofs-5.0.8/debian/patches/manpages.patch autofs-5.0.8/debian/patches/manpages.patch --- autofs-5.0.8/debian/patches/manpages.patch 2014-03-07 05:16:07.000000000 +0100 +++ autofs-5.0.8/debian/patches/manpages.patch 2015-03-11 19:49:44.000000000 +0100 @@ -5,8 +5,7 @@ --- a/man/auto.master.5.in +++ b/man/auto.master.5.in -@@ -321,9 +321,9 @@ - .B LDAP_NETWORK_TIMEOUT +@@ -330,7 +330,7 @@ library default of an infinite timeout. Set the network response timeout (default 8). .TP .B LDAP_URI @@ -15,9 +14,7 @@ where <proto> can be ldap or ldaps. The option can be given multiple times. Map entries that include a server name override this option and it is then not used. Default is an empty list in which case either the server given - in a map entry or the LDAP configured default is used. This uri list is read at -@@ -453,6 +453,6 @@ - .BR autofs (8). +@@ -462,5 +462,5 @@ configuration will be used to locate the .BR autofs_ldap_auth.conf (5) .SH AUTHOR This manual page was written by Christoph Lameter <ch...@waterf.org>, @@ -26,8 +23,7 @@ Ian Kent <ra...@themaw.net> . --- a/man/autofs.8.in +++ b/man/autofs.8.in -@@ -43,15 +43,15 @@ - script must be rerun to activate the changes. +@@ -44,8 +44,8 @@ script must be rerun to activate the cha .P .B @@initdir@@/autofs status will display the status of, @@ -38,7 +34,7 @@ .SH "SEE ALSO" .BR automount (8), .BR autofs (5), - .BR auto.master (5). +@@ -53,5 +53,5 @@ will display the status of, .BR autofs_ldap_auth.conf (5) .SH AUTHOR This manual page was written by Christoph Lameter <ch...@waterf.org>, @@ -47,8 +43,7 @@ <h...@transmeta.com>. --- a/man/automount.8 +++ b/man/automount.8 -@@ -156,9 +156,9 @@ - the map in which case they need to umounted manually. +@@ -157,7 +157,7 @@ the map in which case they need to umoun .P If the option to disable the check to see if the daemon is already running is used be aware that autofs currently may not function correctly @@ -57,4 +52,3 @@ 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 diff -Nru autofs-5.0.8/debian/patches/remove-kernel-mount.nfs-version-check.patch autofs-5.0.8/debian/patches/remove-kernel-mount.nfs-version-check.patch --- autofs-5.0.8/debian/patches/remove-kernel-mount.nfs-version-check.patch 2014-03-07 05:16:07.000000000 +0100 +++ autofs-5.0.8/debian/patches/remove-kernel-mount.nfs-version-check.patch 2015-03-11 19:49:44.000000000 +0100 @@ -22,8 +22,7 @@ --- a/daemon/automount.c +++ b/daemon/automount.c -@@ -50,11 +50,8 @@ - const char *libdir = AUTOFS_LIB_DIR; /* Location of library modules */ +@@ -51,9 +51,6 @@ const char *libdir = AUTOFS_LIB_DIR; /* const char *mapdir = AUTOFS_MAP_DIR; /* Location of mount maps */ const char *confdir = AUTOFS_CONF_DIR; /* Location of autofs config file */ @@ -33,9 +32,7 @@ /* autofs fifo name prefix */ const char *fifodir = AUTOFS_FIFO_DIR "/autofs.fifo"; - const char *global_options; /* Global option, from command line */ -@@ -1284,10 +1281,8 @@ - status = pthread_mutex_lock(&mrc.mutex); +@@ -1285,8 +1282,6 @@ static int do_hup_signal(struct master * if (status) fatal(status); @@ -44,9 +41,7 @@ master_mutex_lock(); /* Already doing a map read or shutdown or no mounts */ if (master->reading) { - status = pthread_mutex_unlock(&mrc.mutex); -@@ -1951,10 +1946,8 @@ - program = argv[0]; +@@ -1952,8 +1947,6 @@ int main(int argc, char *argv[]) defaults_read_config(0); @@ -55,11 +50,9 @@ kpkt_len = get_kpkt_len(); timeout = defaults_get_timeout(); ghost = defaults_get_browse_mode(); - logging = defaults_get_logging(); --- a/include/mounts.h +++ b/include/mounts.h -@@ -75,16 +75,9 @@ - struct list_head ordered; +@@ -76,14 +76,7 @@ struct mnt_list { }; @@ -72,13 +65,11 @@ -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); --- a/modules/replicated.c +++ b/modules/replicated.c -@@ -885,11 +885,10 @@ - * greater than 2.6.22 and mount.nfs version is greater than 1.1.1. +@@ -886,9 +886,8 @@ int prune_host_list(unsigned logopt, str * But also allow the MOUNT_WAIT configuration parameter to override * the probing. */ @@ -90,11 +81,9 @@ if (!this) return 1; } else { - if (!this || !this->next) --- a/lib/mounts.c +++ b/lib/mounts.c -@@ -163,8 +163,9 @@ - { +@@ -165,6 +165,7 @@ unsigned int get_kver_minor(void) return kver.minor; } @@ -102,14 +91,11 @@ #ifdef HAVE_MOUNT_NFS static int extract_version(char *start, struct nfs_mount_vers *vers) { - char *s_ver = strchr(start, ' '); -@@ -301,8 +302,9 @@ - { +@@ -303,6 +304,7 @@ int check_nfs_mount_version(struct nfs_m return 0; } #endif +#endif - struct substvar *addstdenv(struct substvar *sv) + static char *set_env_name(const char *prefix, const char *name, char *buf) { - struct substvar *list = sv; diff -Nru autofs-5.0.8/debian/patches/series autofs-5.0.8/debian/patches/series --- autofs-5.0.8/debian/patches/series 2014-03-07 05:16:07.000000000 +0100 +++ autofs-5.0.8/debian/patches/series 2015-03-11 19:49:44.000000000 +0100 @@ -1,4 +1,8 @@ # +# CVE-2014-8169 +CVE-2014-8169-add-a-prefix-to-program-map-stdvars.patch +CVE-2014-8169-add-config-option-to-force-use-of-program-map-stdvars.patch +# # bugfixes forwarded to upstream filagdir.patch #
Description: add a prefix to program map stdvars When a program map uses an interpreted languages like python it is possible to load and execute arbitrary code from a user home directory. This is because the standard environment variables are used to locate and load modules when using these languages. (CVE-2014-8169) . 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. Origin: vendor Author: Ian Kent <ik...@redhat.com> Reviewed-by: Salvatore Bonaccorso <car...@debian.org> Last-Update: 2015-02-28 --- --- 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 @@ -272,7 +272,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 @@ -1223,12 +1223,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; @@ -1238,7 +1238,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; @@ -1246,7 +1246,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);
Description: add config option to force use of program map stdvars Enabling the extended environment (including $HOME, for example) for program maps opens automount(8) to a privilege escalation. . Rather than just removing the entended environment a configuration option is added to disable it by default so that those who wish to use it can do so if they wish. Origin: vendor Author: Ian Kent <ik...@redhat.com> Author: Salvatore Bonaccorso <car...@debian.org> Last-Update: 2015-02-28 --- --- a/include/defaults.h +++ b/include/defaults.h @@ -28,6 +28,7 @@ #define DEFAULT_UMOUNT_WAIT 12 #define DEFAULT_BROWSE_MODE 1 #define DEFAULT_LOGGING 0 +#define DEFAULT_FORCE_STD_PROG_MAP_ENV 0 #define DEFAULT_LDAP_TIMEOUT -1 #define DEFAULT_LDAP_NETWORK_TIMEOUT 8 @@ -62,6 +63,7 @@ unsigned int defaults_get_timeout(void); unsigned int defaults_get_negative_timeout(void); unsigned int defaults_get_browse_mode(void); unsigned int defaults_get_logging(void); +unsigned int defaults_force_std_prog_map_env(void); const char *defaults_get_ldap_server(void); unsigned int defaults_get_ldap_timeout(void); unsigned int defaults_get_ldap_network_timeout(void); --- a/lib/defaults.c +++ b/lib/defaults.c @@ -35,6 +35,7 @@ #define ENV_NAME_NEGATIVE_TIMEOUT "NEGATIVE_TIMEOUT" #define ENV_NAME_BROWSE_MODE "BROWSE_MODE" #define ENV_NAME_LOGGING "LOGGING" +#define ENV_NAME_FORCE_STD_PROG_MAP_ENV "FORCE_STANDARD_PROGRAM_MAP_ENV" #define LDAP_URI "LDAP_URI" #define ENV_LDAP_TIMEOUT "LDAP_TIMEOUT" @@ -519,6 +520,7 @@ unsigned int defaults_read_config(unsign check_set_config_value(key, ENV_NAME_NEGATIVE_TIMEOUT, value, to_syslog) || check_set_config_value(key, ENV_NAME_BROWSE_MODE, value, to_syslog) || check_set_config_value(key, ENV_NAME_LOGGING, value, to_syslog) || + check_set_config_value(key, ENV_NAME_FORCE_STD_PROG_MAP_ENV, value, to_syslog) || check_set_config_value(key, ENV_LDAP_TIMEOUT, value, to_syslog) || check_set_config_value(key, ENV_LDAP_NETWORK_TIMEOUT, value, to_syslog) || check_set_config_value(key, ENV_NAME_MAP_OBJ_CLASS, value, to_syslog) || @@ -629,6 +631,17 @@ unsigned int defaults_get_logging(void) return logging; } +unsigned int defaults_force_std_prog_map_env(void) +{ + int res; + + res = get_env_yesno(ENV_NAME_FORCE_STD_PROG_MAP_ENV); + if (res < 0) + res = DEFAULT_FORCE_STD_PROG_MAP_ENV; + + return res; +} + unsigned int defaults_get_ldap_timeout(void) { int res; --- a/man/autofs.5 +++ b/man/autofs.5 @@ -174,6 +174,11 @@ SHOST Short hostname (domain part remove .fi .RE .sp +If a program map is used these standard environment variables will have +a prefix of "AUTOFS_" to prevent interpreted languages like python from +being able to load and execute arbitray code from a user home directory. +.RE +.sp Additional entries can be defined with the -Dvariable=Value map-option to .BR automount (8). .SS Executable Maps --- a/modules/lookup_program.c +++ b/modules/lookup_program.c @@ -132,6 +132,7 @@ int lookup_mount(struct autofs_point *ap int ret = 1; int distance; int alloci = 1; + char *prefix; source = ap->entry->current; ap->entry->current = NULL; @@ -265,6 +266,17 @@ int lookup_mount(struct autofs_point *ap warn(ap->logopt, MODPREFIX "failed to set PWD to %s for map %s", ap->path, ctxt->mapname); + + /* + * By default use a prefix with standard environment + * variables to prevent system subversion by interpreted + * languages. + */ + if (defaults_force_std_prog_map_env()) + prefix = NULL; + else + prefix = "AUTOFS_"; + /* * MAPFMT_DEFAULT must be "sun" for ->parse_init() to have setup * the macro table. @@ -272,7 +284,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, "AUTOFS_"); + pctxt->subst = addstdenv(pctxt->subst, prefix); macro_setenv(pctxt->subst); } execl(ctxt->mapname, ctxt->mapname, name, NULL); --- a/samples/autofs.conf.default.in +++ b/samples/autofs.conf.default.in @@ -80,6 +80,17 @@ BROWSE_MODE="no" # #LDAP_NETWORK_TIMEOUT=8 # +# FORCE_STANDARD_PROGRAM_MAP_ENV - disable the use of the "AUTOFS_" +# prefix for standard environment variables when +# executing a program map. Since program maps +# are run as the privileded user this opens +# automount(8) to potential user privilege +# escalation when the program map is written +# in a language that can load components from, +# for example, a user home directory. +# +#FORCE_STANDARD_PROGRAM_MAP_ENV="no" +# # Define base dn for map dn lookup. # # SEARCH_BASE - base dn to use for searching for map search dn. --- a/man/auto.master.5.in +++ b/man/auto.master.5.in @@ -250,6 +250,14 @@ options replace the global options (prog .TP .B LOGGING set default log level "none", "verbose" or "debug" (program default "none"). +.TP +.B FORCE_STANDARD_PROGRAM_MAP_ENV +override the use of a prefix with standard environment variables when a +program map is executed. Since program maps are run as the privileded +user setting these standard environment variables opens automount(8) to +potential user privilege escalation when the program map is written in a +language that can load components from, for example, a user home directory +(program default "no"). .SH BUILTIN MAP -hosts If "-hosts" is given as the map then accessing a key under the mount point which corresponds to a hostname will allow access to the exports of that