SHARE
TWEET

OS X for advanced users!

a guest Sep 26th, 2014 3,541 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. How to patch your vulnerable OS X to latest bash issue:
  2.  
  3. Download source package from:
  4. http://opensource.apple.com/tarballs/bash/bash-92.tar.gz
  5.  
  6. Apply the patch below.
  7. Open the bash.xcodeproj in Xcode.
  8. Compile (you probably want to modify the Xcode project to codesign if you have a certificate).
  9. Copy the binaries (bash and sh) to /bin/bash and /bin/sh.
  10.  
  11. Enjoy being an advanced Mac OS X user!
  12.  
  13. Patches from latest RedHat packages.
  14.  
  15. fg!
  16.  
  17. $ env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
  18. this is a test
  19. $ env X='() { (a)=>\' bash -c "echo date"; cat echo
  20. date
  21. cat: echo: No such file or directory
  22.  
  23. ----- CUT HERE ------
  24. diff -ur bash-92/bash-3.2/builtins/common.h bash-92-patched/bash-3.2/builtins/common.h
  25. --- bash-92/bash-3.2/builtins/common.h  2009-06-12 00:29:43.000000000 +0100
  26. +++ bash-92-patched/bash-3.2/builtins/common.h  2014-09-26 10:46:58.000000000 +0100
  27. @@ -31,6 +31,8 @@
  28.  #define SEVAL_NOHIST   0x004
  29.  #define SEVAL_NOFREE   0x008
  30.  #define SEVAL_RESETLINE        0x010
  31. +#define SEVAL_FUNCDEF 0x080    /* only allow function definitions */
  32. +#define SEVAL_ONECMD  0x100    /* only allow a single command */
  33.  
  34.  /* Flags for describe_command, shared between type.def and command.def */
  35.  #define CDESC_ALL              0x001   /* type -a */
  36. diff -ur bash-92/bash-3.2/builtins/evalstring.c bash-92-patched/bash-3.2/builtins/evalstring.c
  37. --- bash-92/bash-3.2/builtins/evalstring.c      2009-06-12 00:29:43.000000000 +0100
  38. +++ bash-92-patched/bash-3.2/builtins/evalstring.c      2014-09-26 10:46:22.000000000 +0100
  39. @@ -234,6 +234,14 @@
  40.             {
  41.               struct fd_bitmap *bitmap;
  42.  
  43. +         if ((flags & SEVAL_FUNCDEF) && command->type != cm_function_def)
  44. +     {
  45. +       internal_warning ("%s: ignoring function definition attempt", from_file);
  46. +       should_jump_to_top_level = 0;
  47. +       last_result = last_command_exit_value = EX_BADUSAGE;
  48. +       break;
  49. +     }
  50. +
  51.               bitmap = new_fd_bitmap (FD_BITMAP_SIZE);
  52.               begin_unwind_frame ("pe_dispose");
  53.               add_unwind_protect (dispose_fd_bitmap, bitmap);
  54. @@ -291,6 +299,9 @@
  55.               dispose_command (command);
  56.               dispose_fd_bitmap (bitmap);
  57.               discard_unwind_frame ("pe_dispose");
  58. +       if (flags & SEVAL_ONECMD)
  59. +         break;
  60. +
  61.             }
  62.         }
  63.        else
  64. diff -ur bash-92/bash-3.2/parse.y bash-92-patched/bash-3.2/parse.y
  65. --- bash-92/bash-3.2/parse.y    2013-01-22 01:37:34.000000000 +0000
  66. +++ bash-92-patched/bash-3.2/parse.y    2014-09-26 10:48:52.000000000 +0100
  67. @@ -253,9 +253,21 @@
  68.  
  69.  /* Variables to manage the task of reading here documents, because we need to
  70.     defer the reading until after a complete command has been collected. */
  71. -static REDIRECT *redir_stack[10];
  72. +static REDIRECT **redir_stack;
  73.  int need_here_doc;
  74.  
  75. +/* Pushes REDIR onto redir_stack, resizing it as needed. */
  76. +static void
  77. +push_redir_stack (REDIRECT *redir)
  78. +{
  79. +  /* Guard against oveflow. */
  80. +  if (need_here_doc + 1 > INT_MAX / sizeof (*redir_stack))
  81. +    abort ();
  82. +  redir_stack = xrealloc (redir_stack,
  83. +                         (need_here_doc + 1) * sizeof (*redir_stack));
  84. +  redir_stack[need_here_doc++] = redir;
  85. +}
  86. +
  87.  /* Where shell input comes from.  History expansion is performed on each
  88.     line when the shell is interactive. */
  89.  static char *shell_input_line = (char *)NULL;
  90. @@ -424,13 +436,13 @@
  91.                         {
  92.                           redir.filename = $2;
  93.                           $$ = make_redirection (0, r_reading_until, redir);
  94. -                         redir_stack[need_here_doc++] = $$;
  95. +                         push_redir_stack ($$);
  96.                         }
  97.         |       NUMBER LESS_LESS WORD
  98.                         {
  99.                           redir.filename = $3;
  100.                           $$ = make_redirection ($1, r_reading_until, redir);
  101. -                         redir_stack[need_here_doc++] = $$;
  102. +                         push_redir_stack ($$);
  103.                         }
  104.         |       LESS_LESS_LESS WORD
  105.                         {
  106. @@ -487,14 +499,14 @@
  107.                           redir.filename = $2;
  108.                           $$ = make_redirection
  109.                             (0, r_deblank_reading_until, redir);
  110. -                         redir_stack[need_here_doc++] = $$;
  111. +                         push_redir_stack ($$);
  112.                         }
  113.         |       NUMBER LESS_LESS_MINUS WORD
  114.                         {
  115.                           redir.filename = $3;
  116.                           $$ = make_redirection
  117.                             ($1, r_deblank_reading_until, redir);
  118. -                         redir_stack[need_here_doc++] = $$;
  119. +                         push_redir_stack ($$);
  120.                         }
  121.         |       GREATER_AND '-'
  122.                         {
  123. @@ -2503,6 +2515,8 @@
  124.    FREE (word_desc_to_read);
  125.    word_desc_to_read = (WORD_DESC *)NULL;
  126.  
  127. +  eol_ungetc_lookahead = 0;
  128. +
  129.    last_read_token = '\n';
  130.    token_to_read = '\n';
  131.  }
  132. @@ -3767,7 +3781,7 @@
  133.      case CASE:
  134.      case SELECT:
  135.      case FOR:
  136. -      if (word_top < MAX_CASE_NEST)
  137. +      if (word_top + 1 < MAX_CASE_NEST)
  138.         word_top++;
  139.        word_lineno[word_top] = line_number;
  140.        break;
  141. diff -ur bash-92/bash-3.2/patchlevel.h bash-92-patched/bash-3.2/patchlevel.h
  142. --- bash-92/bash-3.2/patchlevel.h       2013-01-22 01:37:34.000000000 +0000
  143. +++ bash-92-patched/bash-3.2/patchlevel.h       2014-09-26 10:44:46.000000000 +0100
  144. @@ -25,6 +25,6 @@
  145.     regexp `^#define[   ]*PATCHLEVEL', since that's what support/mkversion.sh
  146.     looks for to find the patch level (for the sccs version string). */
  147.  
  148. -#define PATCHLEVEL 51
  149. +#define PATCHLEVEL 52
  150.  
  151.  #endif /* _PATCHLEVEL_H_ */
  152. diff -ur bash-92/bash-3.2/variables.c bash-92-patched/bash-3.2/variables.c
  153. --- bash-92/bash-3.2/variables.c        2009-06-12 00:29:43.000000000 +0100
  154. +++ bash-92-patched/bash-3.2/variables.c        2014-09-26 10:42:22.000000000 +0100
  155. @@ -241,7 +241,7 @@
  156.  static void propagate_temp_var __P((PTR_T));
  157.  static void dispose_temporary_env __P((sh_free_func_t *));
  158.  
  159. -static inline char *mk_env_string __P((const char *, const char *));
  160. +static inline char *mk_env_string __P((const char *, const char *, int));
  161.  static char **make_env_array_from_var_list __P((SHELL_VAR **));
  162.  static char **make_var_export_array __P((VAR_CONTEXT *));
  163.  static char **make_func_export_array __P((void));
  164. @@ -274,6 +274,13 @@
  165.  #endif
  166.  }
  167.  
  168. +/* Prefix and suffix for environment variable names which contain
  169. +   shell functions. */
  170. +#define FUNCDEF_PREFIX "BASH_FUNC_"
  171. +#define FUNCDEF_PREFIX_LEN (strlen (FUNCDEF_PREFIX))
  172. +#define FUNCDEF_SUFFIX "()"
  173. +#define FUNCDEF_SUFFIX_LEN (strlen (FUNCDEF_SUFFIX))
  174. +
  175.  /* Initialize the shell variables from the current environment.
  176.     If PRIVMODE is nonzero, don't import functions from ENV or
  177.     parse $SHELLOPTS. */
  178. @@ -309,23 +316,33 @@
  179.  
  180.        /* If exported function, define it now.  Don't import functions from
  181.          the environment in privileged mode. */
  182. -      if (privmode == 0 && read_but_dont_execute == 0 && STREQN ("() {", string, 4))
  183. -       {
  184. -         string_length = strlen (string);
  185. -         temp_string = (char *)xmalloc (3 + string_length + char_index);
  186. -
  187. -         strcpy (temp_string, name);
  188. -         temp_string[char_index] = ' ';
  189. -         strcpy (temp_string + char_index + 1, string);
  190. +      if (privmode == 0 && read_but_dont_execute == 0
  191. +   && STREQN (FUNCDEF_PREFIX, name, FUNCDEF_PREFIX_LEN)
  192. +   && STREQ (name + char_index - FUNCDEF_SUFFIX_LEN, FUNCDEF_SUFFIX)
  193. +   && STREQN ("() {", string, 4))
  194. + {
  195. +   size_t name_length
  196. +     = char_index - (FUNCDEF_PREFIX_LEN + FUNCDEF_SUFFIX_LEN);
  197. +   char *temp_name = name + FUNCDEF_PREFIX_LEN;
  198. +   /* Temporarily remove the suffix. */
  199. +   temp_name[name_length] = '\0';
  200. +
  201. +   string_length = strlen (string);
  202. +   temp_string = (char *)xmalloc (name_length + 1 + string_length + 1);
  203. +   memcpy (temp_string, temp_name, name_length);
  204. +   temp_string[name_length] = ' ';
  205. +   memcpy (temp_string + name_length + 1, string, string_length + 1);
  206.  
  207.           parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST);
  208.  
  209. -         /* Ancient backwards compatibility.  Old versions of bash exported
  210. -            functions like name()=() {...} */
  211. -         if (name[char_index - 1] == ')' && name[char_index - 2] == '(')
  212. -           name[char_index - 2] = '\0';
  213. +    /* Don't import function names that are invalid identifiers from the
  214. +       environment, though we still allow them to be defined as shell
  215. +       variables. */
  216. +   if (legal_identifier (temp_name))
  217. +     parse_and_execute (temp_string, temp_name,
  218. +            SEVAL_NONINT|SEVAL_NOHIST|SEVAL_FUNCDEF|SEVAL_ONECMD);
  219.  
  220. -         if (temp_var = find_function (name))
  221. +         if (temp_var = find_function (temp_name))
  222.             {
  223.               VSETATTR (temp_var, (att_exported|att_imported));
  224.               array_needs_making = 1;
  225. @@ -333,9 +350,8 @@
  226.           else
  227.             report_error (_("error importing function definition for `%s'"), name);
  228.  
  229. -         /* ( */
  230. -         if (name[char_index - 1] == ')' && name[char_index - 2] == '\0')
  231. -           name[char_index - 2] = '(';         /* ) */
  232. +   /* Restore the original suffix. */
  233. +   temp_name[name_length] = FUNCDEF_SUFFIX[0];
  234.         }
  235.  #if defined (ARRAY_VARS)
  236.  #  if 0
  237. @@ -2213,7 +2229,7 @@
  238.    var->context = variable_context;     /* XXX */
  239.  
  240.    INVALIDATE_EXPORTSTR (var);
  241. -  var->exportstr = mk_env_string (name, value);
  242. +  var->exportstr = mk_env_string (name, value, 0);
  243.  
  244.    array_needs_making = 1;
  245.  
  246. @@ -3003,22 +3019,44 @@
  247.  /*                                                                 */
  248.  /* **************************************************************** */
  249.  
  250. +/* Returns the string NAME=VALUE if !FUNCTIONP or if VALUE == NULL (in
  251. +   which case it is treated as empty).  Otherwise, decorate NAME with
  252. +   FUNCDEF_PREFIX and FUNCDEF_SUFFIX, and return a string of the form
  253. +   FUNCDEF_PREFIX NAME FUNCDEF_SUFFIX = VALUE (without spaces).  */
  254.  static inline char *
  255. -mk_env_string (name, value)
  256. +mk_env_string (name, value, functionp)
  257.       const char *name, *value;
  258. +     int functionp;
  259.  {
  260. -  int name_len, value_len;
  261. -  char *p;
  262. +  size_t name_len, value_len;
  263. +  char *p, *q;
  264.  
  265.    name_len = strlen (name);
  266.    value_len = STRLEN (value);
  267. -  p = (char *)xmalloc (2 + name_len + value_len);
  268. -  strcpy (p, name);
  269. -  p[name_len] = '=';
  270. +  if (functionp && value != NULL)
  271. +    {
  272. +      p = (char *)xmalloc (FUNCDEF_PREFIX_LEN + name_len + FUNCDEF_SUFFIX_LEN
  273. +        + 1 + value_len + 1);
  274. +      q = p;
  275. +      memcpy (q, FUNCDEF_PREFIX, FUNCDEF_PREFIX_LEN);
  276. +      q += FUNCDEF_PREFIX_LEN;
  277. +      memcpy (q, name, name_len);
  278. +      q += name_len;
  279. +      memcpy (q, FUNCDEF_SUFFIX, FUNCDEF_SUFFIX_LEN);
  280. +      q += FUNCDEF_SUFFIX_LEN;
  281. +    }
  282. +  else
  283. +    {
  284. +      p = (char *)xmalloc (name_len + 1 + value_len + 1);
  285. +      memcpy (p, name, name_len);
  286. +      q = p + name_len;
  287. +    }
  288. +  q[0] = '=';
  289. +
  290.    if (value && *value)
  291. -    strcpy (p + name_len + 1, value);
  292. +    memcpy (q + 1, value, value_len + 1);
  293.    else
  294. -    p[name_len + 1] = '\0';
  295. +    q[1] = '\0';
  296.    return (p);
  297.  }
  298.  
  299. @@ -3093,7 +3131,7 @@
  300.           /* Gee, I'd like to get away with not using savestring() if we're
  301.              using the cached exportstr... */
  302.           list[list_index] = USE_EXPORTSTR ? savestring (value)
  303. -                                          : mk_env_string (var->name, value);
  304. +                                          : mk_env_string (var->name, value, function_p (var));
  305.  
  306.           if (USE_EXPORTSTR == 0)
  307.             SAVE_EXPORTSTR (var, list[list_index]);
  308. ----- CUT HERE ------
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top