/* * CORE * Copyright (c)2010-2012 the Boeing Company. * See the LICENSE file included in this distribution. * * author: Tom Goff * * netns.c * * Implements nsfork() and nsexecvp() for forking and executing processes * within a network namespace. * */ #include #include #include #include #include #include "myerr.h" #include "netns.h" #define NSCLONEFLGS \ ( \ SIGCHLD | \ CLONE_NEWNS | \ CLONE_NEWUTS | \ CLONE_NEWIPC | \ CLONE_NEWPID | \ CLONE_NEWNET \ ) #define MOUNT_SYS_MIN_VERSION "2.6.35" static void nssetup(void) { int r; struct utsname uts; /* Taken from systemd-nspawn. Not sure why needed, but without this, * the host system goes a bit crazy under systemd. */ r = mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL); if (r) WARN("mounting / failed"); /* mount per-namespace /proc */ r = mount(NULL, "/proc", "proc", 0, NULL); if (r) WARN("mounting /proc failed"); r = uname(&uts); if (r) { WARN("uname() failed"); return; } r = strncmp(uts.release, MOUNT_SYS_MIN_VERSION, sizeof(MOUNT_SYS_MIN_VERSION) - 1); if (r >= 0) { /* mount per-namespace /sys */ r = mount(NULL, "/sys", "sysfs", 0, NULL); if (r) WARN("mounting /sys failed"); } } pid_t nsfork(int flags) { int pid; pid = syscall(SYS_clone, flags | NSCLONEFLGS, NULL, NULL, NULL, NULL); if (pid == 0) /* child */ { nssetup(); } return pid; } pid_t nsexecvp(char *argv[]) { pid_t pid; pid = nsfork(CLONE_VFORK); switch (pid) { case -1: WARN("nsfork() failed"); break; case 0: /* child */ execvp(argv[0], argv); WARN("execvp() failed for '%s'", argv[0]); _exit(1); break; default: /* parent */ if (kill(pid, 0)) pid = -1; break; } return pid; }