aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-08-04 23:04:17 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2017-08-04 23:04:17 +0200
commitb182e9ad6011909fdb76358431d23d195febaf54 (patch)
tree650b66e06387f8b0f7fe054a53150809aede7701
parent692eeb81a4c54d7d8bf0d2e370c12762b2a16ff7 (diff)
downloadbusybox-w32-b182e9ad6011909fdb76358431d23d195febaf54.tar.gz
busybox-w32-b182e9ad6011909fdb76358431d23d195febaf54.tar.bz2
busybox-w32-b182e9ad6011909fdb76358431d23d195febaf54.zip
libbb: use _exit, not exit, in bb_daemonize_or_rexec()
By the time we reach exit in parent, child already exited or execed. We should not re-run libc cleanup code. While at it, introduce bb_daemon_helper() and add a few comments. Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--console-tools/openvt.c4
-rw-r--r--debianutils/start_stop_daemon.c13
-rw-r--r--include/libbb.h1
-rw-r--r--libbb/vfork_daemon_rexec.c10
-rw-r--r--loginutils/login.c4
-rw-r--r--printutils/lpd.c5
6 files changed, 22 insertions, 15 deletions
diff --git a/console-tools/openvt.c b/console-tools/openvt.c
index f3db28367..423122fe9 100644
--- a/console-tools/openvt.c
+++ b/console-tools/openvt.c
@@ -99,7 +99,7 @@ static int find_free_vtno(void)
99 /*xfunc_error_retval = 3; - do we need compat? */ 99 /*xfunc_error_retval = 3; - do we need compat? */
100 if (ioctl(fd, VT_OPENQRY, &vtno) != 0 || vtno <= 0) 100 if (ioctl(fd, VT_OPENQRY, &vtno) != 0 || vtno <= 0)
101 bb_perror_msg_and_die("can't find open VT"); 101 bb_perror_msg_and_die("can't find open VT");
102// Not really needed, grep for DAEMON_ONLY_SANITIZE 102// Not really needed, grep for DAEMON_CLOSE_EXTRA_FDS
103// if (fd > 2) 103// if (fd > 2)
104// close(fd); 104// close(fd);
105 return vtno; 105 return vtno;
@@ -155,7 +155,7 @@ int openvt_main(int argc UNUSED_PARAM, char **argv)
155 /* Grab new VT */ 155 /* Grab new VT */
156 sprintf(vtname, VC_FORMAT, vtno); 156 sprintf(vtname, VC_FORMAT, vtno);
157 /* (Try to) clean up stray open fds above fd 2 */ 157 /* (Try to) clean up stray open fds above fd 2 */
158 bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS | DAEMON_ONLY_SANITIZE, NULL); 158 bb_daemon_helper(DAEMON_CLOSE_EXTRA_FDS);
159 close(STDIN_FILENO); 159 close(STDIN_FILENO);
160 /*setsid(); - BAD IDEA: after we exit, child is SIGHUPed... */ 160 /*setsid(); - BAD IDEA: after we exit, child is SIGHUPed... */
161 xopen(vtname, O_RDWR); 161 xopen(vtname, O_RDWR);
diff --git a/debianutils/start_stop_daemon.c b/debianutils/start_stop_daemon.c
index 9d60b2c7f..07c104baa 100644
--- a/debianutils/start_stop_daemon.c
+++ b/debianutils/start_stop_daemon.c
@@ -516,6 +516,11 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv)
516 /* DAEMON_DEVNULL_STDIO is superfluous - 516 /* DAEMON_DEVNULL_STDIO is superfluous -
517 * it's always done by bb_daemonize() */ 517 * it's always done by bb_daemonize() */
518#else 518#else
519 /* Daemons usually call bb_daemonize_or_rexec(), but SSD can do
520 * without: SSD is not itself a daemon, it _execs_ a daemon.
521 * The usual NOMMU problem of "child can't run indefinitely,
522 * it must exec" does not bite us: we exec anyway.
523 */
519 pid_t pid = xvfork(); 524 pid_t pid = xvfork();
520 if (pid != 0) { 525 if (pid != 0) {
521 /* parent */ 526 /* parent */
@@ -525,12 +530,8 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv)
525 } 530 }
526 /* Child */ 531 /* Child */
527 setsid(); /* detach from controlling tty */ 532 setsid(); /* detach from controlling tty */
528 /* Redirect stdio to /dev/null, close extra FDs. 533 /* Redirect stdio to /dev/null, close extra FDs */
529 * We do not actually daemonize because of DAEMON_ONLY_SANITIZE */ 534 bb_daemon_helper(DAEMON_DEVNULL_STDIO + DAEMON_CLOSE_EXTRA_FDS);
530 bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO
531 + DAEMON_CLOSE_EXTRA_FDS
532 + DAEMON_ONLY_SANITIZE,
533 NULL /* argv, unused */ );
534#endif 535#endif
535 } 536 }
536 if (opt & OPT_MAKEPID) { 537 if (opt & OPT_MAKEPID) {
diff --git a/include/libbb.h b/include/libbb.h
index bb27c59a1..6a2a2d640 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1169,6 +1169,7 @@ enum {
1169#endif 1169#endif
1170void bb_daemonize_or_rexec(int flags, char **argv) FAST_FUNC; 1170void bb_daemonize_or_rexec(int flags, char **argv) FAST_FUNC;
1171void bb_sanitize_stdio(void) FAST_FUNC; 1171void bb_sanitize_stdio(void) FAST_FUNC;
1172#define bb_daemon_helper(arg) bb_daemonize_or_rexec((arg) | DAEMON_ONLY_SANITIZE, NULL)
1172/* Clear dangerous stuff, set PATH. Return 1 if was run by different user. */ 1173/* Clear dangerous stuff, set PATH. Return 1 if was run by different user. */
1173int sanitize_env_if_suid(void) FAST_FUNC; 1174int sanitize_env_if_suid(void) FAST_FUNC;
1174 1175
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c
index 98512bb00..f84e678b5 100644
--- a/libbb/vfork_daemon_rexec.c
+++ b/libbb/vfork_daemon_rexec.c
@@ -209,6 +209,9 @@ pid_t FAST_FUNC fork_or_rexec(char **argv)
209 /* Maybe we are already re-execed and come here again? */ 209 /* Maybe we are already re-execed and come here again? */
210 if (re_execed) 210 if (re_execed)
211 return 0; 211 return 0;
212
213 /* fflush_all(); ? - so far all callers had no buffered output to flush */
214
212 pid = xvfork(); 215 pid = xvfork();
213 if (pid) /* parent */ 216 if (pid) /* parent */
214 return pid; 217 return pid;
@@ -245,8 +248,11 @@ void FAST_FUNC bb_daemonize_or_rexec(int flags, char **argv)
245 fd = dup(fd); /* have 0,1,2 open at least to /dev/null */ 248 fd = dup(fd); /* have 0,1,2 open at least to /dev/null */
246 249
247 if (!(flags & DAEMON_ONLY_SANITIZE)) { 250 if (!(flags & DAEMON_ONLY_SANITIZE)) {
251
252 /* fflush_all(); - add it in fork_or_rexec() if necessary */
253
248 if (fork_or_rexec(argv)) 254 if (fork_or_rexec(argv))
249 exit(EXIT_SUCCESS); /* parent */ 255 _exit(EXIT_SUCCESS); /* parent */
250 /* if daemonizing, detach from stdio & ctty */ 256 /* if daemonizing, detach from stdio & ctty */
251 setsid(); 257 setsid();
252 dup2(fd, 0); 258 dup2(fd, 0);
@@ -258,7 +264,7 @@ void FAST_FUNC bb_daemonize_or_rexec(int flags, char **argv)
258 * Prevent this: stop being a session leader. 264 * Prevent this: stop being a session leader.
259 */ 265 */
260 if (fork_or_rexec(argv)) 266 if (fork_or_rexec(argv))
261 exit(EXIT_SUCCESS); /* parent */ 267 _exit(EXIT_SUCCESS); /* parent */
262 } 268 }
263 } 269 }
264 while (fd > 2) { 270 while (fd > 2) {
diff --git a/loginutils/login.c b/loginutils/login.c
index 381468d81..fcdb9592c 100644
--- a/loginutils/login.c
+++ b/loginutils/login.c
@@ -350,8 +350,8 @@ int login_main(int argc UNUSED_PARAM, char **argv)
350 /* Mandatory paranoia for suid applet: 350 /* Mandatory paranoia for suid applet:
351 * ensure that fd# 0,1,2 are opened (at least to /dev/null) 351 * ensure that fd# 0,1,2 are opened (at least to /dev/null)
352 * and any extra open fd's are closed. 352 * and any extra open fd's are closed.
353 * (The name of the function is misleading. Not daemonizing here.) */ 353 */
354 bb_daemonize_or_rexec(DAEMON_ONLY_SANITIZE | DAEMON_CLOSE_EXTRA_FDS, NULL); 354 bb_daemon_helper(DAEMON_CLOSE_EXTRA_FDS);
355 355
356 username[0] = '\0'; 356 username[0] = '\0';
357 opt = getopt32(argv, "f:h:p", &opt_user, &opt_host); 357 opt = getopt32(argv, "f:h:p", &opt_user, &opt_host);
diff --git a/printutils/lpd.c b/printutils/lpd.c
index 3fdba5d2b..662d3a224 100644
--- a/printutils/lpd.c
+++ b/printutils/lpd.c
@@ -198,9 +198,8 @@ int lpd_main(int argc UNUSED_PARAM, char *argv[])
198 q = p; // next line 198 q = p; // next line
199 } 199 }
200 // helper should not talk over network. 200 // helper should not talk over network.
201 // this call reopens stdio fds to "/dev/null" 201 // this call reopens stdio fds to "/dev/null".
202 // (no daemonization is done) 202 bb_daemon_helper(DAEMON_DEVNULL_STDIO);
203 bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO | DAEMON_ONLY_SANITIZE, NULL);
204 BB_EXECVP_or_die(argv); 203 BB_EXECVP_or_die(argv);
205 } 204 }
206 205