diff options
Diffstat (limited to 'shell/hush.c')
-rw-r--r-- | shell/hush.c | 44 |
1 files changed, 36 insertions, 8 deletions
diff --git a/shell/hush.c b/shell/hush.c index 2fba637..5c8e007 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -6804,7 +6804,7 @@ static void restore_redirects(struct squirrel *sq) } #if ENABLE_FEATURE_SH_STANDALONE && BB_MMU -static void close_saved_fds_and_FILE_list(void) +static void close_saved_fds_and_FILE_fds(void) { if (G_interactive_fd) close(G_interactive_fd); @@ -7090,13 +7090,35 @@ static void exec_function(char ***to_free, argv[0] = G.global_argv[0]; G.global_argv = argv; G.global_argc = n = 1 + string_array_len(argv + 1); -//? close_saved_fds_and_FILE_list(); + +// Example when we are here: "cmd | func" +// func will run with saved-redirect fds open. +// $ f() { echo /proc/self/fd/*; } +// $ true | f +// /proc/self/fd/0 /proc/self/fd/1 /proc/self/fd/2 /proc/self/fd/255 /proc/self/fd/3 +// stdio^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ G_interactive_fd^ DIR fd for glob +// Same in script: +// $ . ./SCRIPT +// /proc/self/fd/0 /proc/self/fd/1 /proc/self/fd/2 /proc/self/fd/255 /proc/self/fd/3 /proc/self/fd/4 +// stdio^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ G_interactive_fd^ opened ./SCRIPT DIR fd for glob +// They are CLOEXEC so external programs won't see them, but +// for "more correctness" we might want to close those extra fds here: +//? close_saved_fds_and_FILE_fds(); + + /* "we are in function, ok to use return" */ + G_flag_return_in_progress = -1; + IF_HUSH_LOCAL(G.func_nest_level++;) + + G_flag_return_in_progress = -1; /* On MMU, funcp->body is always non-NULL */ n = run_list(funcp->body); fflush_all(); _exit(n); # else -//? close_saved_fds_and_FILE_list(); +//? close_saved_fds_and_FILE_fds(); + +//TODO: check whether "true | func_with_return" works + re_execute_shell(to_free, funcp->body_as_string, G.global_argv[0], @@ -7116,9 +7138,7 @@ static int run_function(const struct function *funcp, char **argv) /* "we are in function, ok to use return" */ sv_flg = G_flag_return_in_progress; G_flag_return_in_progress = -1; -# if ENABLE_HUSH_LOCAL - G.func_nest_level++; -# endif + IF_HUSH_LOCAL(G.func_nest_level++;) /* On MMU, funcp->body is always non-NULL */ # if !BB_MMU @@ -7182,7 +7202,7 @@ static void exec_builtin(char ***to_free, #if BB_MMU int rcode; fflush_all(); -//? close_saved_fds_and_FILE_list(); +//? close_saved_fds_and_FILE_fds(); rcode = x->b_function(argv); fflush_all(); _exit(rcode); @@ -7342,7 +7362,7 @@ static NOINLINE void pseudo_exec_argv(nommu_save_t *nommu_save, * Testcase: interactive "ls -l /proc/self/fd" * should not show tty fd open. */ - close_saved_fds_and_FILE_list(); + close_saved_fds_and_FILE_fds(); //FIXME: should also close saved redir fds debug_printf_exec("running applet '%s'\n", argv[0]); run_applet_no_and_exit(a, argv[0], argv); @@ -9253,6 +9273,14 @@ static int FAST_FUNC builtin_exec(char **argv) if (G_saved_tty_pgrp && getpid() == G.root_pid) tcsetpgrp(G_interactive_fd, G_saved_tty_pgrp); + /* Saved-redirect fds, script fds and G_interactive_fd are still + * open here. However, they are all CLOEXEC, and execv below + * closes them. Try interactive "exec ls -l /proc/self/fd", + * it should show no extra open fds in the "ls" process. + * If we'd try to run builtins/NOEXECs, this would need improving. + */ + //close_saved_fds_and_FILE_fds(); + /* TODO: if exec fails, bash does NOT exit! We do. * We'll need to undo trap cleanup (it's inside execvp_or_die) * and tcsetpgrp, and this is inherently racy. |