X-Git-Url: http://git.linux-vserver.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fvcontext.c;h=1e23637cf4814cfdcf457b3df460299042ad356b;hb=148ab3024621f97b9cf95091657db2448098bc66;hp=3cae6ea9a1e9f37b069df74eac4336d236239847;hpb=ec17b0fea7ed4c5724abd5db7ce6efb9c500bae5;p=util-vserver.git diff --git a/src/vcontext.c b/src/vcontext.c index 3cae6ea..1e23637 100644 --- a/src/vcontext.c +++ b/src/vcontext.c @@ -1,16 +1,16 @@ // $Id$ --*- c -*-- -// Copyright (C) 2004 Enrico Scholz -// +// Copyright (C) 2004-2006 Enrico Scholz +// // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. -// +// // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -// +// // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. @@ -21,9 +21,11 @@ #endif #include "util.h" +#include "compat-pivot_root.h" #include "lib/internal.h" #include "lib_internal/jail.h" #include "lib_internal/sys_personality.h" +#include "lib_internal/sys_unshare.h" #include #include @@ -33,6 +35,10 @@ #include #include #include +#include +#include +#include +#include #include @@ -63,6 +69,12 @@ #define CMD_PERSTYPE 0x400e #define CMD_PERSFLAG 0x400f #define CMD_VLOGIN 0x4010 +#define CMD_PIVOT_ROOT 0x4011 + + +#ifndef MNT_DETACH +#define MNT_DETACH 0x0002 +#endif struct option const @@ -87,9 +99,10 @@ CMDLINE_OPTIONS[] = { { "personality-type", required_argument, 0, CMD_PERSTYPE }, { "personality-flags", required_argument, 0, CMD_PERSFLAG }, { "vlogin", no_argument, 0, CMD_VLOGIN }, -#if 1 + { "pivot-root", no_argument, 0, CMD_PIVOT_ROOT }, +#if 1 { "fakeinit", no_argument, 0, CMD_INITPID }, // compatibility -#endif +#endif { 0,0,0,0 }, }; @@ -107,7 +120,8 @@ struct Arguments { uint_least32_t personality_type; int verbosity; bool do_chroot; - uid_t uid; + bool do_pivot_root; + char const * uid; xid_t xid; char const * sync_sock; char const * sync_msg; @@ -165,7 +179,7 @@ showVersion() WRITE_MSG(1, "vcontext " VERSION " -- manages the creation of security contexts\n" "This program is part of " PACKAGE_STRING "\n\n" - "Copyright (C) 2004 Enrico Scholz\n" + "Copyright (C) 2004-2006 Enrico Scholz\n" VERSION_COPYRIGHT_DISCLAIMER); exit(0); } @@ -192,7 +206,7 @@ connectExternalSync(char const *filename) { int fd; struct sockaddr_un addr; - + if (filename==0) return -1; ENSC_INIT_UNIX_SOCK(addr, filename); @@ -224,7 +238,7 @@ static void doExternalSync(int fd, char const *msg) { char c; - + if (fd==-1) return; if (msg) EsendAll(fd, msg, strlen(msg)); @@ -243,23 +257,23 @@ doit(struct Arguments const *args, int argc, char *argv[]) { int p[2][2]; pid_t pid = initSync(p, args->do_disconnect); - + if (pid==0) { xid_t xid; int ext_sync_fd = connectExternalSync(args->sync_sock); - doSyncStage0(p, args->do_disconnect); - + doSyncStage0(p, args->do_disconnect); + if (args->do_create) { - xid = vc_ctx_create(args->xid); + xid = vc_ctx_create(args->xid, NULL); if (xid==VC_NOCTX) { switch (errno) { case EEXIST : if (!args->is_silentexist) - perror(ENSC_WRAPPERS_PREFIX "vc_create_context()"); + perror(ENSC_WRAPPERS_PREFIX "vc_ctx_create()"); return 254; default : - perror(ENSC_WRAPPERS_PREFIX "vc_create_context()"); + perror(ENSC_WRAPPERS_PREFIX "vc_ctx_create()"); return wrapper_exit_code; } } @@ -271,19 +285,75 @@ doit(struct Arguments const *args, int argc, char *argv[]) if (args->do_chroot) { Echroot("."); if (args->set_namespace) { - if (args->do_migrateself) Evc_set_namespace(); - else if (args->do_migrate) Evc_enter_namespace(xid); + if (args->do_migrateself) Evc_set_namespace(xid, CLONE_NEWNS|CLONE_FS, 0); + else if (args->do_migrate) Evc_enter_namespace(xid, CLONE_NEWNS|CLONE_FS, 0); + } + } + else if (args->do_pivot_root) { + if (vc_enter_namespace(xid, CLONE_NEWNS | CLONE_FS, 1) == -1) { + bool existed = false; + if (sys_unshare(CLONE_NEWNS) == -1) { + perror(ENSC_WRAPPERS_PREFIX "unshare(NEWNS)"); + return wrapper_exit_code; + } + if (mkdir("./.oldroot", 0700) == -1) { + if (errno == EEXIST) + existed = true; + else { + perror(ENSC_WRAPPERS_PREFIX "mkdir()"); + return wrapper_exit_code; + } + } + if (pivot_root(".", "./.oldroot") == -1) { + perror(ENSC_WRAPPERS_PREFIX "pivot_root()"); + return wrapper_exit_code; + } + if (umount2("/.oldroot", MNT_DETACH) == -1) { + perror(ENSC_WRAPPERS_PREFIX "umount2()"); + return wrapper_exit_code; + } + if (!existed && rmdir("/.oldroot") == -1) { + perror(ENSC_WRAPPERS_PREFIX "rmdir()"); + return wrapper_exit_code; + } + Evc_set_namespace(xid, CLONE_NEWNS | CLONE_FS, 1); } } setFlags(args, xid); if (args->do_migrate && !args->do_migrateself) - Evc_ctx_migrate(xid); + Evc_ctx_migrate(xid, 0); + + if (args->uid != NULL) { + uid_t uid = 0; + unsigned long tmp; + + if (!isNumberUnsigned(args->uid, &tmp, false)) { +#ifdef __dietlibc__ + struct passwd *pw; + pw = getpwnam(args->uid); + if (pw == NULL) { + WRITE_MSG(2, ENSC_WRAPPERS_PREFIX "Username '"); + WRITE_STR(2, args->uid); + WRITE_MSG(2, "' does not exist\n"); + return wrapper_exit_code; + } + uid = pw->pw_uid; + Einitgroups(args->uid, pw->pw_gid); + Esetgid(pw->pw_gid); +#else + WRITE_MSG(2, ENSC_WRAPPERS_PREFIX "Uid '"); + WRITE_STR(2, args->uid); + WRITE_MSG(2, "' is not a number\n"); + return wrapper_exit_code; +#endif + } + else + uid = (uid_t) tmp; - if (args->uid!=(uid_t)(-1) && getuid()!=args->uid) { - Esetuid(args->uid); - if (getuid()!=args->uid) { + Esetuid((uid_t) uid); + if (getuid()!=uid) { WRITE_MSG(2, ENSC_WRAPPERS_PREFIX "Something went wrong while changing the UID\n"); exit(wrapper_exit_code); } @@ -298,6 +368,10 @@ doit(struct Arguments const *args, int argc, char *argv[]) doExternalSync(ext_sync_fd, args->sync_msg); doSyncStage1(p, args->do_disconnect); DPRINTF("doit: pid=%u, ppid=%u\n", getpid(), getppid()); + + if (args->do_migrateself) + setsid(); + if (!args->do_vlogin) execvp (argv[optind],argv+optind); else @@ -309,7 +383,7 @@ doit(struct Arguments const *args, int argc, char *argv[]) } assert(args->do_disconnect); - + waitOnSync(pid, p, args->xid!=VC_DYNAMIC_XID && args->do_migrate); return EXIT_SUCCESS; } @@ -355,17 +429,17 @@ int main (int argc, char *argv[]) .is_silentexist = false, .set_namespace = false, .verbosity = 1, - .uid = -1, + .uid = NULL, .xid = VC_DYNAMIC_XID, .personality_type = VC_BAD_PERSONALITY, .personality_flags = 0, .sync_msg = "ok", }; - + while (1) { int c = getopt_long(argc, argv, "+", CMDLINE_OPTIONS, 0); if (c==-1) break; - + switch (c) { case CMD_HELP : showHelp(1, argv[0], 0); case CMD_VERSION : showVersion(); @@ -376,11 +450,12 @@ int main (int argc, char *argv[]) case CMD_VLOGIN : args.do_vlogin = true; break; case CMD_INITPID : args.is_initpid = true; break; case CMD_CHROOT : args.do_chroot = true; break; + case CMD_PIVOT_ROOT : args.do_pivot_root = true; break; case CMD_NAMESPACE : args.set_namespace = true; break; case CMD_SILENTEXIST : args.is_silentexist = true; break; case CMD_SYNCSOCK : args.sync_sock = optarg; break; case CMD_SYNCMSG : args.sync_msg = optarg; break; - case CMD_UID : args.uid = atol(optarg); break; + case CMD_UID : args.uid = optarg; break; case CMD_XID : args.xid = Evc_xidopt2xid(optarg,true); break; case CMD_SILENT : --args.verbosity; break; case CMD_PERSTYPE : @@ -397,19 +472,19 @@ int main (int argc, char *argv[]) default : WRITE_MSG(2, "Try '"); WRITE_STR(2, argv[0]); - WRITE_MSG(2, " --help\" for more information.\n"); + WRITE_MSG(2, " --help' for more information.\n"); return wrapper_exit_code; break; } } signal(SIGCHLD, SIG_DFL); - + if (args.do_migrateself) args.xid = Evc_get_task_xid(0); - + if (!args.do_create && !args.do_migrate) - WRITE_MSG(2, "Neither '--create' nor '--migrate specified; try '--help' for more information\n"); + WRITE_MSG(2, "Neither '--create' nor '--migrate' specified; try '--help' for more information\n"); else if (args.do_create && args.do_migrate) WRITE_MSG(2, "Can not specify '--create' and '--migrate' at the same time; try '--help' for more information\n"); else if (!args.do_migrate && args.is_initpid)