hush: use FEATURE_SH_NOFORK to enable NOFORK trick

Also expands docs

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2011-02-02 18:38:57 +01:00
parent c71b469f5d
commit b72baeb003
4 changed files with 34 additions and 14 deletions

View File

@ -44,9 +44,11 @@ NOEXEC trick is disabled for NOMMU build.
NOFORK NOFORK
NOFORK applet should work correctly if another applet simply runs NOFORK applet should work correctly if another applet simply runs
<applet>_main(argc,argv) and then continues with its business (xargs, <applet>_main(argc,argv) and then continues with its business.
find, shells can do it). This poses much more serious limitations xargs, find, shells do it (grep for "spawn_and_wait" and
on what applet can/cannot do: "run_nofork_applet" to find more users).
This poses much more serious limitations on what applet can do:
* all NOEXEC limitations apply. * all NOEXEC limitations apply.
* do not ever exit() or exec(). * do not ever exit() or exec().
@ -56,7 +58,7 @@ on what applet can/cannot do:
is taken from xfunc_error_retval. is taken from xfunc_error_retval.
- fflush_stdout_and_exit(n) is ok to use. - fflush_stdout_and_exit(n) is ok to use.
* do not use shared global data, or save/restore shared global data * do not use shared global data, or save/restore shared global data
prior to returning. (e.g. bb_common_bufsiz1 is off-limits). (e.g. bb_common_bufsiz1) prior to returning.
- getopt32() is ok to use. You do not need to save/restore option_mask32, - getopt32() is ok to use. You do not need to save/restore option_mask32,
it is already done by core code. it is already done by core code.
* if you allocate memory, you can use xmalloc() only on the very first * if you allocate memory, you can use xmalloc() only on the very first
@ -77,3 +79,20 @@ script loops. Applets which mess with signal handlers, termios etc
are probably not worth the effort. are probably not worth the effort.
Any NOFORK applet is also a NOEXEC applet. Any NOFORK applet is also a NOEXEC applet.
Relevant CONFIG options
FEATURE_PREFER_APPLETS
BB_EXECVP(cmd, argv) will try to exec /proc/self/exe
if command's name matches some applet name
applet tables will contain NOFORK/NOEXEC bits
spawn_and_wait(argv) will do NOFORK/NOEXEC tricks
FEATURE_SH_STANDALONE (needs FEATURE_PREFER_APPLETS=y)
shells will try to exec /proc/self/exe if command's name matches
some applet name
shells will do NOEXEC trick on NOEXEC applets
FEATURE_SH_NOFORK (needs FEATURE_PREFER_APPLETS=y)
shells will do NOFORK trick on NOFORK applets

View File

@ -859,6 +859,7 @@ void FAST_FUNC update_utmp(pid_t pid, int new_type, const char *tty_name, const
# define update_utmp(pid, new_type, tty_name, username, hostname) ((void)0) # define update_utmp(pid, new_type, tty_name, username, hostname) ((void)0)
#endif #endif
int execable_file(const char *name) FAST_FUNC; int execable_file(const char *name) FAST_FUNC;
char *find_execable(const char *filename, char **PATHp) FAST_FUNC; char *find_execable(const char *filename, char **PATHp) FAST_FUNC;
int exists_execable(const char *filename) FAST_FUNC; int exists_execable(const char *filename) FAST_FUNC;

View File

@ -123,9 +123,9 @@ config FEATURE_SH_NOFORK
default n default n
depends on (HUSH || ASH) && FEATURE_PREFER_APPLETS depends on (HUSH || ASH) && FEATURE_PREFER_APPLETS
help help
This option causes busybox shells [currently only ash] This option causes busybox shells to not execute typical
to not execute typical fork/exec/wait sequence, but call <applet>_main fork/exec/wait sequence, but call <applet>_main directly,
directly, if possible. (Sometimes it is not possible: for example, if possible. (Sometimes it is not possible: for example,
this is not possible in pipes). this is not possible in pipes).
This will be done only for some applets (those which are marked This will be done only for some applets (those which are marked
@ -133,6 +133,7 @@ config FEATURE_SH_NOFORK
This may significantly speed up some shell scripts. This may significantly speed up some shell scripts.
This feature is relatively new. Use with care. This feature is relatively new. Use with care. Report bugs
to project mailing list.
endmenu endmenu

View File

@ -6615,7 +6615,7 @@ static int checkjobs_and_fg_shell(struct pipe *fg_pipe)
* cmd ; ... { list } ; ... * cmd ; ... { list } ; ...
* cmd && ... { list } && ... * cmd && ... { list } && ...
* cmd || ... { list } || ... * cmd || ... { list } || ...
* If it is, then we can run cmd as a builtin, NOFORK [do we do this?], * If it is, then we can run cmd as a builtin, NOFORK,
* or (if SH_STANDALONE) an applet, and we can run the { list } * or (if SH_STANDALONE) an applet, and we can run the { list }
* with run_list. If it isn't one of these, we fork and exec cmd. * with run_list. If it isn't one of these, we fork and exec cmd.
* *
@ -6797,13 +6797,12 @@ static NOINLINE int run_pipe(struct pipe *pi)
} }
/* Expand the rest into (possibly) many strings each */ /* Expand the rest into (possibly) many strings each */
if (0) {}
#if ENABLE_HUSH_BASH_COMPAT #if ENABLE_HUSH_BASH_COMPAT
else if (command->cmd_type == CMD_SINGLEWORD_NOGLOB) { if (command->cmd_type == CMD_SINGLEWORD_NOGLOB) {
argv_expanded = expand_strvec_to_strvec_singleword_noglob(argv + command->assignment_cnt); argv_expanded = expand_strvec_to_strvec_singleword_noglob(argv + command->assignment_cnt);
} } else
#endif #endif
else { {
argv_expanded = expand_strvec_to_strvec(argv + command->assignment_cnt); argv_expanded = expand_strvec_to_strvec(argv + command->assignment_cnt);
} }
@ -6865,7 +6864,7 @@ static NOINLINE int run_pipe(struct pipe *pi)
return rcode; return rcode;
} }
if (ENABLE_FEATURE_SH_STANDALONE) { if (ENABLE_FEATURE_SH_NOFORK) {
int n = find_applet_by_name(argv_expanded[0]); int n = find_applet_by_name(argv_expanded[0]);
if (n >= 0 && APPLET_IS_NOFORK(n)) { if (n >= 0 && APPLET_IS_NOFORK(n)) {
rcode = redirect_and_varexp_helper(&new_env, &old_vars, command, squirrel, argv_expanded); rcode = redirect_and_varexp_helper(&new_env, &old_vars, command, squirrel, argv_expanded);