Guest User

OS X for advanced users!

a guest
Sep 26th, 2014
3,690
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