use $(LIBENSCVECTOR) instead of libensc_vector.a
[util-vserver.git] / util-vserver / src / chcontext.c
index e6e7425..0e0ae48 100644 (file)
@@ -29,6 +29,7 @@
 #include "util.h"
 #include "vserver.h"
 #include "internal.h"
+#include "lib_internal/jail.h"
 
 #include <stdio.h>
 #include <unistd.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
@@ -63,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 },
@@ -89,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"
@@ -114,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"
@@ -164,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);
@@ -198,14 +205,13 @@ setCap(char const *str, uint32_t *add_caps, uint32_t *remove_caps)
 static inline void
 setFlags(char const *str, uint32_t *flags)
 {
-  char const           *err_ptr;
-  size_t               err_len;
+  struct vc_err_listparser     err;
   
-  *flags = vc_textlist2flag(str, 0, &err_ptr, &err_len);
+  *flags = vc_list2cflag_compat(str, 0, &err);
 
-  if (err_ptr!=0) {
+  if (err.ptr!=0) {
     WRITE_MSG(2, "Unknown flag '");
-    write(2, err_ptr, err_len);
+    Vwrite(2, err.ptr, err.len);
     WRITE_MSG(2, "'\n");
     exit(wrapper_exit_code);
   }
@@ -217,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) {
@@ -233,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) {
@@ -253,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");
+  WRITE_MSG(1, "New security context is ");
+  Vwrite(1, buf, l);
+  WRITE_MSG(1, "\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();
-}
-
-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[])
 {
@@ -321,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;
@@ -342,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);
@@ -354,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;
 
          
@@ -376,13 +336,15 @@ 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 & S_CTX_INFO_INIT;
   args.flags &= ~S_CTX_INFO_INIT;
 
-  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);
@@ -390,17 +352,17 @@ int main (int argc, char *argv[])
 
     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;
 }