libbb: spawn_and_wait() fflushes before forking NOEXEC; child reinits logmode
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
06f20bf675
commit
9967c9949e
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
/* MMU only */
|
||||
/* a->noexec is true */
|
||||
# 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 */
|
||||
xfunc_error_retval = EXIT_FAILURE;
|
||||
/* 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);
|
||||
}
|
||||
# endif
|
||||
}
|
||||
#endif /* FEATURE_PREFER_APPLETS */
|
||||
|
Loading…
Reference in New Issue
Block a user