aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-01-26 01:13:58 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2017-01-26 01:13:58 +0100
commit9967c9949e0436879354e76c2847d697c309984c (patch)
treedcd6b3707305ef43f496a6058da45c89460fda4e
parent06f20bf675cdd415c2f796ebea9fc55030ef49cc (diff)
downloadbusybox-w32-9967c9949e0436879354e76c2847d697c309984c.tar.gz
busybox-w32-9967c9949e0436879354e76c2847d697c309984c.tar.bz2
busybox-w32-9967c9949e0436879354e76c2847d697c309984c.zip
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.txt7
-rw-r--r--include/libbb.h14
-rw-r--r--libbb/vfork_daemon_rexec.c36
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
99option_mask32 getting trashed. 99option_mask32 getting trashed.
100 100
101 101
102 Calling NOEXEC applets
103
104It's the same trusty spawn_and_wait(argv). If FEATURE_PREFER_APPLETS=y,
105it does NOEXEC trick. It resets xfunc_error_retval = 1 and
106logmode = LOGMODE_STDIO in the child.
107
108
102 Relevant CONFIG options 109 Relevant CONFIG options
103 110
104FEATURE_PREFER_APPLETS 111FEATURE_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;
1093 */ 1093 */
1094int wait4pid(pid_t pid) FAST_FUNC; 1094int wait4pid(pid_t pid) FAST_FUNC;
1095int wait_for_exitstatus(pid_t pid) FAST_FUNC; 1095int wait_for_exitstatus(pid_t pid) FAST_FUNC;
1096/************************************************************************/
1097/* spawn_and_wait/run_nofork_applet/run_applet_no_and_exit need to work */
1098/* carefully together to reinit some global state while not disturbing */
1099/* other. Be careful if you change them. Consult docs/nofork_noexec.txt */
1100/************************************************************************/
1096/* Same as wait4pid(spawn(argv)), but with NOFORK/NOEXEC if configured: */ 1101/* Same as wait4pid(spawn(argv)), but with NOFORK/NOEXEC if configured: */
1097int spawn_and_wait(char **argv) FAST_FUNC; 1102int spawn_and_wait(char **argv) FAST_FUNC;
1098/* Does NOT check that applet is NOFORK, just blindly runs it */ 1103/* Does NOT check that applet is NOFORK, just blindly runs it */
1099int run_nofork_applet(int applet_no, char **argv) FAST_FUNC; 1104int run_nofork_applet(int applet_no, char **argv) FAST_FUNC;
1105#ifndef BUILD_INDIVIDUAL
1106extern int find_applet_by_name(const char *name) FAST_FUNC;
1107extern void run_applet_no_and_exit(int a, char **argv) NORETURN FAST_FUNC;
1108#endif
1100 1109
1101/* Helpers for daemonization. 1110/* Helpers for daemonization.
1102 * 1111 *
@@ -1303,11 +1312,6 @@ const struct hwtype *get_hwtype(const char *name) FAST_FUNC;
1303const struct hwtype *get_hwntype(int type) FAST_FUNC; 1312const struct hwtype *get_hwntype(int type) FAST_FUNC;
1304 1313
1305 1314
1306#ifndef BUILD_INDIVIDUAL
1307extern int find_applet_by_name(const char *name) FAST_FUNC;
1308extern void run_applet_no_and_exit(int a, char **argv) NORETURN FAST_FUNC;
1309#endif
1310
1311#ifdef HAVE_MNTENT_H 1315#ifdef HAVE_MNTENT_H
1312extern int match_fstype(const struct mntent *mt, const char *fstypes) FAST_FUNC; 1316extern int match_fstype(const struct mntent *mt, const char *fstypes) FAST_FUNC;
1313extern struct mntent *find_mount_point(const char *name, int subdir_too) FAST_FUNC; 1317extern 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)
183#if ENABLE_FEATURE_PREFER_APPLETS 183#if ENABLE_FEATURE_PREFER_APPLETS
184 int a = find_applet_by_name(argv[0]); 184 int a = find_applet_by_name(argv[0]);
185 185
186 if (a >= 0 && (APPLET_IS_NOFORK(a) 186 if (a >= 0) {
187# if BB_MMU
188 || APPLET_IS_NOEXEC(a) /* NOEXEC trick needs fork() */
189# endif
190 )) {
191# if BB_MMU
192 if (APPLET_IS_NOFORK(a)) 187 if (APPLET_IS_NOFORK(a))
193# endif
194 {
195 return run_nofork_applet(a, argv); 188 return run_nofork_applet(a, argv);
189# if BB_MMU /* NOEXEC needs fork(), thus this is done only on MMU machines: */
190 if (APPLET_IS_NOEXEC(a)) {
191 fflush_all();
192 rc = fork();
193 if (rc) /* parent or error */
194 return wait4pid(rc);
195
196 /* child */
197 /* reset some state and run without execing */
198
199 /* msg_eol = "\n"; - no caller needs this reinited yet */
200 logmode = LOGMODE_STDIO;
201 /* die_func = NULL; - needed if the caller is a shell,
202 * init, or a NOFORK applet. But none of those call us
203 * as of yet (and that should probably always stay true).
204 */
205 /* xfunc_error_retval and applet_name are init by: */
206 run_applet_no_and_exit(a, argv);
196 } 207 }
197# if BB_MMU
198 /* MMU only */
199 /* a->noexec is true */
200 rc = fork();
201 if (rc) /* parent or error */
202 return wait4pid(rc);
203 /* child */
204 xfunc_error_retval = EXIT_FAILURE;
205 run_applet_no_and_exit(a, argv);
206# endif 208# endif
207 } 209 }
208#endif /* FEATURE_PREFER_APPLETS */ 210#endif /* FEATURE_PREFER_APPLETS */