From 210f4b086a4df1740738b422382888f7dd58f86c Mon Sep 17 00:00:00 2001 From: Jay Freeman Date: Wed, 3 Dec 2014 08:55:56 +0000 Subject: Updated to the latest bash 4.0 patch level. git-svn-id: http://svn.telesphoreo.org/trunk@798 514c082c-b64e-11dc-b46d-3d985efe055d --- data/bash/_metadata/version | 2 +- data/bash/bash40-040 | 19 +--- data/bash/bash40-041 | 217 ++++++++++++++++++++++++++++++++++++++++++++ data/bash/bash40-042 | 147 ++++++++++++++++++++++++++++++ data/bash/bash40-043 | 59 ++++++++++++ data/bash/bash40-044 | 140 ++++++++++++++++++++++++++++ 6 files changed, 565 insertions(+), 19 deletions(-) create mode 100644 data/bash/bash40-041 create mode 100644 data/bash/bash40-042 create mode 100644 data/bash/bash40-043 create mode 100644 data/bash/bash40-044 diff --git a/data/bash/_metadata/version b/data/bash/_metadata/version index 266f85706..e2cdb5695 100644 --- a/data/bash/_metadata/version +++ b/data/bash/_metadata/version @@ -1 +1 @@ -4.0.40 +4.0.44 diff --git a/data/bash/bash40-040 b/data/bash/bash40-040 index a8ae2c577..b15f7500c 100644 --- a/data/bash/bash40-040 +++ b/data/bash/bash40-040 @@ -4,7 +4,7 @@ Bash-Release: 4.0 Patch-ID: bash40-040 -Bug-Reported-by: Tavis Ormandy +Bug-Reported-by: Tavis Ormandy Bug-Reference-ID: Bug-Reference-URL: http://twitter.com/taviso/statuses/514887394294652929 @@ -26,23 +26,6 @@ Patch (apply with `patch -p0'): + current_token = '\n'; /* XXX */ last_read_token = '\n'; -*** ../bash-4.0.39/y.tab.c 2009-01-08 09:30:24.000000000 -0500 ---- y.tab.c 2014-09-25 20:27:08.000000000 -0400 -*************** -*** 4927,4930 **** ---- 4927,4932 ---- - word_desc_to_read = (WORD_DESC *)NULL; - -+ eol_ungetc_lookahead = 0; -+ - last_read_token = '\n'; - token_to_read = '\n'; -*************** -*** 7910,7912 **** - } - #endif /* HANDLE_MULTIBYTE */ -- ---- 7912,7913 ---- *** ../bash-4.0/patchlevel.h 2009-01-04 14:32:40.000000000 -0500 --- patchlevel.h 2009-02-22 16:11:31.000000000 -0500 *************** diff --git a/data/bash/bash40-041 b/data/bash/bash40-041 new file mode 100644 index 000000000..5e15c9461 --- /dev/null +++ b/data/bash/bash40-041 @@ -0,0 +1,217 @@ + BASH PATCH REPORT + ================= + +Bash-Release: 4.0 +Patch-ID: bash40-041 + +Bug-Reported-by: Florian Weimer +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: + +*** ../bash-4.0.40/variables.c 2014-09-16 19:20:48.000000000 -0400 +--- variables.c 2014-09-27 21:01:42.000000000 -0400 +*************** +*** 78,81 **** +--- 78,86 ---- + #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; + +*************** +*** 265,269 **** + 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 *)); +--- 270,274 ---- + 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 *)); +*************** +*** 335,353 **** + /* 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)); +--- 340,369 ---- + /* 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)); +*************** +*** 355,359 **** + } + else +! report_error (_("error importing function definition for `%s'"), name); + } + #if defined (ARRAY_VARS) +--- 371,378 ---- + } + else +! report_error (_("error importing function definition for `%s'"), tname); +! +! /* Restore original suffix */ +! tname[namelen] = BASHFUNC_SUFFIX[0]; + } + #if defined (ARRAY_VARS) +*************** +*** 2506,2510 **** + + INVALIDATE_EXPORTSTR (var); +! var->exportstr = mk_env_string (name, value); + + array_needs_making = 1; +--- 2525,2529 ---- + + INVALIDATE_EXPORTSTR (var); +! var->exportstr = mk_env_string (name, value, 0); + + array_needs_making = 1; +*************** +*** 3325,3343 **** + + 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); + } +--- 3344,3383 ---- + + 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); + } +*************** +*** 3420,3424 **** + using the cached exportstr... */ + list[list_index] = USE_EXPORTSTR ? savestring (value) +! : mk_env_string (var->name, value); + + if (USE_EXPORTSTR == 0) +--- 3460,3464 ---- + 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.0/patchlevel.h 2009-01-04 14:32:40.000000000 -0500 +--- patchlevel.h 2009-02-22 16:11:31.000000000 -0500 +*************** +*** 26,30 **** + looks for to find the patch level (for the sccs version string). */ + +! #define PATCHLEVEL 40 + + #endif /* _PATCHLEVEL_H_ */ +--- 26,30 ---- + looks for to find the patch level (for the sccs version string). */ + +! #define PATCHLEVEL 41 + + #endif /* _PATCHLEVEL_H_ */ diff --git a/data/bash/bash40-042 b/data/bash/bash40-042 new file mode 100644 index 000000000..c86e9a5d7 --- /dev/null +++ b/data/bash/bash40-042 @@ -0,0 +1,147 @@ + BASH PATCH REPORT + ================= + +Bash-Release: 4.0 +Patch-ID: bash40-042 + +Bug-Reported-by: Florian Weimer +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: + +*** ../bash-4.0.41/parse.y 2014-09-27 12:17:56.000000000 -0400 +--- parse.y 2014-09-30 19:41:09.000000000 -0400 +*************** +*** 167,170 **** +--- 167,173 ---- + 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; + +*************** +*** 301,305 **** + 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; + +--- 306,310 ---- + 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; + +*************** +*** 452,456 **** + redir.filename = $2; + $$ = make_redirection (0, r_reading_until, redir); +! redir_stack[need_here_doc++] = $$; + } + | NUMBER LESS_LESS WORD +--- 457,461 ---- + redir.filename = $2; + $$ = make_redirection (0, r_reading_until, redir); +! push_heredoc ($$); + } + | NUMBER LESS_LESS WORD +*************** +*** 458,462 **** + redir.filename = $3; + $$ = make_redirection ($1, r_reading_until, redir); +! redir_stack[need_here_doc++] = $$; + } + | LESS_LESS_LESS WORD +--- 463,467 ---- + redir.filename = $3; + $$ = make_redirection ($1, r_reading_until, redir); +! push_heredoc ($$); + } + | LESS_LESS_LESS WORD +*************** +*** 515,519 **** + $$ = make_redirection + (0, r_deblank_reading_until, redir); +! redir_stack[need_here_doc++] = $$; + } + | NUMBER LESS_LESS_MINUS WORD +--- 520,524 ---- + $$ = make_redirection + (0, r_deblank_reading_until, redir); +! push_heredoc ($$); + } + | NUMBER LESS_LESS_MINUS WORD +*************** +*** 522,526 **** + $$ = make_redirection + ($1, r_deblank_reading_until, redir); +! redir_stack[need_here_doc++] = $$; + } + | GREATER_AND '-' +--- 527,531 ---- + $$ = make_redirection + ($1, r_deblank_reading_until, redir); +! push_heredoc ($$); + } + | GREATER_AND '-' +*************** +*** 2377,2380 **** +--- 2382,2400 ---- + 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.0/patchlevel.h 2009-01-04 14:32:40.000000000 -0500 +--- patchlevel.h 2009-02-22 16:11:31.000000000 -0500 +*************** +*** 26,30 **** + looks for to find the patch level (for the sccs version string). */ + +! #define PATCHLEVEL 41 + + #endif /* _PATCHLEVEL_H_ */ +--- 26,30 ---- + looks for to find the patch level (for the sccs version string). */ + +! #define PATCHLEVEL 42 + + #endif /* _PATCHLEVEL_H_ */ diff --git a/data/bash/bash40-043 b/data/bash/bash40-043 new file mode 100644 index 000000000..0ebacfb68 --- /dev/null +++ b/data/bash/bash40-043 @@ -0,0 +1,59 @@ + BASH PATCH REPORT + ================= + +Bash-Release: 4.0 +Patch-ID: bash40-043 + +Bug-Reported-by: Michal Zalewski +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.0.42/make_cmd.c 2009-01-04 14:32:38.000000000 -0500 +--- make_cmd.c 2014-10-02 11:36:55.000000000 -0400 +*************** +*** 681,684 **** +--- 681,685 ---- + temp->redirector = source; + temp->redirectee = dest_and_filename; ++ temp->here_doc_eof = 0; + temp->instruction = instruction; + temp->flags = 0; +*** ../bash-4.0.42/copy_cmd.c 2009-01-04 14:32:23.000000000 -0500 +--- copy_cmd.c 2014-10-02 11:36:55.000000000 -0400 +*************** +*** 119,123 **** + case r_reading_until: + case r_deblank_reading_until: +! new_redirect->here_doc_eof = savestring (redirect->here_doc_eof); + /*FALLTHROUGH*/ + case r_reading_string: +--- 119,123 ---- + 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.0/patchlevel.h 2009-01-04 14:32:40.000000000 -0500 +--- patchlevel.h 2009-02-22 16:11:31.000000000 -0500 +*************** +*** 26,30 **** + looks for to find the patch level (for the sccs version string). */ + +! #define PATCHLEVEL 42 + + #endif /* _PATCHLEVEL_H_ */ +--- 26,30 ---- + looks for to find the patch level (for the sccs version string). */ + +! #define PATCHLEVEL 43 + + #endif /* _PATCHLEVEL_H_ */ diff --git a/data/bash/bash40-044 b/data/bash/bash40-044 new file mode 100644 index 000000000..06c9abeab --- /dev/null +++ b/data/bash/bash40-044 @@ -0,0 +1,140 @@ + BASH PATCH REPORT + ================= + +Bash-Release: 4.0 +Patch-ID: bash40-044 + +Bug-Reported-by: Michal Zalewski +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: + +*** ../bash-4.0.43/builtins/evalstring.c 2014-09-16 19:20:48.000000000 -0400 +--- builtins/evalstring.c 2014-10-04 15:33:32.000000000 -0400 +*************** +*** 44,47 **** +--- 44,48 ---- + #include "../redir.h" + #include "../trap.h" ++ #include "../bashintl.h" + + #include +*************** +*** 259,268 **** + 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; + } + +--- 260,282 ---- + 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; +! } + } + +*************** +*** 329,333 **** + + if (flags & SEVAL_ONECMD) +! break; + } + } +--- 343,350 ---- + + if (flags & SEVAL_ONECMD) +! { +! reset_parser (); +! break; +! } + } + } +*** ../bash-4.0.43/parse.y 2014-09-30 19:41:09.000000000 -0400 +--- parse.y 2014-10-04 15:27:12.000000000 -0400 +*************** +*** 2279,2282 **** +--- 2279,2292 ---- + } + ++ 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. */ +*************** +*** 3628,3633 **** + restore_parser_state (&ps); + reset_parser (); +! if (interactive) +! token_to_read = 0; + + /* Need to find how many characters parse_and_execute consumed, update +--- 3638,3643 ---- + restore_parser_state (&ps); + reset_parser (); +! +! token_to_read = 0; + + /* Need to find how many characters parse_and_execute consumed, update +*** ../bash-4.0.43/shell.h 2009-01-04 14:32:41.000000000 -0500 +--- shell.h 2014-10-04 15:27:12.000000000 -0400 +*************** +*** 161,164 **** +--- 161,166 ---- + + /* 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.0/patchlevel.h 2009-01-04 14:32:40.000000000 -0500 +--- patchlevel.h 2009-02-22 16:11:31.000000000 -0500 +*************** +*** 26,30 **** + looks for to find the patch level (for the sccs version string). */ + +! #define PATCHLEVEL 43 + + #endif /* _PATCHLEVEL_H_ */ +--- 26,30 ---- + looks for to find the patch level (for the sccs version string). */ + +! #define PATCHLEVEL 44 + + #endif /* _PATCHLEVEL_H_ */ -- cgit v1.2.3