[PATCH 1/5] nsenter: Enhance waiting for a child process

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



In the case of a pid namespace we need to fork a child process instead
of calling exec.  Move all of that logic out of line into a function
continue_as_child, making the logic of the primary case easier to
understand.

Update the logic for waiting for a child process to suspend ourselves
when the child processes suspends and to continue the child process
when we are unsuspsended.  This supports the bash suspend command and
various editors that suspend themselves.

If the child process exits with a signal update the logic to run
kill(getpid(), WTERMSIG(status)) so the caller sees the same exit code
that nsenter observed.

There will always be permission to send signals to our children and
the tty is not changing so there is no need for the intermediate
process to forward signals to it's child.

Signed-off-by: "Eric W. Biederman" <ebiederm@xxxxxxxxxxxx>
---
 sys-utils/nsenter.c |   48 +++++++++++++++++++++++++++++++++++-------------
 1 files changed, 35 insertions(+), 13 deletions(-)

diff --git a/sys-utils/nsenter.c b/sys-utils/nsenter.c
index e1f3995..ad01355 100644
--- a/sys-utils/nsenter.c
+++ b/sys-utils/nsenter.c
@@ -145,6 +145,39 @@ static void open_namespace_fd(int nstype, char *path)
 	err(EXIT_FAILURE, "Unrecognized namespace type");
 }
 
+static void continue_as_child(void)
+{
+	pid_t child = fork();
+	int status;
+	pid_t ret;
+
+	if (child < 0)
+		err(EXIT_FAILURE, _("fork failed"));
+
+	/* Only the child returns */
+	if (child == 0)
+		return;
+
+	for (;;) {
+		ret = waitpid(child, &status, WUNTRACED);
+		if ((ret == child) && (WIFSTOPPED(status))) {
+			/* The child suspended so suspend us as well */
+			kill(getpid(), SIGSTOP);
+			kill(child, SIGCONT);
+		} else {
+			break;
+		}
+	}
+	/* Return the child's exit code if possible */
+	if (WIFEXITED(status)) {
+		exit(WEXITSTATUS(status));
+	}
+	else if (WIFSIGNALED(status)) {
+		kill(getpid(), WTERMSIG(status));
+	}
+	exit(EXIT_FAILURE);
+}
+
 int main(int argc, char *argv[])
 {
 	static const struct option longopts[] = {
@@ -266,19 +299,8 @@ int main(int argc, char *argv[])
 		wd_fd = -1;
 	}
 
-	if (do_fork) {
-		pid_t child = fork();
-		if (child < 0)
-			err(EXIT_FAILURE, _("fork failed"));
-		if (child != 0) {
-			int status;
-			if ((waitpid(child, &status, 0) == child) &&
-			     WIFEXITED(status)) {
-				exit(WEXITSTATUS(status));
-			}
-			exit(EXIT_FAILURE);
-		}
-	}
+	if (do_fork)
+		continue_as_child();
 
 	execvp(argv[optind], argv + optind);
 
-- 
1.7.5.4

--
To unsubscribe from this list: send the line "unsubscribe util-linux" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux