19701904 problem in UTILITY/BASH s11u2-sru
authorStefan Teleman <stefan.teleman@oracle.com>
Wed, 12 Nov 2014 08:02:05 -0800
branchs11u2-sru
changeset 3463 32e84fd7641c
parent 3461 1240b4c4e38d
child 3465 286faccbf469
19701904 problem in UTILITY/BASH
components/bash/patches/bash41-012.patch
components/bash/patches/bash41-013.patch
components/bash/patches/bash41-014.patch
components/bash/patches/bash41-015.patch
components/bash/patches/bash41-016.patch
components/bash/patches/bash41-017.patch
components/bash/patches/funcdef-import-4.1-CVE-2014-6271.patch
components/bash/patches/parse.y-CVE-2014-7169.patch
components/bash/patches/parser-oob-4.1.patch
components/bash/patches/variables-affix-4.1.patch
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/bash/patches/bash41-012.patch	Wed Nov 12 08:02:05 2014 -0800
@@ -0,0 +1,104 @@
+			     BASH PATCH REPORT
+			     =================
+
+Bash-Release:	4.1
+Patch-ID:	bash41-012
+
+Bug-Reported-by:	Stephane Chazelas <[email protected]>
+Bug-Reference-ID:
+Bug-Reference-URL:
+
+Bug-Description:
+
+Under certain circumstances, bash will execute user code while processing the
+environment for exported function definitions.
+
+Patch (apply with `patch -p0'):
+
+*** ../bash-4.1.11/builtins/common.h	2009-12-22 16:30:42.000000000 -0500
+--- builtins/common.h	2014-09-16 19:27:38.000000000 -0400
+***************
+*** 36,39 ****
+--- 36,41 ----
+  
+  /* Flags for describe_command, shared between type.def and command.def */
++ #define SEVAL_FUNCDEF	0x080		/* only allow function definitions */
++ #define SEVAL_ONECMD	0x100		/* only allow a single command */
+  #define CDESC_ALL		0x001	/* type -a */
+  #define CDESC_SHORTDESC		0x002	/* command -V */
+*** ../bash-4.1.11/builtins/evalstring.c	2009-10-17 21:18:50.000000000 -0400
+--- builtins/evalstring.c	2014-09-16 19:27:38.000000000 -0400
+***************
+*** 262,265 ****
+--- 262,273 ----
+  	      struct fd_bitmap *bitmap;
+  
++ 	      if ((flags & SEVAL_FUNCDEF) && command->type != cm_function_def)
++ 		{
++ 		  internal_warning ("%s: ignoring function definition attempt", from_file);
++ 		  should_jump_to_top_level = 0;
++ 		  last_result = last_command_exit_value = EX_BADUSAGE;
++ 		  break;
++ 		}
++ 
+  	      bitmap = new_fd_bitmap (FD_BITMAP_SIZE);
+  	      begin_unwind_frame ("pe_dispose");
+***************
+*** 322,325 ****
+--- 330,336 ----
+  	      dispose_fd_bitmap (bitmap);
+  	      discard_unwind_frame ("pe_dispose");
++ 
++ 	      if (flags & SEVAL_ONECMD)
++ 		break;
+  	    }
+  	}
+*** ../bash-4.1.11/variables.c	2010-03-26 12:15:39.000000000 -0400
+--- variables.c	2014-09-16 19:27:38.000000000 -0400
+***************
+*** 348,357 ****
+  	  strcpy (temp_string + char_index + 1, string);
+  
+! 	  parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST);
+! 
+! 	  /* Ancient backwards compatibility.  Old versions of bash exported
+! 	     functions like name()=() {...} */
+! 	  if (name[char_index - 1] == ')' && name[char_index - 2] == '(')
+! 	    name[char_index - 2] = '\0';
+  
+  	  if (temp_var = find_function (name))
+--- 348,355 ----
+  	  strcpy (temp_string + char_index + 1, string);
+  
+! 	  /* Don't import function names that are invalid identifiers from the
+! 	     environment. */
+! 	  if (legal_identifier (name))
+! 	    parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST|SEVAL_FUNCDEF|SEVAL_ONECMD);
+  
+  	  if (temp_var = find_function (name))
+***************
+*** 362,369 ****
+  	  else
+  	    report_error (_("error importing function definition for `%s'"), name);
+- 
+- 	  /* ( */
+- 	  if (name[char_index - 1] == ')' && name[char_index - 2] == '\0')
+- 	    name[char_index - 2] = '(';		/* ) */
+  	}
+  #if defined (ARRAY_VARS)
+--- 360,363 ----
+*** ../bash-4.1-patched/patchlevel.h	2009-10-01 16:39:22.000000000 -0400
+--- patchlevel.h	2010-01-14 09:38:08.000000000 -0500
+***************
+*** 26,30 ****
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 11
+  
+  #endif /* _PATCHLEVEL_H_ */
+--- 26,30 ----
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 12
+  
+  #endif /* _PATCHLEVEL_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/bash/patches/bash41-013.patch	Wed Nov 12 08:02:05 2014 -0800
@@ -0,0 +1,43 @@
+			     BASH PATCH REPORT
+			     =================
+
+Bash-Release:	4.1
+Patch-ID:	bash41-013
+
+Bug-Reported-by:	Tavis Ormandy <[email protected]>
+Bug-Reference-ID:
+Bug-Reference-URL:	http://twitter.com/taviso/statuses/514887394294652929
+
+Bug-Description:
+
+Under certain circumstances, bash can incorrectly save a lookahead character and
+return it on a subsequent call, even when reading a new line.
+
+Patch (apply with `patch -p0'):
+
+*** ../bash-4.1.12/parse.y	2011-02-24 19:41:01.000000000 -0500
+--- parse.y	2014-09-25 16:13:57.000000000 -0400
+***************
+*** 2812,2815 ****
+--- 2812,2817 ----
+    word_desc_to_read = (WORD_DESC *)NULL;
+  
++   eol_ungetc_lookahead = 0;
++ 
+    current_token = '\n';		/* XXX */
+    last_read_token = '\n';
+*** ../bash-4.1-patched/patchlevel.h	2009-10-01 16:39:22.000000000 -0400
+--- patchlevel.h	2010-01-14 09:38:08.000000000 -0500
+***************
+*** 26,30 ****
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 12
+  
+  #endif /* _PATCHLEVEL_H_ */
+--- 26,30 ----
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 13
+  
+  #endif /* _PATCHLEVEL_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/bash/patches/bash41-014.patch	Wed Nov 12 08:02:05 2014 -0800
@@ -0,0 +1,217 @@
+			     BASH PATCH REPORT
+			     =================
+
+Bash-Release:	4.1
+Patch-ID:	bash41-014
+
+Bug-Reported-by:	Florian Weimer <[email protected]>
+Bug-Reference-ID:
+Bug-Reference-URL:
+
+Bug-Description:
+
+This patch changes the encoding bash uses for exported functions to avoid
+clashes with shell variables and to avoid depending only on an environment
+variable's contents to determine whether or not to interpret it as a shell
+function.
+
+Patch (apply with `patch -p0'):
+
+*** ../bash-4.1.13/variables.c	2014-09-16 19:27:38.000000000 -0400
+--- variables.c	2014-09-27 20:57:46.000000000 -0400
+***************
+*** 80,83 ****
+--- 80,88 ----
+  #define ifsname(s)	((s)[0] == 'I' && (s)[1] == 'F' && (s)[2] == 'S' && (s)[3] == '\0')
+  
++ #define BASHFUNC_PREFIX		"BASH_FUNC_"
++ #define BASHFUNC_PREFLEN	10	/* == strlen(BASHFUNC_PREFIX */
++ #define BASHFUNC_SUFFIX		"%%"
++ #define BASHFUNC_SUFFLEN	2	/* == strlen(BASHFUNC_SUFFIX) */
++ 
+  extern char **environ;
+  
+***************
+*** 269,273 ****
+  static void dispose_temporary_env __P((sh_free_func_t *));     
+  
+! static inline char *mk_env_string __P((const char *, const char *));
+  static char **make_env_array_from_var_list __P((SHELL_VAR **));
+  static char **make_var_export_array __P((VAR_CONTEXT *));
+--- 274,278 ----
+  static void dispose_temporary_env __P((sh_free_func_t *));     
+  
+! static inline char *mk_env_string __P((const char *, const char *, int));
+  static char **make_env_array_from_var_list __P((SHELL_VAR **));
+  static char **make_var_export_array __P((VAR_CONTEXT *));
+***************
+*** 339,357 ****
+        /* If exported function, define it now.  Don't import functions from
+  	 the environment in privileged mode. */
+!       if (privmode == 0 && read_but_dont_execute == 0 && STREQN ("() {", string, 4))
+  	{
+  	  string_length = strlen (string);
+! 	  temp_string = (char *)xmalloc (3 + string_length + char_index);
+  
+! 	  strcpy (temp_string, name);
+! 	  temp_string[char_index] = ' ';
+! 	  strcpy (temp_string + char_index + 1, string);
+  
+  	  /* Don't import function names that are invalid identifiers from the
+  	     environment. */
+! 	  if (legal_identifier (name))
+! 	    parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST|SEVAL_FUNCDEF|SEVAL_ONECMD);
+  
+! 	  if (temp_var = find_function (name))
+  	    {
+  	      VSETATTR (temp_var, (att_exported|att_imported));
+--- 344,373 ----
+        /* If exported function, define it now.  Don't import functions from
+  	 the environment in privileged mode. */
+!       if (privmode == 0 && read_but_dont_execute == 0 &&
+! 	  STREQN (BASHFUNC_PREFIX, name, BASHFUNC_PREFLEN) &&
+! 	  STREQ (BASHFUNC_SUFFIX, name + char_index - BASHFUNC_SUFFLEN) &&
+! 	  STREQN ("() {", string, 4))
+  	{
++ 	  size_t namelen;
++ 	  char *tname;		/* desired imported function name */
++ 
++ 	  namelen = char_index - BASHFUNC_PREFLEN - BASHFUNC_SUFFLEN;
++ 
++ 	  tname = name + BASHFUNC_PREFLEN;	/* start of func name */
++ 	  tname[namelen] = '\0';		/* now tname == func name */
++ 
+  	  string_length = strlen (string);
+! 	  temp_string = (char *)xmalloc (namelen + string_length + 2);
+  
+! 	  memcpy (temp_string, tname, namelen);
+! 	  temp_string[namelen] = ' ';
+! 	  memcpy (temp_string + namelen + 1, string, string_length + 1);
+  
+  	  /* Don't import function names that are invalid identifiers from the
+  	     environment. */
+! 	  if (absolute_program (tname) == 0 && (posixly_correct == 0 || legal_identifier (tname)))
+! 	    parse_and_execute (temp_string, tname, SEVAL_NONINT|SEVAL_NOHIST|SEVAL_FUNCDEF|SEVAL_ONECMD);
+  
+! 	  if (temp_var = find_function (tname))
+  	    {
+  	      VSETATTR (temp_var, (att_exported|att_imported));
+***************
+*** 359,363 ****
+  	    }
+  	  else
+! 	    report_error (_("error importing function definition for `%s'"), name);
+  	}
+  #if defined (ARRAY_VARS)
+--- 375,382 ----
+  	    }
+  	  else
+! 	    report_error (_("error importing function definition for `%s'"), tname);
+! 
+! 	  /* Restore original suffix */
+! 	  tname[namelen] = BASHFUNC_SUFFIX[0];
+  	}
+  #if defined (ARRAY_VARS)
+***************
+*** 2520,2524 ****
+  
+    INVALIDATE_EXPORTSTR (var);
+!   var->exportstr = mk_env_string (name, value);
+  
+    array_needs_making = 1;
+--- 2539,2543 ----
+  
+    INVALIDATE_EXPORTSTR (var);
+!   var->exportstr = mk_env_string (name, value, 0);
+  
+    array_needs_making = 1;
+***************
+*** 3339,3357 ****
+  
+  static inline char *
+! mk_env_string (name, value)
+       const char *name, *value;
+  {
+!   int name_len, value_len;
+!   char	*p;
+  
+    name_len = strlen (name);
+    value_len = STRLEN (value);
+!   p = (char *)xmalloc (2 + name_len + value_len);
+!   strcpy (p, name);
+!   p[name_len] = '=';
+    if (value && *value)
+!     strcpy (p + name_len + 1, value);
+    else
+!     p[name_len + 1] = '\0';
+    return (p);
+  }
+--- 3358,3397 ----
+  
+  static inline char *
+! mk_env_string (name, value, isfunc)
+       const char *name, *value;
++      int isfunc;
+  {
+!   size_t name_len, value_len;
+!   char	*p, *q;
+  
+    name_len = strlen (name);
+    value_len = STRLEN (value);
+! 
+!   /* If we are exporting a shell function, construct the encoded function
+!      name. */
+!   if (isfunc && value)
+!     {
+!       p = (char *)xmalloc (BASHFUNC_PREFLEN + name_len + BASHFUNC_SUFFLEN + value_len + 2);
+!       q = p;
+!       memcpy (q, BASHFUNC_PREFIX, BASHFUNC_PREFLEN);
+!       q += BASHFUNC_PREFLEN;
+!       memcpy (q, name, name_len);
+!       q += name_len;
+!       memcpy (q, BASHFUNC_SUFFIX, BASHFUNC_SUFFLEN);
+!       q += BASHFUNC_SUFFLEN;
+!     }
+!   else
+!     {
+!       p = (char *)xmalloc (2 + name_len + value_len);
+!       memcpy (p, name, name_len);
+!       q = p + name_len;
+!     }
+! 
+!   q[0] = '=';
+    if (value && *value)
+!     memcpy (q + 1, value, value_len + 1);
+    else
+!     q[1] = '\0';
+! 
+    return (p);
+  }
+***************
+*** 3439,3443 ****
+  	     using the cached exportstr... */
+  	  list[list_index] = USE_EXPORTSTR ? savestring (value)
+! 					   : mk_env_string (var->name, value);
+  
+  	  if (USE_EXPORTSTR == 0)
+--- 3479,3483 ----
+  	     using the cached exportstr... */
+  	  list[list_index] = USE_EXPORTSTR ? savestring (value)
+! 					   : mk_env_string (var->name, value, function_p (var));
+  
+  	  if (USE_EXPORTSTR == 0)
+*** ../bash-4.1-patched/patchlevel.h	2009-10-01 16:39:22.000000000 -0400
+--- patchlevel.h	2010-01-14 09:38:08.000000000 -0500
+***************
+*** 26,30 ****
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 13
+  
+  #endif /* _PATCHLEVEL_H_ */
+--- 26,30 ----
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 14
+  
+  #endif /* _PATCHLEVEL_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/bash/patches/bash41-015.patch	Wed Nov 12 08:02:05 2014 -0800
@@ -0,0 +1,173 @@
+			     BASH PATCH REPORT
+			     =================
+
+Bash-Release:	4.1
+Patch-ID:	bash41-015
+
+Bug-Reported-by:	Florian Weimer <[email protected]>
+Bug-Reference-ID:
+Bug-Reference-URL:
+
+Bug-Description:
+
+There are two local buffer overflows in parse.y that can cause the shell
+to dump core when given many here-documents attached to a single command
+or many nested loops.
+
+Patch (apply with `patch -p0'):
+
+*** ../bash-4.1.14/parse.y	2014-09-27 12:18:25.000000000 -0400
+--- parse.y	2014-09-30 19:36:03.000000000 -0400
+***************
+*** 168,171 ****
+--- 168,174 ----
+  static int reserved_word_acceptable __P((int));
+  static int yylex __P((void));
++ 
++ static void push_heredoc __P((REDIRECT *));
++ static char *mk_alexpansion __P((char *));
+  static int alias_expand_token __P((char *));
+  static int time_command_acceptable __P((void));
+***************
+*** 262,266 ****
+  /* Variables to manage the task of reading here documents, because we need to
+     defer the reading until after a complete command has been collected. */
+! static REDIRECT *redir_stack[10];
+  int need_here_doc;
+  
+--- 265,271 ----
+  /* Variables to manage the task of reading here documents, because we need to
+     defer the reading until after a complete command has been collected. */
+! #define HEREDOC_MAX 16
+! 
+! static REDIRECT *redir_stack[HEREDOC_MAX];
+  int need_here_doc;
+  
+***************
+*** 304,308 ****
+     index is decremented after a case, select, or for command is parsed. */
+  #define MAX_CASE_NEST	128
+! static int word_lineno[MAX_CASE_NEST];
+  static int word_top = -1;
+  
+--- 309,313 ----
+     index is decremented after a case, select, or for command is parsed. */
+  #define MAX_CASE_NEST	128
+! static int word_lineno[MAX_CASE_NEST+1];
+  static int word_top = -1;
+  
+***************
+*** 517,521 ****
+  			  redir.filename = $2;
+  			  $$ = make_redirection (source, r_reading_until, redir, 0);
+! 			  redir_stack[need_here_doc++] = $$;
+  			}
+  	|	NUMBER LESS_LESS WORD
+--- 522,526 ----
+  			  redir.filename = $2;
+  			  $$ = make_redirection (source, r_reading_until, redir, 0);
+! 			  push_heredoc ($$);
+  			}
+  	|	NUMBER LESS_LESS WORD
+***************
+*** 524,528 ****
+  			  redir.filename = $3;
+  			  $$ = make_redirection (source, r_reading_until, redir, 0);
+! 			  redir_stack[need_here_doc++] = $$;
+  			}
+  	|	REDIR_WORD LESS_LESS WORD
+--- 529,533 ----
+  			  redir.filename = $3;
+  			  $$ = make_redirection (source, r_reading_until, redir, 0);
+! 			  push_heredoc ($$);
+  			}
+  	|	REDIR_WORD LESS_LESS WORD
+***************
+*** 531,535 ****
+  			  redir.filename = $3;
+  			  $$ = make_redirection (source, r_reading_until, redir, REDIR_VARASSIGN);
+! 			  redir_stack[need_here_doc++] = $$;
+  			}
+  	|	LESS_LESS_MINUS WORD
+--- 536,540 ----
+  			  redir.filename = $3;
+  			  $$ = make_redirection (source, r_reading_until, redir, REDIR_VARASSIGN);
+! 			  push_heredoc ($$);
+  			}
+  	|	LESS_LESS_MINUS WORD
+***************
+*** 538,542 ****
+  			  redir.filename = $2;
+  			  $$ = make_redirection (source, r_deblank_reading_until, redir, 0);
+! 			  redir_stack[need_here_doc++] = $$;
+  			}
+  	|	NUMBER LESS_LESS_MINUS WORD
+--- 543,547 ----
+  			  redir.filename = $2;
+  			  $$ = make_redirection (source, r_deblank_reading_until, redir, 0);
+! 			  push_heredoc ($$);
+  			}
+  	|	NUMBER LESS_LESS_MINUS WORD
+***************
+*** 545,549 ****
+  			  redir.filename = $3;
+  			  $$ = make_redirection (source, r_deblank_reading_until, redir, 0);
+! 			  redir_stack[need_here_doc++] = $$;
+  			}
+  	|	REDIR_WORD  LESS_LESS_MINUS WORD
+--- 550,554 ----
+  			  redir.filename = $3;
+  			  $$ = make_redirection (source, r_deblank_reading_until, redir, 0);
+! 			  push_heredoc ($$);
+  			}
+  	|	REDIR_WORD  LESS_LESS_MINUS WORD
+***************
+*** 552,556 ****
+  			  redir.filename = $3;
+  			  $$ = make_redirection (source, r_deblank_reading_until, redir, REDIR_VARASSIGN);
+! 			  redir_stack[need_here_doc++] = $$;
+  			}
+  	|	LESS_LESS_LESS WORD
+--- 557,561 ----
+  			  redir.filename = $3;
+  			  $$ = make_redirection (source, r_deblank_reading_until, redir, REDIR_VARASSIGN);
+! 			  push_heredoc ($$);
+  			}
+  	|	LESS_LESS_LESS WORD
+***************
+*** 2508,2511 ****
+--- 2513,2531 ----
+  static int esacs_needed_count;
+  
++ static void
++ push_heredoc (r)
++      REDIRECT *r;
++ {
++   if (need_here_doc >= HEREDOC_MAX)
++     {
++       last_command_exit_value = EX_BADUSAGE;
++       need_here_doc = 0;
++       report_syntax_error (_("maximum here-document count exceeded"));
++       reset_parser ();
++       exit_shell (last_command_exit_value);
++     }
++   redir_stack[need_here_doc++] = r;
++ }
++ 
+  void
+  gather_here_documents ()
+*** ../bash-4.1-patched/patchlevel.h	2009-10-01 16:39:22.000000000 -0400
+--- patchlevel.h	2010-01-14 09:38:08.000000000 -0500
+***************
+*** 26,30 ****
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 14
+  
+  #endif /* _PATCHLEVEL_H_ */
+--- 26,30 ----
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 15
+  
+  #endif /* _PATCHLEVEL_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/bash/patches/bash41-016.patch	Wed Nov 12 08:02:05 2014 -0800
@@ -0,0 +1,59 @@
+			     BASH PATCH REPORT
+			     =================
+
+Bash-Release:	4.1
+Patch-ID:	bash41-016
+
+Bug-Reported-by:	Michal Zalewski <[email protected]>
+Bug-Reference-ID:
+Bug-Reference-URL:
+
+Bug-Description:
+
+When bash is parsing a function definition that contains a here-document
+delimited by end-of-file (or end-of-string), it leaves the closing delimiter
+uninitialized.  This can result in an invalid memory access when the parsed
+function is later copied.
+
+Patch (apply with `patch -p0'):
+
+*** ../bash-4.1.15/make_cmd.c	2009-09-11 17:26:12.000000000 -0400
+--- make_cmd.c	2014-10-02 11:29:35.000000000 -0400
+***************
+*** 690,693 ****
+--- 690,694 ----
+    temp->redirector = source;
+    temp->redirectee = dest_and_filename;
++   temp->here_doc_eof = 0;
+    temp->instruction = instruction;
+    temp->flags = 0;
+*** ../bash-4.1.15/copy_cmd.c	2009-09-11 16:28:02.000000000 -0400
+--- copy_cmd.c	2014-10-02 11:29:35.000000000 -0400
+***************
+*** 127,131 ****
+      case r_reading_until:
+      case r_deblank_reading_until:
+!       new_redirect->here_doc_eof = savestring (redirect->here_doc_eof);
+        /*FALLTHROUGH*/
+      case r_reading_string:
+--- 127,131 ----
+      case r_reading_until:
+      case r_deblank_reading_until:
+!       new_redirect->here_doc_eof = redirect->here_doc_eof ? savestring (redirect->here_doc_eof) : 0;
+        /*FALLTHROUGH*/
+      case r_reading_string:
+*** ../bash-4.1-patched/patchlevel.h	2009-10-01 16:39:22.000000000 -0400
+--- patchlevel.h	2010-01-14 09:38:08.000000000 -0500
+***************
+*** 26,30 ****
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 15
+  
+  #endif /* _PATCHLEVEL_H_ */
+--- 26,30 ----
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 16
+  
+  #endif /* _PATCHLEVEL_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/bash/patches/bash41-017.patch	Wed Nov 12 08:02:05 2014 -0800
@@ -0,0 +1,132 @@
+			     BASH PATCH REPORT
+			     =================
+
+Bash-Release:	4.1
+Patch-ID:	bash41-017
+
+Bug-Reported-by:	Michal Zalewski <[email protected]>
+Bug-Reference-ID:
+Bug-Reference-URL:
+
+Bug-Description:
+
+A combination of nested command substitutions and function importing from
+the environment can cause bash to execute code appearing in the environment
+variable value following the function definition.
+
+Patch (apply with `patch -p0'):
+
+*** ../bash-4.1.16/builtins/evalstring.c	2014-09-16 19:27:38.000000000 -0400
+--- builtins/evalstring.c	2014-10-04 15:08:26.000000000 -0400
+***************
+*** 262,271 ****
+  	      struct fd_bitmap *bitmap;
+  
+! 	      if ((flags & SEVAL_FUNCDEF) && command->type != cm_function_def)
+  		{
+! 		  internal_warning ("%s: ignoring function definition attempt", from_file);
+! 		  should_jump_to_top_level = 0;
+! 		  last_result = last_command_exit_value = EX_BADUSAGE;
+! 		  break;
+  		}
+  
+--- 262,284 ----
+  	      struct fd_bitmap *bitmap;
+  
+! 	      if (flags & SEVAL_FUNCDEF)
+  		{
+! 		  char *x;
+! 
+! 		  /* If the command parses to something other than a straight
+! 		     function definition, or if we have not consumed the entire
+! 		     string, or if the parser has transformed the function
+! 		     name (as parsing will if it begins or ends with shell
+! 		     whitespace, for example), reject the attempt */
+! 		  if (command->type != cm_function_def ||
+! 		      ((x = parser_remaining_input ()) && *x) ||
+! 		      (STREQ (from_file, command->value.Function_def->name->word) == 0))
+! 		    {
+! 		      internal_warning (_("%s: ignoring function definition attempt"), from_file);
+! 		      should_jump_to_top_level = 0;
+! 		      last_result = last_command_exit_value = EX_BADUSAGE;
+! 		      reset_parser ();
+! 		      break;
+! 		    }
+  		}
+  
+***************
+*** 332,336 ****
+  
+  	      if (flags & SEVAL_ONECMD)
+! 		break;
+  	    }
+  	}
+--- 345,352 ----
+  
+  	      if (flags & SEVAL_ONECMD)
+! 		{
+! 		  reset_parser ();
+! 		  break;
+! 		}
+  	    }
+  	}
+*** ../bash-4.1.16/parse.y	2014-09-30 19:36:03.000000000 -0400
+--- parse.y	2014-10-04 15:08:26.000000000 -0400
+***************
+*** 2410,2413 ****
+--- 2410,2423 ----
+  }
+  
++ char *
++ parser_remaining_input ()
++ {
++   if (shell_input_line == 0)
++     return 0;
++   if (shell_input_line_index < 0 || shell_input_line_index >= shell_input_line_len)
++     return '\0';	/* XXX */
++   return (shell_input_line + shell_input_line_index);
++ }
++ 
+  #ifdef INCLUDE_UNUSED
+  /* Back the input pointer up by one, effectively `ungetting' a character. */
+***************
+*** 3809,3814 ****
+    restore_parser_state (&ps);
+    reset_parser ();
+!   if (interactive)
+!     token_to_read = 0;
+  
+    /* Need to find how many characters parse_and_execute consumed, update
+--- 3819,3824 ----
+    restore_parser_state (&ps);
+    reset_parser ();
+! 
+!   token_to_read = 0;
+  
+    /* Need to find how many characters parse_and_execute consumed, update
+*** ../bash-4.1.16/shell.h	2009-08-14 16:32:52.000000000 -0400
+--- shell.h	2014-10-04 15:08:26.000000000 -0400
+***************
+*** 164,167 ****
+--- 164,169 ----
+  
+  /* Let's try declaring these here. */
++ extern char *parser_remaining_input __P((void));
++ 
+  extern sh_parser_state_t *save_parser_state __P((sh_parser_state_t *));
+  extern void restore_parser_state __P((sh_parser_state_t *));
+*** ../bash-4.1-patched/patchlevel.h	2009-10-01 16:39:22.000000000 -0400
+--- patchlevel.h	2010-01-14 09:38:08.000000000 -0500
+***************
+*** 26,30 ****
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 16
+  
+  #endif /* _PATCHLEVEL_H_ */
+--- 26,30 ----
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 17
+  
+  #endif /* _PATCHLEVEL_H_ */
--- a/components/bash/patches/funcdef-import-4.1-CVE-2014-6271.patch	Mon Nov 10 14:45:35 2014 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-# Patch is from the bash project.
-# It is currently embargo'ed (as of 2014-02-23).
-# It will become an official bash patch once the embargo is lifted.
-*** ../bash-4.1.11/builtins/common.h	2009-12-22 16:30:42.000000000 -0500
---- builtins/common.h	2014-09-16 19:27:38.000000000 -0400
-***************
-*** 36,39 ****
---- 36,41 ----
-  
-  /* Flags for describe_command, shared between type.def and command.def */
-+ #define SEVAL_FUNCDEF	0x080		/* only allow function definitions */
-+ #define SEVAL_ONECMD	0x100		/* only allow a single command */
-  #define CDESC_ALL		0x001	/* type -a */
-  #define CDESC_SHORTDESC		0x002	/* command -V */
-*** ../bash-4.1.11/builtins/evalstring.c	2009-10-17 21:18:50.000000000 -0400
---- builtins/evalstring.c	2014-09-16 19:27:38.000000000 -0400
-***************
-*** 262,265 ****
---- 262,273 ----
-  	      struct fd_bitmap *bitmap;
-  
-+ 	      if ((flags & SEVAL_FUNCDEF) && command->type != cm_function_def)
-+ 		{
-+ 		  internal_warning ("%s: ignoring function definition attempt", from_file);
-+ 		  should_jump_to_top_level = 0;
-+ 		  last_result = last_command_exit_value = EX_BADUSAGE;
-+ 		  break;
-+ 		}
-+ 
-  	      bitmap = new_fd_bitmap (FD_BITMAP_SIZE);
-  	      begin_unwind_frame ("pe_dispose");
-***************
-*** 322,325 ****
---- 330,336 ----
-  	      dispose_fd_bitmap (bitmap);
-  	      discard_unwind_frame ("pe_dispose");
-+ 
-+ 	      if (flags & SEVAL_ONECMD)
-+ 		break;
-  	    }
-  	}
-*** ../bash-4.1.11/variables.c	2010-03-26 12:15:39.000000000 -0400
---- variables.c	2014-09-16 19:27:38.000000000 -0400
-***************
-*** 348,357 ****
-  	  strcpy (temp_string + char_index + 1, string);
-  
-! 	  parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST);
-! 
-! 	  /* Ancient backwards compatibility.  Old versions of bash exported
-! 	     functions like name()=() {...} */
-! 	  if (name[char_index - 1] == ')' && name[char_index - 2] == '(')
-! 	    name[char_index - 2] = '\0';
-  
-  	  if (temp_var = find_function (name))
---- 348,355 ----
-  	  strcpy (temp_string + char_index + 1, string);
-  
-! 	  /* Don't import function names that are invalid identifiers from the
-! 	     environment. */
-! 	  if (legal_identifier (name))
-! 	    parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST|SEVAL_FUNCDEF|SEVAL_ONECMD);
-  
-  	  if (temp_var = find_function (name))
-***************
-*** 362,369 ****
-  	  else
-  	    report_error (_("error importing function definition for `%s'"), name);
-- 
-- 	  /* ( */
-- 	  if (name[char_index - 1] == ')' && name[char_index - 2] == '\0')
-- 	    name[char_index - 2] = '(';		/* ) */
-  	}
-  #if defined (ARRAY_VARS)
---- 360,363 ----
-
--- a/components/bash/patches/parse.y-CVE-2014-7169.patch	Mon Nov 10 14:45:35 2014 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-# Patch is from Chet Ramey (Bash Project Lead);
-# http://www.openwall.com/lists/oss-security/2014/09/25/10
-# This will become an official bash patch.
-*** ../bash-20140912/parse.y	2014-08-26 15:09:42.000000000 -0400
---- parse.y	2014-09-24 22:47:28.000000000 -0400
-***************
-*** 2959,2962 ****
---- 2959,2964 ----
-    word_desc_to_read = (WORD_DESC *)NULL;
-  
-+   eol_ungetc_lookahead = 0;
-+ 
-    current_token = '\n';		/* XXX */
-    last_read_token = '\n';
-
--- a/components/bash/patches/parser-oob-4.1.patch	Mon Nov 10 14:45:35 2014 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-# Patch Origin: http://www.openwall.com/lists/oss-security/2014/09/26/2
-# Patch is from Red Hat Security.
-# Assigned CVE-2014-7186 and CVE-2014-7187
-# CVSS Score: 4.6
---- ../bash-4.1.orig/parse.y	2014-09-25 08:10:49.809021000 -0700
-+++ parse.y	2014-09-25 11:33:15.596573700 -0700
-@@ -261,9 +261,21 @@
- 
- /* Variables to manage the task of reading here documents, because we need to
-    defer the reading until after a complete command has been collected. */
--static REDIRECT *redir_stack[10];
-+static REDIRECT **redir_stack;
- int need_here_doc;
- 
-+/* Pushes REDIR onto redir_stack, resizing it as needed. */
-+static void
-+push_redir_stack (REDIRECT *redir)
-+{
-+  /* Guard against oveflow. */
-+  if (need_here_doc + 1 > INT_MAX / sizeof (*redir_stack))
-+    abort ();
-+  redir_stack = xrealloc (redir_stack,
-+             (need_here_doc + 1) * sizeof (*redir_stack));
-+  redir_stack[need_here_doc++] = redir;
-+}
-+
- /* Where shell input comes from.  History expansion is performed on each
-    line when the shell is interactive. */
- static char *shell_input_line = (char *)NULL;
-@@ -516,42 +528,42 @@
- 			  source.dest = 0;
- 			  redir.filename = $2;
- 			  $$ = make_redirection (source, r_reading_until, redir, 0);
--			  redir_stack[need_here_doc++] = $$;
-+                          push_redir_stack ($$);
- 			}
- 	|	NUMBER LESS_LESS WORD
- 			{
- 			  source.dest = $1;
- 			  redir.filename = $3;
- 			  $$ = make_redirection (source, r_reading_until, redir, 0);
--			  redir_stack[need_here_doc++] = $$;
-+                          push_redir_stack ($$);
- 			}
- 	|	REDIR_WORD LESS_LESS WORD
- 			{
- 			  source.filename = $1;
- 			  redir.filename = $3;
- 			  $$ = make_redirection (source, r_reading_until, redir, REDIR_VARASSIGN);
--			  redir_stack[need_here_doc++] = $$;
-+                          push_redir_stack ($$);
- 			}
- 	|	LESS_LESS_MINUS WORD
- 			{
- 			  source.dest = 0;
- 			  redir.filename = $2;
- 			  $$ = make_redirection (source, r_deblank_reading_until, redir, 0);
--			  redir_stack[need_here_doc++] = $$;
-+                          push_redir_stack ($$);
- 			}
- 	|	NUMBER LESS_LESS_MINUS WORD
- 			{
- 			  source.dest = $1;
- 			  redir.filename = $3;
- 			  $$ = make_redirection (source, r_deblank_reading_until, redir, 0);
--			  redir_stack[need_here_doc++] = $$;
-+                          push_redir_stack ($$);
- 			}
- 	|	REDIR_WORD  LESS_LESS_MINUS WORD
- 			{
- 			  source.filename = $1;
- 			  redir.filename = $3;
- 			  $$ = make_redirection (source, r_deblank_reading_until, redir, REDIR_VARASSIGN);
--			  redir_stack[need_here_doc++] = $$;
-+                          push_redir_stack ($$);
- 			}
- 	|	LESS_LESS_LESS WORD
- 			{
-@@ -4677,7 +4689,7 @@
-     case CASE:
-     case SELECT:
-     case FOR:
--      if (word_top < MAX_CASE_NEST)
-+      if ((word_top + 1) < MAX_CASE_NEST)
- 	word_top++;
-       word_lineno[word_top] = line_number;
-       break;
--- a/components/bash/patches/variables-affix-4.1.patch	Mon Nov 10 14:45:35 2014 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,153 +0,0 @@
-# Patch Origin: http://www.openwall.com/lists/oss-security/2014/09/25/32
-# Patch is from Red Hat Security.
-# CVE-2014-7619
-# CVSS Score:10.0
-# This is an update to the previously released patchset for the same
-# vulnerability. The previous patch did NOT cover all possible attack
-# vectors.
---- ../bash-4.1.orig/variables.c	2014-09-25 08:10:49.920709400 -0700
-+++ variables.c	2014-09-25 11:59:38.642742000 -0700
-@@ -268,7 +268,7 @@
- static void propagate_temp_var __P((PTR_T));
- static void dispose_temporary_env __P((sh_free_func_t *));     
- 
--static inline char *mk_env_string __P((const char *, const char *));
-+static inline char *mk_env_string __P((const char *, const char *, int));
- static char **make_env_array_from_var_list __P((SHELL_VAR **));
- static char **make_var_export_array __P((VAR_CONTEXT *));
- static char **make_func_export_array __P((void));
-@@ -301,6 +301,14 @@
- #endif
- }
- 
-+/* Prefix and suffix for environment variable names which contain
-+   shell functions. */
-+#define FUNCDEF_PREFIX "BASH_FUNC_"
-+#define FUNCDEF_PREFIX_LEN (strlen (FUNCDEF_PREFIX))
-+#define FUNCDEF_SUFFIX "()"
-+#define FUNCDEF_SUFFIX_LEN (strlen (FUNCDEF_SUFFIX))
-+
-+
- /* Initialize the shell variables from the current environment.
-    If PRIVMODE is nonzero, don't import functions from ENV or
-    parse $SHELLOPTS. */
-@@ -338,27 +346,39 @@
- 
-       /* If exported function, define it now.  Don't import functions from
- 	 the environment in privileged mode. */
--      if (privmode == 0 && read_but_dont_execute == 0 && STREQN ("() {", string, 4))
--	{
--	  string_length = strlen (string);
--	  temp_string = (char *)xmalloc (3 + string_length + char_index);
-+      if (privmode == 0 && read_but_dont_execute == 0
-+          && STREQN (FUNCDEF_PREFIX, name, FUNCDEF_PREFIX_LEN)
-+          && STREQ (name + char_index - FUNCDEF_SUFFIX_LEN, FUNCDEF_SUFFIX)
-+          && STREQN ("() {", string, 4))
-+	{
-+          size_t name_length
-+            = char_index - (FUNCDEF_PREFIX_LEN + FUNCDEF_SUFFIX_LEN);
-+          char *temp_name = name + FUNCDEF_PREFIX_LEN;
-+          /* Temporarily remove the suffix. */
-+          temp_name[name_length] = '\0';
- 
--	  strcpy (temp_string, name);
--	  temp_string[char_index] = ' ';
--	  strcpy (temp_string + char_index + 1, string);
-+	  string_length = strlen (string);
-+	  temp_string = (char *)xmalloc (name_length + 1 + string_length + 1);
-+          memcpy (temp_string, temp_name, name_length);
-+          temp_string[name_length] = ' ';
-+          memcpy (temp_string + name_length + 1, string, string_length + 1);
- 
- 	  /* Don't import function names that are invalid identifiers from the
- 	     environment. */
--	  if (legal_identifier (name))
--	    parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST|SEVAL_FUNCDEF|SEVAL_ONECMD);
-+	  if (legal_identifier (temp_name))
-+	    parse_and_execute (temp_string, temp_name,
-+                SEVAL_NONINT|SEVAL_NOHIST|SEVAL_FUNCDEF|SEVAL_ONECMD);
- 
--	  if (temp_var = find_function (name))
-+	  if (temp_var = find_function (temp_name))
- 	    {
- 	      VSETATTR (temp_var, (att_exported|att_imported));
- 	      array_needs_making = 1;
- 	    }
- 	  else
- 	    report_error (_("error importing function definition for `%s'"), name);
-+
-+          /* Restore the original suffix. */
-+          temp_name[name_length] = FUNCDEF_SUFFIX[0];
- 	}
- #if defined (ARRAY_VARS)
- #  if 0
-@@ -2515,7 +2535,7 @@
-   var->context = variable_context;	/* XXX */
- 
-   INVALIDATE_EXPORTSTR (var);
--  var->exportstr = mk_env_string (name, value);
-+  var->exportstr = mk_env_string (name, value, 0);
- 
-   array_needs_making = 1;
- 
-@@ -3333,22 +3353,43 @@
- /*								    */
- /* **************************************************************** */
- 
-+/* Returns the string NAME=VALUE if !FUNCTIONP or if VALUE == NULL (in
-+   which case it is treated as empty).  Otherwise, decorate NAME with
-+   FUNCDEF_PREFIX and FUNCDEF_SUFFIX, and return a string of the form
-+   FUNCDEF_PREFIX NAME FUNCDEF_SUFFIX = VALUE (without spaces).  */
- static inline char *
--mk_env_string (name, value)
-+mk_env_string (name, value, functionp)
-      const char *name, *value;
-+     int functionp;
- {
--  int name_len, value_len;
--  char	*p;
-+  size_t name_len, value_len;
-+  char	*p, *q;
- 
-   name_len = strlen (name);
-   value_len = STRLEN (value);
--  p = (char *)xmalloc (2 + name_len + value_len);
--  strcpy (p, name);
--  p[name_len] = '=';
-+  if (functionp && value != NULL)
-+  {
-+    p = (char *)xmalloc (FUNCDEF_PREFIX_LEN + name_len + FUNCDEF_SUFFIX_LEN
-+        + 1 + value_len + 1);
-+    q = p;
-+    memcpy (q, FUNCDEF_PREFIX, FUNCDEF_PREFIX_LEN);
-+    q += FUNCDEF_PREFIX_LEN;
-+    memcpy (q, name, name_len);
-+    q += name_len;
-+    memcpy (q, FUNCDEF_SUFFIX, FUNCDEF_SUFFIX_LEN);
-+    q += FUNCDEF_SUFFIX_LEN;
-+  }
-+  else
-+  {
-+    p = (char *)xmalloc (name_len + 1 + value_len + 1);
-+    memcpy (p, name, name_len);
-+    q = p + name_len;
-+  }
-+  q[0] = '=';
-   if (value && *value)
--    strcpy (p + name_len + 1, value);
-+    memcpy (q + 1, value, value_len + 1);
-   else
--    p[name_len + 1] = '\0';
-+    q[1] = '\0';
-   return (p);
- }
- 
-@@ -3434,7 +3475,7 @@
- 	  /* Gee, I'd like to get away with not using savestring() if we're
- 	     using the cached exportstr... */
- 	  list[list_index] = USE_EXPORTSTR ? savestring (value)
--					   : mk_env_string (var->name, value);
-+            : mk_env_string (var->name, value, function_p (var));
- 
- 	  if (USE_EXPORTSTR == 0)
- 	    SAVE_EXPORTSTR (var, list[list_index]);