Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- How to patch your vulnerable OS X to latest bash issue:
- Download source package from:
- http://opensource.apple.com/tarballs/bash/bash-92.tar.gz
- Apply the patch below.
- Open the bash.xcodeproj in Xcode.
- Compile (you probably want to modify the Xcode project to codesign if you have a certificate).
- Copy the binaries (bash and sh) to /bin/bash and /bin/sh.
- Enjoy being an advanced Mac OS X user!
- Patches from latest RedHat packages.
- fg!
- $ env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
- this is a test
- $ env X='() { (a)=>\' bash -c "echo date"; cat echo
- date
- cat: echo: No such file or directory
- ----- CUT HERE ------
- diff -ur bash-92/bash-3.2/builtins/common.h bash-92-patched/bash-3.2/builtins/common.h
- --- bash-92/bash-3.2/builtins/common.h 2009-06-12 00:29:43.000000000 +0100
- +++ bash-92-patched/bash-3.2/builtins/common.h 2014-09-26 10:46:58.000000000 +0100
- @@ -31,6 +31,8 @@
- #define SEVAL_NOHIST 0x004
- #define SEVAL_NOFREE 0x008
- #define SEVAL_RESETLINE 0x010
- +#define SEVAL_FUNCDEF 0x080 /* only allow function definitions */
- +#define SEVAL_ONECMD 0x100 /* only allow a single command */
- /* Flags for describe_command, shared between type.def and command.def */
- #define CDESC_ALL 0x001 /* type -a */
- diff -ur bash-92/bash-3.2/builtins/evalstring.c bash-92-patched/bash-3.2/builtins/evalstring.c
- --- bash-92/bash-3.2/builtins/evalstring.c 2009-06-12 00:29:43.000000000 +0100
- +++ bash-92-patched/bash-3.2/builtins/evalstring.c 2014-09-26 10:46:22.000000000 +0100
- @@ -234,6 +234,14 @@
- {
- 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");
- add_unwind_protect (dispose_fd_bitmap, bitmap);
- @@ -291,6 +299,9 @@
- dispose_command (command);
- dispose_fd_bitmap (bitmap);
- discard_unwind_frame ("pe_dispose");
- + if (flags & SEVAL_ONECMD)
- + break;
- +
- }
- }
- else
- diff -ur bash-92/bash-3.2/parse.y bash-92-patched/bash-3.2/parse.y
- --- bash-92/bash-3.2/parse.y 2013-01-22 01:37:34.000000000 +0000
- +++ bash-92-patched/bash-3.2/parse.y 2014-09-26 10:48:52.000000000 +0100
- @@ -253,9 +253,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;
- @@ -424,13 +436,13 @@
- {
- redir.filename = $2;
- $$ = make_redirection (0, r_reading_until, redir);
- - redir_stack[need_here_doc++] = $$;
- + push_redir_stack ($$);
- }
- | NUMBER LESS_LESS WORD
- {
- redir.filename = $3;
- $$ = make_redirection ($1, r_reading_until, redir);
- - redir_stack[need_here_doc++] = $$;
- + push_redir_stack ($$);
- }
- | LESS_LESS_LESS WORD
- {
- @@ -487,14 +499,14 @@
- redir.filename = $2;
- $$ = make_redirection
- (0, r_deblank_reading_until, redir);
- - redir_stack[need_here_doc++] = $$;
- + push_redir_stack ($$);
- }
- | NUMBER LESS_LESS_MINUS WORD
- {
- redir.filename = $3;
- $$ = make_redirection
- ($1, r_deblank_reading_until, redir);
- - redir_stack[need_here_doc++] = $$;
- + push_redir_stack ($$);
- }
- | GREATER_AND '-'
- {
- @@ -2503,6 +2515,8 @@
- FREE (word_desc_to_read);
- word_desc_to_read = (WORD_DESC *)NULL;
- + eol_ungetc_lookahead = 0;
- +
- last_read_token = '\n';
- token_to_read = '\n';
- }
- @@ -3767,7 +3781,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;
- diff -ur bash-92/bash-3.2/patchlevel.h bash-92-patched/bash-3.2/patchlevel.h
- --- bash-92/bash-3.2/patchlevel.h 2013-01-22 01:37:34.000000000 +0000
- +++ bash-92-patched/bash-3.2/patchlevel.h 2014-09-26 10:44:46.000000000 +0100
- @@ -25,6 +25,6 @@
- regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
- looks for to find the patch level (for the sccs version string). */
- -#define PATCHLEVEL 51
- +#define PATCHLEVEL 52
- #endif /* _PATCHLEVEL_H_ */
- diff -ur bash-92/bash-3.2/variables.c bash-92-patched/bash-3.2/variables.c
- --- bash-92/bash-3.2/variables.c 2009-06-12 00:29:43.000000000 +0100
- +++ bash-92-patched/bash-3.2/variables.c 2014-09-26 10:42:22.000000000 +0100
- @@ -241,7 +241,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));
- @@ -274,6 +274,13 @@
- #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. */
- @@ -309,23 +316,33 @@
- /* 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);
- + 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';
- +
- + 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);
- 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';
- + /* Don't import function names that are invalid identifiers from the
- + environment, though we still allow them to be defined as shell
- + variables. */
- + 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;
- @@ -333,9 +350,8 @@
- else
- report_error (_("error importing function definition for `%s'"), name);
- - /* ( */
- - if (name[char_index - 1] == ')' && name[char_index - 2] == '\0')
- - name[char_index - 2] = '('; /* ) */
- + /* Restore the original suffix. */
- + temp_name[name_length] = FUNCDEF_SUFFIX[0];
- }
- #if defined (ARRAY_VARS)
- # if 0
- @@ -2213,7 +2229,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;
- @@ -3003,22 +3019,44 @@
- /* */
- /* **************************************************************** */
- +/* 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);
- }
- @@ -3093,7 +3131,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]);
- ----- CUT HERE ------
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement