diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-01-26 01:13:58 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-01-26 01:13:58 +0100 |
commit | 9967c9949e0436879354e76c2847d697c309984c (patch) | |
tree | dcd6b3707305ef43f496a6058da45c89460fda4e | |
parent | 06f20bf675cdd415c2f796ebea9fc55030ef49cc (diff) | |
download | busybox-9967c9949e0436879354e76c2847d697c309984c.tar.gz |
libbb: spawn_and_wait() fflushes before forking NOEXEC; child reinits logmode
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | docs/nofork_noexec.txt | 7 | ||||
-rw-r--r-- | include/libbb.h | 14 | ||||
-rw-r--r-- | libbb/vfork_daemon_rexec.c | 36 |
3 files changed, 35 insertions, 22 deletions
diff --git a/docs/nofork_noexec.txt b/docs/nofork_noexec.txt index 2fb184a03..a24dd9c27 100644 --- a/docs/nofork_noexec.txt +++ b/docs/nofork_noexec.txt @@ -99,6 +99,13 @@ applet_name. Thus, for example, caller does not need to worry about option_mask32 getting trashed. + Calling NOEXEC applets + +It's the same trusty spawn_and_wait(argv). If FEATURE_PREFER_APPLETS=y, +it does NOEXEC trick. It resets xfunc_error_retval = 1 and +logmode = LOGMODE_STDIO in the child. + + Relevant CONFIG options FEATURE_PREFER_APPLETS diff --git a/include/libbb.h b/include/libbb.h index 8c652e2d7..07fe20dac 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1093,10 +1093,19 @@ pid_t wait_any_nohang(int *wstat) FAST_FUNC; */ int wait4pid(pid_t pid) FAST_FUNC; int wait_for_exitstatus(pid_t pid) FAST_FUNC; +/************************************************************************/ +/* spawn_and_wait/run_nofork_applet/run_applet_no_and_exit need to work */ +/* carefully together to reinit some global state while not disturbing */ +/* other. Be careful if you change them. Consult docs/nofork_noexec.txt */ +/************************************************************************/ /* Same as wait4pid(spawn(argv)), but with NOFORK/NOEXEC if configured: */ int spawn_and_wait(char **argv) FAST_FUNC; /* Does NOT check that applet is NOFORK, just blindly runs it */ int run_nofork_applet(int applet_no, char **argv) FAST_FUNC; +#ifndef BUILD_INDIVIDUAL +extern int find_applet_by_name(const char *name) FAST_FUNC; +extern void run_applet_no_and_exit(int a, char **argv) NORETURN FAST_FUNC; +#endif /* Helpers for daemonization. * @@ -1303,11 +1312,6 @@ const struct hwtype *get_hwtype(const char *name) FAST_FUNC; const struct hwtype *get_hwntype(int type) FAST_FUNC; -#ifndef BUILD_INDIVIDUAL -extern int find_applet_by_name(const char *name) FAST_FUNC; -extern void run_applet_no_and_exit(int a, char **argv) NORETURN FAST_FUNC; -#endif - #ifdef HAVE_MNTENT_H extern int match_fstype(const struct mntent *mt, const char *fstypes) FAST_FUNC; extern struct mntent *find_mount_point(const char *name, int subdir_too) FAST_FUNC; diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index c192829b5..2e7dc2d9b 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c @@ -183,26 +183,28 @@ int FAST_FUNC spawn_and_wait(char **argv) #if ENABLE_FEATURE_PREFER_APPLETS int a = find_applet_by_name(argv[0]); - if (a >= 0 && (APPLET_IS_NOFORK(a) -# if BB_MMU - || APPLET_IS_NOEXEC(a) /* NOEXEC trick needs fork() */ -# endif - )) { -# if BB_MMU + if (a >= 0) { if (APPLET_IS_NOFORK(a)) -# endif - { return run_nofork_applet(a, argv); +# if BB_MMU /* NOEXEC needs fork(), thus this is done only on MMU machines: */ + if (APPLET_IS_NOEXEC(a)) { + fflush_all(); + rc = fork(); + if (rc) /* parent or error */ + return wait4pid(rc); + + /* child */ + /* reset some state and run without execing */ + + /* msg_eol = "\n"; - no caller needs this reinited yet */ + logmode = LOGMODE_STDIO; + /* die_func = NULL; - needed if the caller is a shell, + * init, or a NOFORK applet. But none of those call us + * as of yet (and that should probably always stay true). + */ + /* xfunc_error_retval and applet_name are init by: */ + run_applet_no_and_exit(a, argv); } -# if BB_MMU - /* MMU only */ - /* a->noexec is true */ - rc = fork(); - if (rc) /* parent or error */ - return wait4pid(rc); - /* child */ - xfunc_error_retval = EXIT_FAILURE; - run_applet_no_and_exit(a, argv); # endif } #endif /* FEATURE_PREFER_APPLETS */ |