[PATCH v7 6/7] namespace utils: code shrink

Bartosz Golaszewski bartekgola at gmail.com
Fri Mar 18 11:37:49 UTC 2016


Both unshare and nsenter use similar code to fork and have the parent
wait for child's completion. Move it to a common library function.

function                                             old     new   delta
continue_as_child                                      -     105    +105
unshare_main                                        1066    1004     -62
nsenter_main                                         850     753     -97
------------------------------------------------------------------------------
(add/remove: 2/0 grow/shrink: 0/2 up/down: 105/-159)          Total: -54 bytes
   text	   data	    bss	    dec	    hex	filename
 829552	   4486	   9120	 843158	  cdd96	busybox_old
 829498	   4486	   9120	 843104	  cdd60	busybox_unstripped

Signed-off-by: Bartosz Golaszewski <bartekgola at gmail.com>
---
 util-linux/namespace.c | 34 ++++++++++++++++++++++++++++++++++
 util-linux/namespace.h |  7 +++++++
 util-linux/nsenter.c   | 20 ++------------------
 util-linux/unshare.c   | 19 ++-----------------
 4 files changed, 45 insertions(+), 35 deletions(-)
 create mode 100644 util-linux/namespace.c

diff --git a/util-linux/namespace.c b/util-linux/namespace.c
new file mode 100644
index 0000000..1cfa1ae
--- /dev/null
+++ b/util-linux/namespace.c
@@ -0,0 +1,34 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Common namespace code.
+ *
+ * Copyright (C) 2016 by Bartosz Golaszewski <bartekgola at gmail.com>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+//kbuild:lib-$(CONFIG_UNSHARE) += namespace.o
+//kbuild:lib-$(CONFIG_NSENTER) += namespace.o
+
+#include "libbb.h"
+#include "namespace.h"
+
+void continue_as_child(void)
+{
+	int exit_status, rv;
+	pid_t pid;
+
+	pid = xfork();
+	if (pid > 0) {
+		rv = safe_waitpid(pid, &exit_status, WUNTRACED);
+		if (rv < 0)
+			bb_perror_msg_and_die("waitpid");
+
+		if (WIFEXITED(exit_status))
+			exit(WEXITSTATUS(exit_status));
+		else if (WIFSIGNALED(exit_status))
+			kill(getpid(), WTERMSIG(exit_status));
+
+		bb_error_msg_and_die("child exit failed");
+	} /* Child continues. */
+}
diff --git a/util-linux/namespace.h b/util-linux/namespace.h
index 331bfe6..8a203d5 100644
--- a/util-linux/namespace.h
+++ b/util-linux/namespace.h
@@ -17,4 +17,11 @@
  */
 #define NS_PROC_PATH_MAX (sizeof("/proc//ns/user") + INT_BUF_MAX(pid_t))
 
+/*
+ * Fork and wait for the child process to finish. Exit with the child process'
+ * exit status or deliver the signal which killed the child to the parent.
+ * Exit if fork() or waitpid() fails.
+ */
+void continue_as_child(void);
+
 #endif /* BB_NAMESPACE_H */
diff --git a/util-linux/nsenter.c b/util-linux/nsenter.c
index 79a28c6..28c6972 100644
--- a/util-linux/nsenter.c
+++ b/util-linux/nsenter.c
@@ -312,24 +312,8 @@ int nsenter_main(int argc UNUSED_PARAM, char **argv)
 	 * Entering the pid namespace implies forking unless it's been
 	 * explicitly requested by the user not to.
 	 */
-	if (!(opts & OPT_nofork) && (opts & OPT_pid)) {
-		int exit_status;
-		pid_t pid;
-
-		pid = xfork();
-		if (pid > 0) {
-			status = safe_waitpid(pid, &exit_status, 0);
-			if (status < 0)
-				bb_perror_msg_and_die("waitpid");
-
-			if (WIFEXITED(exit_status))
-				return WEXITSTATUS(exit_status);
-			else if (WIFSIGNALED(exit_status))
-				kill(getpid(), WTERMSIG(exit_status));
-
-			bb_error_msg_and_die("child exit failed");
-		} /* Child continues. */
-	}
+	if (!(opts & OPT_nofork) && (opts & OPT_pid))
+		continue_as_child();
 
 	if (opts & OPT_setgid) {
 		status = setgroups(0, NULL);
diff --git a/util-linux/unshare.c b/util-linux/unshare.c
index 3bb1990..4ebf932 100644
--- a/util-linux/unshare.c
+++ b/util-linux/unshare.c
@@ -378,23 +378,8 @@ int unshare_main(int argc UNUSED_PARAM, char **argv)
 	 * child. The user may want to use this option to spawn a new process
 	 * that'll become PID 1 in this new namespace.
 	 */
-	if (opts & OPT_fork) {
-		int exit_status;
-
-		pid = xfork();
-		if (pid > 0) {
-			status = safe_waitpid(pid, &exit_status, 0);
-			if (status < 0)
-				bb_perror_msg_and_die("waitpid");
-
-			if (WIFEXITED(exit_status))
-				return WEXITSTATUS(exit_status);
-			else if (WIFSIGNALED(exit_status))
-				kill(getpid(), WTERMSIG(exit_status));
-
-			bb_error_msg_and_die("child exit failed");
-		} /* Child continues. */
-	}
+	if (opts & OPT_fork)
+		continue_as_child();
 
 	if (opts & OPT_map_root) {
 		char uidmap_buf[sizeof(unsigned int) * 3 + sizeof(" 0 1")];
-- 
2.1.4



More information about the busybox mailing list