Merge commit '7b25b1c5b2794a499c8ae99db75830a6d564561e'

# Conflicts:
#	shell/hush.c
This commit is contained in:
Stephen Heumann 2018-01-01 14:08:01 -06:00
commit 0eb3794f57

View File

@ -741,6 +741,13 @@ enum {
}; };
/* Can be extended to handle a FIXME in setup_redirects about not saving script fds */
struct FILE_list {
struct FILE_list *next;
FILE *fp;
};
/* "Globals" within this file */ /* "Globals" within this file */
/* Sorted roughly by size (smaller offsets == smaller code) */ /* Sorted roughly by size (smaller offsets == smaller code) */
struct globals { struct globals {
@ -839,6 +846,9 @@ struct globals {
unsigned count_SIGCHLD; unsigned count_SIGCHLD;
unsigned handled_SIGCHLD; unsigned handled_SIGCHLD;
smallint we_have_children; smallint we_have_children;
#endif
#if ENABLE_FEATURE_SH_STANDALONE
struct FILE_list *FILE_list;
#endif #endif
/* Which signals have non-DFL handler (even with no traps set)? /* Which signals have non-DFL handler (even with no traps set)?
* Set at the start to: * Set at the start to:
@ -1339,6 +1349,54 @@ static void free_strings(char **strings)
} }
/* Manipulating the list of open FILEs */
static FILE *remember_FILE(FILE *fp)
{
if (fp) {
#if ENABLE_FEATURE_SH_STANDALONE
struct FILE_list *n = xmalloc(sizeof(*n));
n->fp = fp;
n->next = G.FILE_list;
G.FILE_list = n;
#endif
close_on_exec_on(fileno(fp));
}
return fp;
}
#if ENABLE_FEATURE_SH_STANDALONE
static void close_all_FILE_list(void)
{
struct FILE_list *fl = G.FILE_list;
while (fl) {
/* fclose would also free FILE object.
* It is disastrous if we share memory with a vforked parent.
* I'm not sure we never come here after vfork.
* Therefore just close fd, nothing more.
*/
/*fclose(fl->fp); - unsafe */
close(fileno(fl->fp));
fl = fl->next;
}
}
static void fclose_and_forget(FILE *fp)
{
struct FILE_list **pp = &G.FILE_list;
while (*pp) {
struct FILE_list *cur = *pp;
if (cur->fp == fp) {
*pp = cur->next;
free(cur);
break;
}
pp = &cur->next;
}
fclose(fp);
}
#else
# define fclose_and_forget(fp) fclose(fp);
#endif
/* Helpers for setting new $n and restoring them back /* Helpers for setting new $n and restoring them back
*/ */
typedef struct save_arg_t { typedef struct save_arg_t {
@ -6276,8 +6334,7 @@ static FILE *generate_stream_from_string(const char *s, pid_t *pid_p)
free(to_free); free(to_free);
# endif # endif
close(channel[1]); close(channel[1]);
close_on_exec_on(channel[0]); return remember_FILE(xfdopen_for_read(channel[0]));
return xfdopen_for_read(channel[0]);
} }
#ifdef __ORCAC__ #ifdef __ORCAC__
@ -6392,7 +6449,7 @@ static int process_command_subs(o_string *dest, const char *s)
} }
debug_printf(("done reading from `cmd` pipe, closing it\n")); debug_printf(("done reading from `cmd` pipe, closing it\n"));
fclose(fp); fclose_and_forget(fp);
/* We need to extract exitcode. Test case /* We need to extract exitcode. Test case
* "true; echo `sleep 1; false` $?" * "true; echo `sleep 1; false` $?"
* should print 1 */ * should print 1 */
@ -7026,6 +7083,8 @@ static NOINLINE void pseudo_exec_argv(nommu_save_t *nommu_save,
if (a >= 0) { if (a >= 0) {
# if BB_MMU /* see above why on NOMMU it is not allowed */ # if BB_MMU /* see above why on NOMMU it is not allowed */
if (APPLET_IS_NOEXEC(a)) { if (APPLET_IS_NOEXEC(a)) {
/* Do not leak open fds from opened script files etc */
close_all_FILE_list();
debug_printf_exec(("running applet '%s'\n", argv[0])); debug_printf_exec(("running applet '%s'\n", argv[0]));
run_applet_no_and_exit(a, argv); run_applet_no_and_exit(a, argv);
} }
@ -8486,10 +8545,10 @@ static bool source_startup_file(const char *path)
{ {
FILE *input = fopen_for_read(path); FILE *input = fopen_for_read(path);
if (input != NULL) { if (input != NULL) {
close_on_exec_on(fileno(input)); remember_FILE(input);
install_special_sighandlers(); install_special_sighandlers();
parse_and_run_file(input); parse_and_run_file(input);
fclose(input); fclose_and_forget(input);
return 1; return 1;
} }
return 0; return 0;
@ -8875,11 +8934,11 @@ int hush_main(int argc, char **argv)
G.global_argv++; G.global_argv++;
debug_printf(("running script '%s'\n", G.global_argv[0])); debug_printf(("running script '%s'\n", G.global_argv[0]));
input = xfopen_for_read(G.global_argv[0]); input = xfopen_for_read(G.global_argv[0]);
close_on_exec_on(fileno(input)); remember_FILE(input);
install_special_sighandlers(); install_special_sighandlers();
parse_and_run_file(input); parse_and_run_file(input);
#if ENABLE_FEATURE_CLEAN_UP #if ENABLE_FEATURE_CLEAN_UP
fclose(input); fclose_and_forget(input);
#endif #endif
goto final_return; goto final_return;
} }
@ -9792,7 +9851,7 @@ static int FAST_FUNC builtin_source(char **argv)
if (arg_path) if (arg_path)
filename = arg_path; filename = arg_path;
} }
input = fopen_or_warn(filename, "r"); input = remember_FILE(fopen_or_warn(filename, "r"));
free(arg_path); free(arg_path);
if (!input) { if (!input) {
/* bb_perror_msg("%s", *argv); - done by fopen_or_warn */ /* bb_perror_msg("%s", *argv); - done by fopen_or_warn */
@ -9801,7 +9860,6 @@ static int FAST_FUNC builtin_source(char **argv)
*/ */
return EXIT_FAILURE; return EXIT_FAILURE;
} }
close_on_exec_on(fileno(input));
#if ENABLE_HUSH_FUNCTIONS #if ENABLE_HUSH_FUNCTIONS
sv_flg = G.flag_return_in_progress; sv_flg = G.flag_return_in_progress;
@ -9812,7 +9870,7 @@ static int FAST_FUNC builtin_source(char **argv)
save_and_replace_G_args(&sv, argv); save_and_replace_G_args(&sv, argv);
parse_and_run_file(input); parse_and_run_file(input);
fclose(input); fclose_and_forget(input);
if (argv[1]) if (argv[1])
restore_G_args(&sv, argv); restore_G_args(&sv, argv);