Commit 50e98013 by Daniel Lezcano Committed by Daniel Lezcano

replace fork_ns by lxc_clone

Make use of the lxc_clone function and do no longer use the fork_ns function. The lxc-unshare utility has been changed to always do a fork. Signed-off-by: 's avatarDaniel Lezcano <dlezcano@fr.ibm.com>
parent 5bb3ba8a
......@@ -40,7 +40,6 @@ void usage(char *cmd)
{
fprintf(stderr, "%s <options> [command]\n", basename(cmd));
fprintf(stderr, "Options are:\n");
fprintf(stderr, "\t -f : fork and unshare (automatic when unsharing the pids)\n");
fprintf(stderr, "\t -s flags: Ored list of flags to unshare:\n" \
"\t MOUNT, PID, UTSNAME, IPC, USER, NETWORK\n");
fprintf(stderr, "\t -u <id> : new id to be set if -s USER is specified\n");
......@@ -101,7 +100,7 @@ static int lxc_namespace_2_cloneflag(char *namespace)
return -1;
}
static int lxc_fill_namespace_flags(char *flaglist, long *flags)
static int lxc_fill_namespace_flags(char *flaglist, int *flags)
{
char *token, *saveptr = NULL;
int aflag;
......@@ -125,17 +124,48 @@ static int lxc_fill_namespace_flags(char *flaglist, long *flags)
return 0;
}
struct start_arg {
char ***args;
int *flags;
uid_t *uid;
};
static int do_start(void *arg)
{
struct start_arg *start_arg = arg;
char **args = *start_arg->args;
int flags = *start_arg->flags;
uid_t uid = *start_arg->uid;
if (flags & CLONE_NEWUSER && setuid(uid)) {
ERROR("failed to set uid %d: %s", uid, strerror(errno));
exit(1);
}
execvp(args[0], args);
ERROR("failed to exec: '%s': %s", args[0], strerror(errno));
return 1;
}
int main(int argc, char *argv[])
{
int opt, status = 1, hastofork = 0;
int opt, status;
int ret;
char *namespaces = NULL;
char **args;
long flags = 0;
int flags = 0;
uid_t uid = -1; /* valid only if (flags & CLONE_NEWUSER) */
pid_t pid;
while ((opt = getopt(argc, argv, "fs:u:")) != -1) {
struct start_arg start_arg = {
.args = &args,
.uid = &uid,
.flags = &flags,
};
while ((opt = getopt(argc, argv, "s:u:")) != -1) {
switch (opt) {
case 's':
namespaces = optarg;
......@@ -144,9 +174,6 @@ int main(int argc, char *argv[])
uid = lookup_user(optarg);
if (uid == -1)
return 1;
case 'f':
hastofork = 1;
break;
}
}
......@@ -157,61 +184,21 @@ int main(int argc, char *argv[])
usage(argv[0]);
if (!(flags & CLONE_NEWUSER) && uid != -1) {
ERROR("-u <uid> need -s USER option");
ERROR("-u <uid> needs -s USER option");
return 1;
}
if ((flags & CLONE_NEWPID) || hastofork) {
if (!argv[optind] || !strlen(argv[optind]))
usage(argv[0]);
pid = fork_ns(flags);
pid = lxc_clone(do_start, &start_arg, flags);
if (pid < 0) {
ERROR("failed to fork into a new namespace: %s",
strerror(errno));
return 1;
}
if (!pid) {
if (flags & CLONE_NEWUSER && setuid(uid)) {
ERROR("failed to set uid %d: %s",
uid, strerror(errno));
exit(1);
}
execvp(args[0], args);
ERROR("failed to exec: '%s': %s",
argv[0], strerror(errno));
exit(1);
ERROR("failed to clone");
return -1;
}
if (waitpid(pid, &status, 0) < 0)
if (waitpid(pid, &status, 0) < 0) {
ERROR("failed to wait for '%d'", pid);
return status;
}
if (unshare_ns(flags)) {
ERROR("failed to unshare the current process: %s",
strerror(errno));
return 1;
}
if (flags & CLONE_NEWUSER && setuid(uid)) {
ERROR("failed to set uid %d: %s",
uid, strerror(errno));
return 1;
}
if (argv[optind] && strlen(argv[optind])) {
execvp(args[0], args);
ERROR("failed to exec: '%s': %s",
argv[0], strerror(errno));
return 1;
return -1;
}
return 0;
return status;
}
......@@ -32,6 +32,7 @@
#include <signal.h>
#include <fcntl.h>
#include <termios.h>
#include <namespace.h>
#include <sys/param.h>
#include <sys/file.h>
#include <sys/mount.h>
......@@ -452,31 +453,22 @@ void lxc_abort(const char *name, struct lxc_handler *handler)
kill(handler->pid, SIGKILL);
}
int lxc_spawn(const char *name, struct lxc_handler *handler, char *const argv[])
struct start_arg {
const char *name;
char *const *argv;
struct lxc_handler *handler;
int *sv;
};
static int do_start(void *arg)
{
int sv[2];
int clone_flags;
struct start_arg *start_arg = arg;
struct lxc_handler *handler = start_arg->handler;
const char *name = start_arg->name;
char *const *argv = start_arg->argv;
int *sv = start_arg->sv;
int err = -1, sync;
/* Synchro socketpair */
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sv)) {
SYSERROR("failed to create communication socketpair");
goto out;
}
clone_flags = CLONE_NEWUTS|CLONE_NEWPID|CLONE_NEWIPC|CLONE_NEWNS;
if (conf_has_network(name))
clone_flags |= CLONE_NEWNET;
/* Create a process in a new set of namespaces */
handler->pid = fork_ns(clone_flags);
if (handler->pid < 0) {
SYSERROR("failed to fork into a new namespace");
goto out_close;
}
if (!handler->pid) {
if (sigprocmask(SIG_SETMASK, &handler->oldmask, NULL)) {
SYSERROR("failed to set sigprocmask");
goto out_child;
......@@ -513,12 +505,42 @@ int lxc_spawn(const char *name, struct lxc_handler *handler, char *const argv[])
execvp(argv[0], argv);
SYSERROR("failed to exec %s", argv[0]);
out_warn_father:
out_warn_father:
/* If the exec fails, tell that to our father */
if (write(sv[0], &err, sizeof(err)) < 0)
SYSERROR("failed to write the socket");
out_child:
exit(err);
out_child:
return -1;
}
int lxc_spawn(const char *name, struct lxc_handler *handler, char *const argv[])
{
int sv[2];
int clone_flags;
int err = -1, sync;
struct start_arg start_arg = {
.name = name,
.argv = argv,
.handler = handler,
.sv = sv,
};
/* Synchro socketpair */
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sv)) {
SYSERROR("failed to create communication socketpair");
goto out;
}
clone_flags = CLONE_NEWUTS|CLONE_NEWPID|CLONE_NEWIPC|CLONE_NEWNS;
if (conf_has_network(name))
clone_flags |= CLONE_NEWNET;
/* Create a process in a new set of namespaces */
handler->pid = lxc_clone(do_start, &start_arg, clone_flags);
if (handler->pid < 0) {
SYSERROR("failed to fork into a new namespace");
goto out_close;
}
close(sv[0]);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment