[git commit] libbb: use _exit, not exit, in bb_daemonize_or_rexec()

Denys Vlasenko vda.linux at googlemail.com
Fri Aug 4 21:04:17 UTC 2017


commit: https://git.busybox.net/busybox/commit/?id=b182e9ad6011909fdb76358431d23d195febaf54
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

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 at googlemail.com>
---
 console-tools/openvt.c          |  4 ++--
 debianutils/start_stop_daemon.c | 13 +++++++------
 include/libbb.h                 |  1 +
 libbb/vfork_daemon_rexec.c      | 10 ++++++++--
 loginutils/login.c              |  4 ++--
 printutils/lpd.c                |  5 ++---
 6 files changed, 22 insertions(+), 15 deletions(-)

diff --git a/console-tools/openvt.c b/console-tools/openvt.c
index f3db283..423122f 100644
--- a/console-tools/openvt.c
+++ b/console-tools/openvt.c
@@ -99,7 +99,7 @@ static int find_free_vtno(void)
 	/*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;
@@ -155,7 +155,7 @@ int openvt_main(int argc UNUSED_PARAM, char **argv)
 	/* 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);
diff --git a/debianutils/start_stop_daemon.c b/debianutils/start_stop_daemon.c
index 9d60b2c..07c104b 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)
 		/* 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 */
@@ -525,12 +530,8 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv)
 		}
 		/* 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) {
diff --git a/include/libbb.h b/include/libbb.h
index bb27c59..6a2a2d6 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1169,6 +1169,7 @@ enum {
 #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;
 
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c
index 98512bb..f84e678 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)
 	/* 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;
@@ -245,8 +248,11 @@ void FAST_FUNC bb_daemonize_or_rexec(int flags, char **argv)
 		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);
@@ -258,7 +264,7 @@ void FAST_FUNC bb_daemonize_or_rexec(int flags, char **argv)
 			 * Prevent this: stop being a session leader.
 			 */
 			if (fork_or_rexec(argv))
-				exit(EXIT_SUCCESS); /* parent */
+				_exit(EXIT_SUCCESS); /* parent */
 		}
 	}
 	while (fd > 2) {
diff --git a/loginutils/login.c b/loginutils/login.c
index 381468d..fcdb959 100644
--- a/loginutils/login.c
+++ b/loginutils/login.c
@@ -350,8 +350,8 @@ int login_main(int argc UNUSED_PARAM, char **argv)
 	/* 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);
diff --git a/printutils/lpd.c b/printutils/lpd.c
index 3fdba5d..662d3a2 100644
--- a/printutils/lpd.c
+++ b/printutils/lpd.c
@@ -198,9 +198,8 @@ int lpd_main(int argc UNUSED_PARAM, char *argv[])
 				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);
 		}
 


More information about the busybox-cvs mailing list