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