From: Daniel Lezcano Date: Tue, 7 Jul 2009 20:51:18 +0000 (+0200) Subject: replace fork_ns by lxc_clone X-Git-Tag: lxc_0_6_3~24 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=50e98013d518a3b6c57d0288887590af96689998;p=thirdparty%2Flxc.git 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: Daniel Lezcano --- diff --git a/src/lxc/lxc_unshare.c b/src/lxc/lxc_unshare.c index f105ef26d..f91d4cd99 100644 --- a/src/lxc/lxc_unshare.c +++ b/src/lxc/lxc_unshare.c @@ -40,7 +40,6 @@ void usage(char *cmd) { fprintf(stderr, "%s [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 : 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 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 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; } diff --git a/src/lxc/start.c b/src/lxc/start.c index d4cadac81..4e0c3f1d1 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -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 */