bash: Fix CVE-2014-6278 (shellshock) Upstream-status: backport Downloaded from: ftp://ftp.gnu.org/pub/bash/bash-3.2-patches/bash32-057 Author: Chet Ramey Signed-off-by: Catalin Popeanga BASH PATCH REPORT ================= Bash-Release: 3.2 Patch-ID: bash32-057 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. --- a/builtins/evalstring.c 2014-09-16 19:08:02.000000000 -0400 +++ b/builtins/evalstring.c 2014-10-04 15:58:35.000000000 -0400 @@ -44,4 +44,5 @@ #include "../redir.h" #include "../trap.h" +#include "../bashintl.h" #if defined (HISTORY) @@ -235,10 +236,23 @@ struct fd_bitmap *bitmap; - if ((flags & SEVAL_FUNCDEF) && command->type != cm_function_def) + if (flags & SEVAL_FUNCDEF) { - internal_warning ("%s: ignoring function definition attempt", from_file); - should_jump_to_top_level = 0; - last_result = last_command_exit_value = EX_BADUSAGE; - break; + 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; + } } @@ -302,5 +316,8 @@ if (flags & SEVAL_ONECMD) - break; + { + reset_parser (); + break; + } } } --- a/parse.y 2014-09-30 19:43:22.000000000 -0400 +++ b/parse.y 2014-10-04 15:58:35.000000000 -0400 @@ -2125,4 +2125,14 @@ } +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. */ --- a/shell.h 2008-04-28 22:00:24.000000000 -0400 +++ b/shell.h 2014-10-04 15:58:35.000000000 -0400 @@ -161,4 +161,6 @@ /* 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 *));