Treat no limit separately.
[util-vserver.git] / src / vcontext.c
index 3cae6ea..fd2f59f 100644 (file)
@@ -1,6 +1,6 @@
 // $Id$    --*- c -*--
 
-// Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// Copyright (C) 2004-2006 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
 //  
 // 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
@@ -24,6 +24,7 @@
 #include "lib/internal.h"
 #include "lib_internal/jail.h"
 #include "lib_internal/sys_personality.h"
+#include "lib_internal/sys_unshare.h"
 
 #include <vserver.h>
 #include <getopt.h>
 #include <sys/un.h>
 #include <assert.h>
 #include <signal.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/mount.h>
 
 #include <linux/personality.h>
 
 #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,6 +98,7 @@ CMDLINE_OPTIONS[] = {
   { "personality-type",  required_argument, 0, CMD_PERSTYPE },
   { "personality-flags", required_argument, 0, CMD_PERSFLAG },
   { "vlogin",       no_argument,        0, CMD_VLOGIN },
+  { "pivot-root",   no_argument,        0, CMD_PIVOT_ROOT },
 #if 1  
   { "fakeinit",     no_argument,               0, CMD_INITPID },       // compatibility
 #endif  
@@ -107,7 +119,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 +178,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);
 }
@@ -251,15 +264,15 @@ doit(struct Arguments const *args, int argc, char *argv[])
     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 +284,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);
       }
@@ -355,7 +424,7 @@ 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,
@@ -376,11 +445,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,7 +467,7 @@ 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;
     }
@@ -409,7 +479,7 @@ int main (int argc, char *argv[])
     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)