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-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.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 | |||
99 | option_mask32 getting trashed. | 99 | option_mask32 getting trashed. |
100 | 100 | ||
101 | 101 | ||
102 | Calling NOEXEC applets | ||
103 | |||
104 | It's the same trusty spawn_and_wait(argv). If FEATURE_PREFER_APPLETS=y, | ||
105 | it does NOEXEC trick. It resets xfunc_error_retval = 1 and | ||
106 | logmode = LOGMODE_STDIO in the child. | ||
107 | |||
108 | |||
102 | Relevant CONFIG options | 109 | Relevant CONFIG options |
103 | 110 | ||
104 | FEATURE_PREFER_APPLETS | 111 | 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; | |||
1093 | */ | 1093 | */ |
1094 | int wait4pid(pid_t pid) FAST_FUNC; | 1094 | int wait4pid(pid_t pid) FAST_FUNC; |
1095 | int wait_for_exitstatus(pid_t pid) FAST_FUNC; | 1095 | int 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: */ |
1097 | int spawn_and_wait(char **argv) FAST_FUNC; | 1102 | int 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 */ |
1099 | int run_nofork_applet(int applet_no, char **argv) FAST_FUNC; | 1104 | int run_nofork_applet(int applet_no, char **argv) FAST_FUNC; |
1105 | #ifndef BUILD_INDIVIDUAL | ||
1106 | extern int find_applet_by_name(const char *name) FAST_FUNC; | ||
1107 | extern 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; | |||
1303 | const struct hwtype *get_hwntype(int type) FAST_FUNC; | 1312 | const struct hwtype *get_hwntype(int type) FAST_FUNC; |
1304 | 1313 | ||
1305 | 1314 | ||
1306 | #ifndef BUILD_INDIVIDUAL | ||
1307 | extern int find_applet_by_name(const char *name) FAST_FUNC; | ||
1308 | extern 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 |
1312 | extern int match_fstype(const struct mntent *mt, const char *fstypes) FAST_FUNC; | 1316 | extern int match_fstype(const struct mntent *mt, const char *fstypes) FAST_FUNC; |
1313 | extern struct mntent *find_mount_point(const char *name, int subdir_too) FAST_FUNC; | 1317 | 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) | |||
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 */ |