111 lines
1.9 KiB
C
111 lines
1.9 KiB
C
|
/*
|
||
|
* CORE
|
||
|
* Copyright (c)2010-2012 the Boeing Company.
|
||
|
* See the LICENSE file included in this distribution.
|
||
|
*
|
||
|
* author: Tom Goff <thomas.goff@boeing.com>
|
||
|
*
|
||
|
* netns.c
|
||
|
*
|
||
|
* Implements nsfork() and nsexecvp() for forking and executing processes
|
||
|
* within a network namespace.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#include <signal.h>
|
||
|
#include <unistd.h>
|
||
|
|
||
|
#include <sys/syscall.h>
|
||
|
#include <sys/mount.h>
|
||
|
#include <sys/utsname.h>
|
||
|
|
||
|
#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;
|
||
|
}
|