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>
/*xfunc_error_retval = 3; - do we need compat? */
if (ioctl(fd, VT_OPENQRY, &vtno) != 0 || vtno <= 0)
bb_perror_msg_and_die("can't find open VT");
-// Not really needed, grep for DAEMON_ONLY_SANITIZE
+// Not really needed, grep for DAEMON_CLOSE_EXTRA_FDS
// if (fd > 2)
// close(fd);
return vtno;
/* Grab new VT */
sprintf(vtname, VC_FORMAT, vtno);
/* (Try to) clean up stray open fds above fd 2 */
- bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS | DAEMON_ONLY_SANITIZE, NULL);
+ bb_daemon_helper(DAEMON_CLOSE_EXTRA_FDS);
close(STDIN_FILENO);
/*setsid(); - BAD IDEA: after we exit, child is SIGHUPed... */
xopen(vtname, O_RDWR);
/* DAEMON_DEVNULL_STDIO is superfluous -
* it's always done by bb_daemonize() */
#else
+ /* Daemons usually call bb_daemonize_or_rexec(), but SSD can do
+ * without: SSD is not itself a daemon, it _execs_ a daemon.
+ * The usual NOMMU problem of "child can't run indefinitely,
+ * it must exec" does not bite us: we exec anyway.
+ */
pid_t pid = xvfork();
if (pid != 0) {
/* parent */
}
/* Child */
setsid(); /* detach from controlling tty */
- /* Redirect stdio to /dev/null, close extra FDs.
- * We do not actually daemonize because of DAEMON_ONLY_SANITIZE */
- bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO
- + DAEMON_CLOSE_EXTRA_FDS
- + DAEMON_ONLY_SANITIZE,
- NULL /* argv, unused */ );
+ /* Redirect stdio to /dev/null, close extra FDs */
+ bb_daemon_helper(DAEMON_DEVNULL_STDIO + DAEMON_CLOSE_EXTRA_FDS);
#endif
}
if (opt & OPT_MAKEPID) {
#endif
void bb_daemonize_or_rexec(int flags, char **argv) FAST_FUNC;
void bb_sanitize_stdio(void) FAST_FUNC;
+#define bb_daemon_helper(arg) bb_daemonize_or_rexec((arg) | DAEMON_ONLY_SANITIZE, NULL)
/* Clear dangerous stuff, set PATH. Return 1 if was run by different user. */
int sanitize_env_if_suid(void) FAST_FUNC;
/* Maybe we are already re-execed and come here again? */
if (re_execed)
return 0;
+
+ /* fflush_all(); ? - so far all callers had no buffered output to flush */
+
pid = xvfork();
if (pid) /* parent */
return pid;
fd = dup(fd); /* have 0,1,2 open at least to /dev/null */
if (!(flags & DAEMON_ONLY_SANITIZE)) {
+
+ /* fflush_all(); - add it in fork_or_rexec() if necessary */
+
if (fork_or_rexec(argv))
- exit(EXIT_SUCCESS); /* parent */
+ _exit(EXIT_SUCCESS); /* parent */
/* if daemonizing, detach from stdio & ctty */
setsid();
dup2(fd, 0);
* Prevent this: stop being a session leader.
*/
if (fork_or_rexec(argv))
- exit(EXIT_SUCCESS); /* parent */
+ _exit(EXIT_SUCCESS); /* parent */
}
}
while (fd > 2) {
/* Mandatory paranoia for suid applet:
* ensure that fd# 0,1,2 are opened (at least to /dev/null)
* and any extra open fd's are closed.
- * (The name of the function is misleading. Not daemonizing here.) */
- bb_daemonize_or_rexec(DAEMON_ONLY_SANITIZE | DAEMON_CLOSE_EXTRA_FDS, NULL);
+ */
+ bb_daemon_helper(DAEMON_CLOSE_EXTRA_FDS);
username[0] = '\0';
opt = getopt32(argv, "f:h:p", &opt_user, &opt_host);
q = p; // next line
}
// helper should not talk over network.
- // this call reopens stdio fds to "/dev/null"
- // (no daemonization is done)
- bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO | DAEMON_ONLY_SANITIZE, NULL);
+ // this call reopens stdio fds to "/dev/null".
+ bb_daemon_helper(DAEMON_DEVNULL_STDIO);
BB_EXECVP_or_die(argv);
}