--- Begin Message ---
Source: autofs
Version: 5.0.8-1
Severity: important
Tags: security upstream patch
Hi,
the following vulnerability was published for autofs.
CVE-2014-8169[0]:
priv escalation via interpreter load path for program based automount maps
If you fix the vulnerability please also make sure to include the
CVE (Common Vulnerabilities & Exposures) id in your changelog entry.
For further information see:
[0] https://security-tracker.debian.org/tracker/CVE-2014-8169
[1] https://bugzilla.redhat.com/show_bug.cgi?id=1192565
Attached are the backported patches for 5.0.8, lightly tested but a
second pair of eyes to review would be welcome.
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-02-28 23:11:25.000000000 +0100
@@ -1,3 +1,21 @@
+autofs (5.0.8-1.1) unstable; urgency=high
+
+ * Non-maintainer upload by the Security Team.
+ * 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 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.
+ Additionally a configuration option to force the use of program map
+ standard environment variables is added
+ (FORCE_STANDARD_PROGRAM_MAP_ENV).
+ * Refresh remove-kernel-mount.nfs-version-check.patch patch
+ * Refresh manpages-hyphen.patch patch
+
+ -- Salvatore Bonaccorso <[email protected]> Sat, 28 Feb 2015 20:23:20 +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-02-28 23:11:25.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 <[email protected]>
+Reviewed-by: Salvatore Bonaccorso <[email protected]>
+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-02-28 23:11:25.000000000 +0100
@@ -0,0 +1,137 @@
+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 <[email protected]>
+Author: Salvatore Bonaccorso <[email protected]>
+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.
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-02-28 23:11:25.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,11 +96,9 @@
.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).
+@@ -250,8 +250,8 @@ options replace the global options (prog
.TP
.B LOGGING
set default log level "none", "verbose" or "debug" (program default "none").
@@ -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.
+@@ -260,7 +260,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/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-02-28 23:11:25.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-02-28 23:11:25.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
#
@@ -15,3 +19,4 @@
link-daemon-with-lpthread.patch
fix-ldflags.patch
remove-kernel-mount.nfs-version-check.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 <[email protected]>
Reviewed-by: Salvatore Bonaccorso <[email protected]>
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 <[email protected]>
Author: Salvatore Bonaccorso <[email protected]>
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.
--- End Message ---