Hello community, here is the log from the commit of package autofs for openSUSE:Factory checked in at 2015-03-05 15:34:43 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/autofs (Old) and /work/SRC/openSUSE:Factory/.autofs.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "autofs" Changes: -------- --- /work/SRC/openSUSE:Factory/autofs/autofs.changes 2015-02-20 12:00:52.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.autofs.new/autofs.changes 2015-03-05 18:15:33.000000000 +0100 @@ -1,0 +2,9 @@ +Tue Mar 3 10:56:48 CET 2015 - mszer...@suse.cz + +- prevent potential privilege escalation via interpreter load path + for program-based automount maps, add the following patches: + autofs-5.1.0-add-a-prefix-to-program-map-stdvars.patch + autofs-5.1.0-add-config-option-to-force-use-of-program-map-stdvars.patch + (bnc#917977 CVE-2014-8169) + +------------------------------------------------------------------- New: ---- autofs-5.1.0-add-a-prefix-to-program-map-stdvars.patch autofs-5.1.0-add-config-option-to-force-use-of-program-map-stdvars.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ autofs.spec ++++++ --- /var/tmp/diff_new_pack.hvUEVj/_old 2015-03-05 18:15:33.000000000 +0100 +++ /var/tmp/diff_new_pack.hvUEVj/_new 2015-03-05 18:15:33.000000000 +0100 @@ -1,7 +1,7 @@ # # spec file for package autofs # -# Copyright (c) 2015 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -80,6 +80,8 @@ # PATCH-FIX-UPSTREAM autofs-5.1.0-task-use-after-free.patch [bnc#727392] Patch82: autofs-5.0.9-task-use-after-free.patch Patch83: autofs-5.1.0-dont-pass-sloppy-option-for-other-than-nfs-mounts.patch +Patch84: autofs-5.1.0-add-a-prefix-to-program-map-stdvars.patch +Patch85: autofs-5.1.0-add-config-option-to-force-use-of-program-map-stdvars.patch # PATCH-FIX-OPENSUSE autofs-5.0.9-suse-auto_master_default.patch Patch100: autofs-5.0.9-suse-auto_master_default.patch # PATCH-EXTEND-OPENSUSE autofs-5.0.8-dbus-udisks-monitor.patch @@ -108,6 +110,8 @@ # %patch82 -p1 %patch83 -p1 +%patch84 -p1 +%patch85 -p1 %patch100 -p1 %patch102 -p0 -b .udisks %patch200 -p1 ++++++ autofs-5.1.0-add-a-prefix-to-program-map-stdvars.patch ++++++ autofs-5.1.0 - add a prefix to program map stdvars From: Ian Kent <ik...@redhat.com> 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 @@ -87,8 +87,8 @@ extern unsigned int nfs_mount_uses_strin 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); --- 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 @@ -316,7 +317,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; @@ -331,14 +386,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); @@ -346,7 +401,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); } } @@ -354,16 +410,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 @@ -181,7 +181,7 @@ static char *lookup_one(struct autofs_po 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); ++++++ autofs-5.1.0-add-config-option-to-force-use-of-program-map-stdvars.patch ++++++ autofs-5.1.0 - add config option to force use of program map stdvars From: Ian Kent <ik...@redhat.com> 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. --- include/defaults.h | 2 ++ lib/defaults.c | 12 ++++++++++++ man/autofs.5 | 5 +++++ man/autofs.conf.5.in | 9 +++++++++ modules/lookup_program.c | 14 +++++++++++++- redhat/autofs.conf.default.in | 11 +++++++++++ samples/autofs.conf.default.in | 11 +++++++++++ 7 files changed, 63 insertions(+), 1 deletion(-) --- a/include/defaults.h +++ b/include/defaults.h @@ -30,6 +30,7 @@ #define DEFAULT_UMOUNT_WAIT "12" #define DEFAULT_BROWSE_MODE "1" #define DEFAULT_LOGGING "none" +#define DEFAULT_FORCE_STD_PROG_MAP_ENV "0" #define DEFAULT_LDAP_TIMEOUT "-1" #define DEFAULT_LDAP_NETWORK_TIMEOUT "8" @@ -151,6 +152,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 @@ -50,6 +50,7 @@ #define NAME_NEGATIVE_TIMEOUT "negative_timeout" #define NAME_BROWSE_MODE "browse_mode" #define NAME_LOGGING "logging" +#define NAME_FORCE_STD_PROG_MAP_ENV "force_standard_program_map_env" #define NAME_LDAP_URI "ldap_uri" #define NAME_LDAP_TIMEOUT "ldap_timeout" @@ -1571,6 +1572,17 @@ unsigned int defaults_get_logging(void) return logging; } +unsigned int defaults_force_std_prog_map_env(void) +{ + int res; + + res = conf_get_yesno(autofs_gbl_sec, NAME_FORCE_STD_PROG_MAP_ENV); + if (res < 0) + res = atoi(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 @@ -190,6 +190,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/man/autofs.conf.5.in +++ b/man/autofs.conf.5.in @@ -71,6 +71,15 @@ options replace the global options (prog .B logging .br set default log level "none", "verbose" or "debug" (program default "none"). +.TP +.B force_standard_program_map_env +.br +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"). .SS LDAP Configuration .P Configuration settings available are: --- a/modules/lookup_program.c +++ b/modules/lookup_program.c @@ -129,6 +129,7 @@ static char *lookup_one(struct autofs_po int distance; int alloci = 1; int status; + char *prefix; mapent = (char *) malloc(MAPENT_MAX_LEN + 1); if (!mapent) { @@ -174,6 +175,17 @@ static char *lookup_one(struct autofs_po 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. @@ -181,7 +193,7 @@ static char *lookup_one(struct autofs_po 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/redhat/autofs.conf.default.in +++ b/redhat/autofs.conf.default.in @@ -53,6 +53,17 @@ mount_nfs_default_protocol = 4 # #logging = none # +# force_standard_program_map_env - disable the use of the "AUTOFS_" +# prefix for standard environemt 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. # # Define server URIs --- a/samples/autofs.conf.default.in +++ b/samples/autofs.conf.default.in @@ -52,6 +52,17 @@ browse_mode = no # #logging = none # +# force_standard_program_map_env - disable the use of the "AUTOFS_" +# prefix for standard environemt 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. # # Define server URIs -- To unsubscribe, e-mail: opensuse-commit+unsubscr...@opensuse.org For additional commands, e-mail: opensuse-commit+h...@opensuse.org