svn commit: [25960] trunk/busybox/shell
vda at busybox.net
vda at busybox.net
Sun Apr 5 07:38:49 UTC 2009
Author: vda
Date: 2009-04-05 07:38:48 +0000 (Sun, 05 Apr 2009)
New Revision: 25960
Log:
hush: plug the leak on NOMMU re-execute path
function old new delta
clean_up_after_re_execute - 58 +58
re_execute_shell 226 244 +18
run_pipe 1271 1276 +5
generate_stream_from_string 133 138 +5
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 3/0 up/down: 86/0) Total: 86 bytes
Modified:
trunk/busybox/shell/hush.c
Changeset:
Modified: trunk/busybox/shell/hush.c
===================================================================
--- trunk/busybox/shell/hush.c 2009-04-05 02:14:59 UTC (rev 25959)
+++ trunk/busybox/shell/hush.c 2009-04-05 07:38:48 UTC (rev 25960)
@@ -481,11 +481,14 @@
smallint fake_mode;
/* These four support $?, $#, and $1 */
smalluint last_return_code;
- /* is global_argv and global_argv[1..n] malloced? (note: not [0]) */
+ /* are global_argv and global_argv[1..n] malloced? (note: not [0]) */
smalluint global_args_malloced;
/* how many non-NULL argv's we have. NB: $# + 1 */
int global_argc;
char **global_argv;
+#if !BB_MMU
+ char **argv_for_re_execing;
+#endif
#if ENABLE_HUSH_LOOPS
unsigned depth_break_continue;
unsigned depth_of_loop;
@@ -1127,7 +1130,9 @@
set_str_and_exp:
cur->varstr = str;
+#if !BB_MMU
cur->flg_read_only = flg_read_only;
+#endif
exp:
if (flg_export == 1)
cur->flg_export = 1;
@@ -2338,6 +2343,7 @@
_exit(EXIT_FAILURE);
}
+#if !BB_MMU
static void re_execute_shell(const char *s) NORETURN;
static void re_execute_shell(const char *s)
{
@@ -2354,7 +2360,7 @@
cnt += 2;
}
//TODO: need to free these strings in parent!
- argv = pp = xmalloc(sizeof(argv[0]) * cnt);
+ G.argv_for_re_execing = pp = xmalloc(sizeof(argv[0]) * cnt);
*pp++ = (char *) applet_name;
*pp++ = xasprintf("-$%u", G.root_pid);
*pp++ = xasprintf("-?%u", G.last_return_code);
@@ -2379,11 +2385,28 @@
//TODO: pass traps and functions
debug_printf_exec("re_execute_shell pid:%d cmd:'%s'\n", getpid(), s);
- execv(bb_busybox_exec_path, argv);
+ sigprocmask(SIG_SETMASK, &G.inherited_set, NULL);
+ execv(bb_busybox_exec_path, G.argv_for_re_execing);
//TODO: fallback for init=/bin/hush?
_exit(127);
}
+static void clean_up_after_re_execute(void)
+{
+ char **pp = G.argv_for_re_execing;
+ if (pp) {
+ /* Must match re_execute_shell's allocations */
+ free(pp[1]);
+ free(pp[2]);
+ free(pp[3]);
+ free(pp);
+ G.argv_for_re_execing = NULL;
+ }
+}
+#else
+#define clean_up_after_re_execute() ((void)0)
+#endif
+
static int run_list(struct pipe *pi);
/* Called after [v]fork() in run_pipe()
@@ -2892,9 +2915,11 @@
pseudo_exec((nommu_save_t*) &nommu_save, command, argv_expanded);
/* pseudo_exec() does not return */
}
+
/* parent */
#if !BB_MMU
/* Clean up after vforked child */
+ clean_up_after_re_execute();
free(nommu_save.argv);
free_strings_and_unsetenv(nommu_save.new_env, 1);
putenv_all(nommu_save.old_env);
@@ -3890,6 +3915,7 @@
}
/* parent */
+ clean_up_after_re_execute();
close(channel[1]);
pf = fdopen(channel[0], "r");
return pf;
@@ -4827,6 +4853,9 @@
* while if false; then false; fi do break; done
* (bash accepts it)
* while if false; then false; fi; do break; fi
+ * Samples to catch leaks at execution:
+ * while if (true | {true;}); then echo ok; fi; do break; done
+ * while if (true | {true;}); then echo ok; fi; do (if echo ok; break; then :; fi) | cat; break; done
*/
pctx = &ctx;
do {
More information about the busybox-cvs
mailing list