use $(LIBENSCVECTOR) instead of libensc_vector.a
[util-vserver.git] / util-vserver / src / chcontext.c
index 431763b..0e0ae48 100644 (file)
@@ -28,9 +28,8 @@
 
 #include "util.h"
 #include "vserver.h"
-#include "wrappers.h"
-#include "wrappers-vserver.h"
 #include "internal.h"
+#include "lib_internal/jail.h"
 
 #include <stdio.h>
 #include <unistd.h>
 #include <errno.h>
 #include <getopt.h>
 #include <assert.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <signal.h>
+
+#define ENSC_WRAPPERS_PREFIX   "chcontext: "
+#define ENSC_WRAPPERS_VSERVER  1
+#define ENSC_WRAPPERS_UNISTD   1
+#define ENSC_WRAPPERS_FCNTL    1
+#include <wrappers.h>
 
 #define CMD_HELP       0x1000
 #define CMD_VERSION    0x1001
@@ -59,6 +67,7 @@ CMDLINE_OPTIONS[] = {
   { "version",  no_argument,  0, CMD_VERSION },
   { "cap",        required_argument,  0, CMD_CAP },
   { "ctx",        required_argument,  0, CMD_CTX },
+  { "xid",        required_argument,  0, CMD_CTX },
   { "disconnect", no_argument,        0, CMD_DISCONNECT },
   { "domainname", required_argument,  0, CMD_DOMAINNAME },
   { "flag",       required_argument,  0, CMD_FLAG },
@@ -85,10 +94,12 @@ static struct Arguments const *             global_args = 0;
 static void
 showHelp(int fd, char const *cmd, int res)
 {
+  VSERVER_DECLARE_CMD(cmd);
+  
   WRITE_MSG(fd, "Usage: ");
   WRITE_STR(fd, cmd);
   WRITE_MSG(fd,
-           " [--cap [!]<cap_name>] [--secure] [--ctx <num>] [--disconnect]\n"
+           " [--cap [!]<cap_name>] [--secure] [--xid <num>] [--disconnect]\n"
            "       [--domainname <name>] [--hostname <name>] [--flag <flags>+]\n"
            "       [--silent] [--] command arguments ...\n"
            "\n"
@@ -110,12 +121,12 @@ showHelp(int fd, char const *cmd, int res)
            "    repeated several time.\n"
            "    See /usr/include/linux/capability.h\n"
            "\n"
-           "--ctx num\n"
+           "--xid num\n"
            "    Select the context. On root in context 0 is allowed to\n"
            "    select a specific context.\n"
            "    Context number 1 is special. It can see all processes\n"
            "    in any contexts, but can't kill them though.\n"
-           "    Option --ctx may be repeated several times to specify up to 16 contexts.\n"
+           "    Option --xid may be repeated several times to specify up to 16 contexts.\n"
 
            "--disconnect\n"
            "    Start the command in background and make the process\n"
@@ -160,7 +171,7 @@ static void
 showVersion()
 {
   WRITE_MSG(1,
-           "chcontext " VERSION " -- allocates/enters a security context\n"
+           "chcontext-compat " VERSION " -- allocates/enters a security context\n"
            "This program is part of " PACKAGE_STRING "\n\n"
            "Copyright (C) 2003,2004 Enrico Scholz\n"
            VERSION_COPYRIGHT_DISCLAIMER);
@@ -187,34 +198,22 @@ setCap(char const *str, uint32_t *add_caps, uint32_t *remove_caps)
     WRITE_MSG(2, "Unknown capability '");
     WRITE_STR(2, str);
     WRITE_MSG(2, "'\n");
-    exit(255);
+    exit(wrapper_exit_code);
   }
 }
 
 static inline void
 setFlags(char const *str, uint32_t *flags)
 {
-  for (;;) {
-    char const *ptr = strchr(str, ',');
-    size_t     cnt  = ptr ? (size_t)(ptr-str) : strlen(str);
-    
-    if      (strncmp(str, "lock",     cnt)==0) *flags |= S_CTX_INFO_LOCK;
-    else if (strncmp(str, "sched",    cnt)==0) *flags |= S_CTX_INFO_SCHED;
-    else if (strncmp(str, "nproc",    cnt)==0) *flags |= S_CTX_INFO_NPROC;
-    else if (strncmp(str, "private",  cnt)==0) *flags |= S_CTX_INFO_PRIVATE;
-    else if (strncmp(str, "fakeinit", cnt)==0) *flags |= S_CTX_INFO_INIT;
-    else if (strncmp(str, "hideinfo", cnt)==0) *flags |= S_CTX_INFO_HIDEINFO;
-    else if (strncmp(str, "ulimit",   cnt)==0) *flags |= S_CTX_INFO_ULIMIT;
-    else {
-      WRITE_MSG(2, "Unknown flag '");
-      write(2, str, cnt);
-      WRITE_MSG(2, "'\n");
-      exit(255);
-    }
+  struct vc_err_listparser     err;
+  
+  *flags = vc_list2cflag_compat(str, 0, &err);
 
-    
-    if (ptr==0) break;
-    str = ptr+1;
+  if (err.ptr!=0) {
+    WRITE_MSG(2, "Unknown flag '");
+    Vwrite(2, err.ptr, err.len);
+    WRITE_MSG(2, "'\n");
+    exit(wrapper_exit_code);
   }
 }
 
@@ -224,7 +223,7 @@ setHostname(char const *name)
   if (name == NULL) return;
   
   if (sethostname(name, strlen(name))==-1) {
-    perror("sethostname()");
+    perror("chcontext: sethostname()");
     exit(255);
   }
   if (!global_args->do_silent) {
@@ -240,7 +239,7 @@ setDomainname(char const *name)
   if (name == NULL) return;
   
   if (setdomainname(name, strlen(name))==-1) {
-    perror("setdomainname()");
+    perror("chcontext: setdomainname()");
     exit(255);
   }
   if (!global_args->do_silent) {
@@ -260,59 +259,12 @@ tellContext(xid_t ctx)
 
   l = utilvserver_fmt_long(buf,ctx);
 
-  WRITE_MSG(2, "New security context is ");
-  write(2, buf, l);
-  WRITE_MSG(2, "\n");
-}
-
-static inline ALWAYSINLINE int
-initSync(int p[2])
-{
-  if (!global_args->do_disconnect) return 0;
-
-  Epipe(p);
-  fcntl(p[1], F_SETFD, FD_CLOEXEC);
-  return Efork();
+  WRITE_MSG(1, "New security context is ");
+  Vwrite(1, buf, l);
+  WRITE_MSG(1, "\n");
 }
 
-static inline ALWAYSINLINE void
-doSyncStage1(int p[2])
-{
-  int  fd;
-
-  if (!global_args->do_disconnect) return;
-  
-  fd = Eopen("/dev/null", O_RDONLY, 0);
-  Esetsid();
-  Edup2(fd, 0);
-  Eclose(p[0]);
-  if (fd!=0) Eclose(fd);
-  Ewrite(p[1], ".", 1);
-}
-
-static inline ALWAYSINLINE void
-doSyncStage2(int p[2])
-{
-  if (!global_args->do_disconnect) return;
-
-  Ewrite(p[1], "X", 1);
-}
-
-static void
-waitOnSync(pid_t pid, int p[2])
-{
-  int          c;
-  size_t       l;
-
-  assert(global_args->do_disconnect);
-  assert(pid!=0);
-
-  Eclose(p[1]);
-  l = Eread(p[0], &c, 1);
-  if (l!=1) exitLikeProcess(pid);
-  l = Eread(p[0], &c, 1);
-  if (l!=0) exitLikeProcess(pid);
-}
+#include "context-sync.hc"
 
 int main (int argc, char *argv[])
 {
@@ -328,11 +280,12 @@ int main (int argc, char *argv[])
   };
   xid_t                newctx;
   int          xflags;
-  int          p[2];
+  int          p[2][2];
   pid_t                pid;
   
   global_args = &args;
-  
+  signal(SIGCHLD, SIG_DFL);
+
   while (1) {
     int                c = getopt_long(argc, argv, "+", CMDLINE_OPTIONS, 0);
     if (c==-1) break;
@@ -349,7 +302,7 @@ int main (int argc, char *argv[])
        setCap(optarg, &args.add_caps, &args.remove_caps);
        break;
       case CMD_SECURE          :
-       args.remove_caps |= vc_get_securecaps();
+       args.remove_caps |= vc_get_insecurebcaps();
        break;
       case CMD_FLAG            :
        setFlags(optarg, &args.flags);
@@ -361,7 +314,7 @@ int main (int argc, char *argv[])
          WRITE_MSG(2, "Too many contexts given\n");
          exit(255);
        }
-       args.ctxs[args.nbctx++] = atoi(optarg);
+       args.ctxs[args.nbctx++] = Evc_xidopt2xid(optarg, true);
        break;
 
          
@@ -383,31 +336,33 @@ int main (int argc, char *argv[])
     args.domainname = "";
     
   if (args.nbctx == 0)
-    args.ctxs[args.nbctx++] = VC_RANDCTX;
+    args.ctxs[args.nbctx++] = VC_DYNAMIC_XID;
     
-  xflags = args.flags & 16;
+  xflags      = args.flags & S_CTX_INFO_INIT;
+  args.flags &= ~S_CTX_INFO_INIT;
 
-  newctx            = Evc_new_s_context(args.ctxs[0],0,args.flags&~16);
-  args.remove_caps &= (~args.add_caps);
-  setHostname(args.hostname);
-  setDomainname(args.domainname);
-
-  pid = initSync(p);
-  
+  pid = initSync(p, args.do_disconnect);
   if (pid==0) {
+    doSyncStage0(p, args.do_disconnect);
+    
+    newctx            = Evc_new_s_context(args.ctxs[0],0,args.flags);
+    args.remove_caps &= (~args.add_caps);
+    setHostname(args.hostname);
+    setDomainname(args.domainname);
+
     if (args.remove_caps!=0 || xflags!=0)
       Evc_new_s_context (VC_SAMECTX,args.remove_caps,xflags);
-    tellContext(args.ctxs[0]==VC_RANDCTX ? newctx : args.ctxs[0]);
+    tellContext(args.ctxs[0]==VC_DYNAMIC_XID ? newctx : args.ctxs[0]);
 
-    doSyncStage1(p);
+    doSyncStage1(p, args.do_disconnect);
     execvp (argv[optind],argv+optind);
-    doSyncStage2(p);
+    doSyncStage2(p, args.do_disconnect);
 
-    perror("execvp()");
+    PERROR_Q("chcontext: execvp", argv[optind]);
     exit(255);
   }
 
-  waitOnSync(pid, p);
+  waitOnSync(pid, p, args.ctxs[0]!=VC_DYNAMIC_XID);
   return EXIT_SUCCESS;
 }