diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-05 07:38:48 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-05 07:38:48 +0000 |
commit | cc4c693ec5c9bf93a179f205182d68d54a3daae4 (patch) | |
tree | da5fdb29cf1527602d142c3cbb58c4f9f4baf363 | |
parent | c3ff48b921780fc88712fb64e6eda67a36806325 (diff) | |
download | busybox-w32-cc4c693ec5c9bf93a179f205182d68d54a3daae4.tar.gz busybox-w32-cc4c693ec5c9bf93a179f205182d68d54a3daae4.tar.bz2 busybox-w32-cc4c693ec5c9bf93a179f205182d68d54a3daae4.zip |
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
-rw-r--r-- | shell/hush.c | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/shell/hush.c b/shell/hush.c index 8ffdfb1a8..47eff0fb8 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -481,11 +481,14 @@ struct globals { | |||
481 | smallint fake_mode; | 481 | smallint fake_mode; |
482 | /* These four support $?, $#, and $1 */ | 482 | /* These four support $?, $#, and $1 */ |
483 | smalluint last_return_code; | 483 | smalluint last_return_code; |
484 | /* is global_argv and global_argv[1..n] malloced? (note: not [0]) */ | 484 | /* are global_argv and global_argv[1..n] malloced? (note: not [0]) */ |
485 | smalluint global_args_malloced; | 485 | smalluint global_args_malloced; |
486 | /* how many non-NULL argv's we have. NB: $# + 1 */ | 486 | /* how many non-NULL argv's we have. NB: $# + 1 */ |
487 | int global_argc; | 487 | int global_argc; |
488 | char **global_argv; | 488 | char **global_argv; |
489 | #if !BB_MMU | ||
490 | char **argv_for_re_execing; | ||
491 | #endif | ||
489 | #if ENABLE_HUSH_LOOPS | 492 | #if ENABLE_HUSH_LOOPS |
490 | unsigned depth_break_continue; | 493 | unsigned depth_break_continue; |
491 | unsigned depth_of_loop; | 494 | unsigned depth_of_loop; |
@@ -1127,7 +1130,9 @@ static int set_local_var(char *str, int flg_export, int flg_read_only) | |||
1127 | 1130 | ||
1128 | set_str_and_exp: | 1131 | set_str_and_exp: |
1129 | cur->varstr = str; | 1132 | cur->varstr = str; |
1133 | #if !BB_MMU | ||
1130 | cur->flg_read_only = flg_read_only; | 1134 | cur->flg_read_only = flg_read_only; |
1135 | #endif | ||
1131 | exp: | 1136 | exp: |
1132 | if (flg_export == 1) | 1137 | if (flg_export == 1) |
1133 | cur->flg_export = 1; | 1138 | cur->flg_export = 1; |
@@ -2338,6 +2343,7 @@ static void pseudo_exec_argv(nommu_save_t *nommu_save, | |||
2338 | _exit(EXIT_FAILURE); | 2343 | _exit(EXIT_FAILURE); |
2339 | } | 2344 | } |
2340 | 2345 | ||
2346 | #if !BB_MMU | ||
2341 | static void re_execute_shell(const char *s) NORETURN; | 2347 | static void re_execute_shell(const char *s) NORETURN; |
2342 | static void re_execute_shell(const char *s) | 2348 | static void re_execute_shell(const char *s) |
2343 | { | 2349 | { |
@@ -2354,7 +2360,7 @@ static void re_execute_shell(const char *s) | |||
2354 | cnt += 2; | 2360 | cnt += 2; |
2355 | } | 2361 | } |
2356 | //TODO: need to free these strings in parent! | 2362 | //TODO: need to free these strings in parent! |
2357 | argv = pp = xmalloc(sizeof(argv[0]) * cnt); | 2363 | G.argv_for_re_execing = pp = xmalloc(sizeof(argv[0]) * cnt); |
2358 | *pp++ = (char *) applet_name; | 2364 | *pp++ = (char *) applet_name; |
2359 | *pp++ = xasprintf("-$%u", G.root_pid); | 2365 | *pp++ = xasprintf("-$%u", G.root_pid); |
2360 | *pp++ = xasprintf("-?%u", G.last_return_code); | 2366 | *pp++ = xasprintf("-?%u", G.last_return_code); |
@@ -2379,11 +2385,28 @@ static void re_execute_shell(const char *s) | |||
2379 | //TODO: pass traps and functions | 2385 | //TODO: pass traps and functions |
2380 | 2386 | ||
2381 | debug_printf_exec("re_execute_shell pid:%d cmd:'%s'\n", getpid(), s); | 2387 | debug_printf_exec("re_execute_shell pid:%d cmd:'%s'\n", getpid(), s); |
2382 | execv(bb_busybox_exec_path, argv); | 2388 | sigprocmask(SIG_SETMASK, &G.inherited_set, NULL); |
2389 | execv(bb_busybox_exec_path, G.argv_for_re_execing); | ||
2383 | //TODO: fallback for init=/bin/hush? | 2390 | //TODO: fallback for init=/bin/hush? |
2384 | _exit(127); | 2391 | _exit(127); |
2385 | } | 2392 | } |
2386 | 2393 | ||
2394 | static void clean_up_after_re_execute(void) | ||
2395 | { | ||
2396 | char **pp = G.argv_for_re_execing; | ||
2397 | if (pp) { | ||
2398 | /* Must match re_execute_shell's allocations */ | ||
2399 | free(pp[1]); | ||
2400 | free(pp[2]); | ||
2401 | free(pp[3]); | ||
2402 | free(pp); | ||
2403 | G.argv_for_re_execing = NULL; | ||
2404 | } | ||
2405 | } | ||
2406 | #else | ||
2407 | #define clean_up_after_re_execute() ((void)0) | ||
2408 | #endif | ||
2409 | |||
2387 | static int run_list(struct pipe *pi); | 2410 | static int run_list(struct pipe *pi); |
2388 | 2411 | ||
2389 | /* Called after [v]fork() in run_pipe() | 2412 | /* Called after [v]fork() in run_pipe() |
@@ -2892,9 +2915,11 @@ static int run_pipe(struct pipe *pi) | |||
2892 | pseudo_exec((nommu_save_t*) &nommu_save, command, argv_expanded); | 2915 | pseudo_exec((nommu_save_t*) &nommu_save, command, argv_expanded); |
2893 | /* pseudo_exec() does not return */ | 2916 | /* pseudo_exec() does not return */ |
2894 | } | 2917 | } |
2918 | |||
2895 | /* parent */ | 2919 | /* parent */ |
2896 | #if !BB_MMU | 2920 | #if !BB_MMU |
2897 | /* Clean up after vforked child */ | 2921 | /* Clean up after vforked child */ |
2922 | clean_up_after_re_execute(); | ||
2898 | free(nommu_save.argv); | 2923 | free(nommu_save.argv); |
2899 | free_strings_and_unsetenv(nommu_save.new_env, 1); | 2924 | free_strings_and_unsetenv(nommu_save.new_env, 1); |
2900 | putenv_all(nommu_save.old_env); | 2925 | putenv_all(nommu_save.old_env); |
@@ -3890,6 +3915,7 @@ static FILE *generate_stream_from_string(const char *s) | |||
3890 | } | 3915 | } |
3891 | 3916 | ||
3892 | /* parent */ | 3917 | /* parent */ |
3918 | clean_up_after_re_execute(); | ||
3893 | close(channel[1]); | 3919 | close(channel[1]); |
3894 | pf = fdopen(channel[0], "r"); | 3920 | pf = fdopen(channel[0], "r"); |
3895 | return pf; | 3921 | return pf; |
@@ -4827,6 +4853,9 @@ static struct pipe *parse_stream(char **pstring, | |||
4827 | * while if false; then false; fi do break; done | 4853 | * while if false; then false; fi do break; done |
4828 | * (bash accepts it) | 4854 | * (bash accepts it) |
4829 | * while if false; then false; fi; do break; fi | 4855 | * while if false; then false; fi; do break; fi |
4856 | * Samples to catch leaks at execution: | ||
4857 | * while if (true | {true;}); then echo ok; fi; do break; done | ||
4858 | * while if (true | {true;}); then echo ok; fi; do (if echo ok; break; then :; fi) | cat; break; done | ||
4830 | */ | 4859 | */ |
4831 | pctx = &ctx; | 4860 | pctx = &ctx; |
4832 | do { | 4861 | do { |