]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
replace fork_ns by lxc_clone
authorDaniel Lezcano <daniel.lezcano@free.fr>
Tue, 7 Jul 2009 20:51:18 +0000 (22:51 +0200)
committerDaniel Lezcano <dlezcano@fr.ibm.com>
Tue, 7 Jul 2009 20:51:18 +0000 (22:51 +0200)
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: Daniel Lezcano <dlezcano@fr.ibm.com>
src/lxc/lxc_unshare.c
src/lxc/start.c

index f105ef26df022140840c54658402dc4dde8fb17b..f91d4cd9910e676f4a2b927a2f5b6ac38212106a 100644 (file)
@@ -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,74 +174,31 @@ int main(int argc, char *argv[])
                        uid = lookup_user(optarg);
                        if (uid == -1)
                                return 1;
-               case 'f':
-                       hastofork = 1;
-                       break;
                }
        }
 
        args = &argv[optind];
 
         ret = lxc_fill_namespace_flags(namespaces, &flags);
-       if (ret)
+       if (ret)
                usage(argv[0]);
 
        if (!(flags & CLONE_NEWUSER) && uid != -1) {
-               ERROR("-u <uid> need -s USER option");
-               return 1;
-       }
-
-       if ((flags & CLONE_NEWPID) || hastofork) {
-
-               if (!argv[optind] || !strlen(argv[optind]))
-                       usage(argv[0]);
-
-               pid = fork_ns(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);
-               }
-               
-               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));
+               ERROR("-u <uid> needs -s USER option");
                return 1;
        }
 
-       if (flags & CLONE_NEWUSER && setuid(uid)) {
-               ERROR("failed to set uid %d: %s",
-                       uid, strerror(errno));
-               return 1;
+       pid = lxc_clone(do_start, &start_arg, flags);
+       if (pid < 0) {
+               ERROR("failed to clone");
+               return -1;
        }
 
-       if (argv[optind] && strlen(argv[optind])) {
-               execvp(args[0], args);
-               ERROR("failed to exec: '%s': %s",
-                       argv[0], strerror(errno));
-               return 1;
+       if (waitpid(pid, &status, 0) < 0) {
+               ERROR("failed to wait for '%d'", pid);
+               return -1;
        }
 
-       return 0;
+       return status;
 }
 
index d4cadac81eaa3b1df6ac6df234bd693c928bf2d7..4e0c3f1d19304e44d9a18280e4148bb245ce6613 100644 (file)
@@ -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,12 +453,79 @@ void lxc_abort(const char *name, struct lxc_handler *handler)
        kill(handler->pid, SIGKILL);
 }
 
+struct start_arg {
+       const char *name;
+       char *const *argv;
+       struct lxc_handler *handler;
+       int *sv;
+};
+
+static int do_start(void *arg)
+{
+       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;
+
+       if (sigprocmask(SIG_SETMASK, &handler->oldmask, NULL)) {
+               SYSERROR("failed to set sigprocmask");
+               goto out_child;
+       }
+
+       close(sv[1]);
+
+       /* Be sure we don't inherit this after the exec */
+       fcntl(sv[0], F_SETFD, FD_CLOEXEC);
+
+       /* Tell our father he can begin to configure the container */
+       if (write(sv[0], &sync, sizeof(sync)) < 0) {
+               SYSERROR("failed to write socket");
+               goto out_child;
+       }
+
+       /* Wait for the father to finish the configuration */
+       if (read(sv[0], &sync, sizeof(sync)) < 0) {
+               SYSERROR("failed to read socket");
+               goto out_child;
+       }
+
+       /* Setup the container, ip, names, utsname, ... */
+       if (lxc_setup(name, handler->tty, &handler->tty_info)) {
+               ERROR("failed to setup the container");
+               goto out_warn_father;
+       }
+
+       if (prctl(PR_CAPBSET_DROP, CAP_SYS_BOOT, 0, 0, 0)) {
+               SYSERROR("failed to remove CAP_SYS_BOOT capability");
+               goto out_child;
+       }
+
+       execvp(argv[0], argv);
+       SYSERROR("failed to exec %s", argv[0]);
+
+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:
+       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");
@@ -469,58 +537,12 @@ int lxc_spawn(const char *name, struct lxc_handler *handler, char *const argv[])
                clone_flags |= CLONE_NEWNET;
 
        /* Create a process in a new set of namespaces */
-       handler->pid = fork_ns(clone_flags);
+       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;
        }
 
-       if (!handler->pid) {
-
-               if (sigprocmask(SIG_SETMASK, &handler->oldmask, NULL)) {
-                       SYSERROR("failed to set sigprocmask");
-                       goto out_child;
-               }
-
-               close(sv[1]);
-
-               /* Be sure we don't inherit this after the exec */
-               fcntl(sv[0], F_SETFD, FD_CLOEXEC);
-               
-               /* Tell our father he can begin to configure the container */
-               if (write(sv[0], &sync, sizeof(sync)) < 0) {
-                       SYSERROR("failed to write socket");
-                       goto out_child;
-               }
-
-               /* Wait for the father to finish the configuration */
-               if (read(sv[0], &sync, sizeof(sync)) < 0) {
-                       SYSERROR("failed to read socket");
-                       goto out_child;
-               }
-
-               /* Setup the container, ip, names, utsname, ... */
-               if (lxc_setup(name, handler->tty, &handler->tty_info)) {
-                       ERROR("failed to setup the container");
-                       goto out_warn_father;
-               }
-
-               if (prctl(PR_CAPBSET_DROP, CAP_SYS_BOOT, 0, 0, 0)) {
-                       SYSERROR("failed to remove CAP_SYS_BOOT capability");
-                       goto out_child;
-               }
-
-               execvp(argv[0], argv);
-               SYSERROR("failed to exec %s", argv[0]);
-
-       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);
-       }
-
        close(sv[0]);
        
        /* Wait for the child to be ready */