s!/etc/slackware-release!/etc/slackware-version! (reported by bubulak)
[util-vserver.git] / util-vserver / src / rpm-fake-resolver.c
index 640946d..39438b4 100644 (file)
 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 
+// Protocol:
+// 1. startup
+// 2. initialize (setuid, ctx-migrate, chroot, ...)
+// 3. send "." token to fd 3
+// 4. wait one character on fd 1
+// 5. process this character and consume further characters from fd 1 as far
+//    as needed
+// 6. go to 3) (or exit)
+
 #ifdef HAVE_CONFIG_H
 #  include <config.h>
 #endif
@@ -35,6 +44,7 @@
 #define ENSC_WRAPPERS_PREFIX   "rpm-fake-resolver: "
 #define ENSC_WRAPPERS_VSERVER  1
 #define ENSC_WRAPPERS_UNISTD   1
+#define ENSC_WRAPPERS_IO       1
 #define ENSC_WRAPPERS_FCNTL    1
 #include <wrappers.h>
 
@@ -47,8 +57,11 @@ struct ArgInfo {
     uid_t              uid;
     gid_t              gid;
     bool               do_fork;
+    bool               in_ctx;
     char const *       pid_file;
     char const *       chroot;
+    uint32_t           caps;
+    int                        flags;
 };
 
 static struct option const
@@ -64,7 +77,7 @@ showHelp(int fd, char const *cmd, int res)
   WRITE_MSG(fd, "Usage:  ");
   WRITE_STR(fd, cmd);
   WRITE_MSG(fd,
-           " [-c <ctx>] [-u <uid>] [-g <gid>] [-r <chroot>] [-n]\n"
+           " [-c <ctx>] [-u <uid>] [-g <gid>] [-r <chroot>] [-s] [-n]\n"
            "Please report bugs to " PACKAGE_BUGREPORT "\n");
   exit(res);
 }
@@ -85,18 +98,21 @@ inline static void
 parseArgs(struct ArgInfo *args, int argc, char *argv[])
 {
   while (1) {
-    int                c = getopt_long(argc, argv, "c:u:g:r:n", CMDLINE_OPTIONS, 0);
+    int                c = getopt_long(argc, argv, "F:C:c:u:g:r:ns", CMDLINE_OPTIONS, 0);
     if (c==-1) break;
 
     switch (c) {
       case 'h'         :  showHelp(1, argv[0], 0);
       case 'v'         :  showVersion();
 
-      case 'c'         :  args->ctx = atoi(optarg); break;
-      case 'u'         :  args->uid = atoi(optarg); break;
-      case 'g'         :  args->gid = atoi(optarg); break;
+      case 'c'         :  args->ctx     = atoi(optarg); break;
+      case 'u'         :  args->uid     = atoi(optarg); break;
+      case 'g'         :  args->gid     = atoi(optarg); break;
+      case 'F'         :  args->flags   = atoi(optarg); break;
+      case 'C'         :  args->caps    = atoi(optarg); break;
       case 'r'         :  args->chroot  = optarg;   break;
       case 'n'         :  args->do_fork = false;    break;
+      case 's'         :  args->in_ctx  = true;     break;
       default          :
        WRITE_MSG(2, "Try '");
        WRITE_STR(2, argv[0]);
@@ -136,15 +152,17 @@ static void
 do_getpwnam()
 {
   uint32_t     len;
-  Eread(0, &len, sizeof len);
 
-  if (len<MAX_RQSIZE) {
+  if (EreadAll(0, &len, sizeof len) &&
+      len<MAX_RQSIZE) {
     char               buf[len+1];
-    struct passwd *    res;
+    struct passwd *    res = 0;
+    
+    if (EreadAll(0, buf, len)) {
+      buf[len] = '\0';
+      res = getpwnam(buf);
+    }
     
-    Eread(0, buf, len);
-    buf[len] = '\0';
-    res = getpwnam(buf);
     if (res!=0) sendResult(true,  res->pw_uid);
     else        sendResult(false, -1);
   }
@@ -155,15 +173,17 @@ static void
 do_getgrnam()
 {
   uint32_t     len;
-  Eread(0, &len, sizeof len);
 
-  if (len<MAX_RQSIZE) {
+  if (EreadAll(0, &len, sizeof len) &&
+      len<MAX_RQSIZE) {
     char               buf[len+1];
-    struct group *     res;
+    struct group *     res = 0;
+    
+    if (EreadAll(0, buf, len)) {
+      buf[len] = '\0';
+      res = getgrnam(buf);
+    }
     
-    Eread(0, buf, len);
-    buf[len] = '\0';
-    res = getgrnam(buf);
     if (res!=0) sendResult(true,  res->gr_gid);
     else        sendResult(false, -1);
   }
@@ -174,11 +194,13 @@ static void
 do_closenss()
 {
   uint8_t      what;
-  Eread(0, &what, sizeof what);
-  switch (what) {
-    case 'p'   :  endpwent(); break;
-    case 'g'   :  endgrent(); break;
-    default    :  break;
+
+  if (EreadAll(0, &what, sizeof what)) {
+    switch (what) {
+      case 'p' :  endpwent(); break;
+      case 'g' :  endgrent(); break;
+      default  :  break;
+    }
   }
 }
 
@@ -187,9 +209,8 @@ run()
 {
   uint8_t      c;
 
-  while (true) {
-    Ewrite(3, ".", 1);
-    Eread (0, &c,  sizeof c);
+  while (EwriteAll(3, ".", 1),
+        EreadAll (0, &c, sizeof c)) {
     switch (c) {
       case 'P' :  do_getpwnam(); break;
       case 'G' :  do_getgrnam(); break;
@@ -223,10 +244,34 @@ daemonize(struct ArgInfo const UNUSED * args, int pid_fd)
     _exit(0);
   }
   Eclose(p[1]);
-  read(p[0], &c, 1);
+  TEMP_FAILURE_RETRY(read(p[0], &c, 1));
   Eclose(p[0]);
 }
 
+static void
+activateContext(xid_t xid, bool in_ctx,
+               uint32_t xid_caps, int xid_flags)
+{
+  if (in_ctx) {
+    struct vc_ctx_flags                flags = {
+      .flagword = 0,
+      .mask     = VC_VXF_STATE_SETUP,
+    };
+
+    Evc_set_cflags(xid, &flags);
+  }
+  else if (vc_isSupported(vcFEATURE_MIGRATE))
+      Evc_ctx_migrate(xid);
+  else {
+#ifdef VC_ENABLE_API_COMPAT
+    Evc_new_s_context(xid, xid_caps, xid_flags);
+#else
+    WRITE_MSG(2, ENSC_WRAPPERS_PREFIX "can not change context: migrate kernel feature missing and 'compat' API disabled\n");
+    exit(wrapper_exit_code);
+#endif
+  }
+}
+
 int main(int argc, char * argv[])
 {
   struct ArgInfo       args = {
@@ -235,7 +280,9 @@ int main(int argc, char * argv[])
     .gid      = 99,
     .do_fork  = true,
     .pid_file = 0,
-    .chroot   = 0
+    .chroot   = 0,
+    .in_ctx   = false,
+    .flags    = S_CTX_INFO_LOCK,
   };
   int                  pid_fd = -1;
 
@@ -253,8 +300,7 @@ int main(int argc, char * argv[])
   if (args.chroot) Echroot(args.chroot);
   Echdir("/");
 
-  //Evc_new_s_context(args.ctx, ~(VC_CAP_SETGID|VC_CAP_SETUID), S_CTX_INFO_LOCK);
-  Evc_new_s_context(args.ctx, 0, S_CTX_INFO_LOCK);
+  activateContext(args.ctx, args.in_ctx, args.caps, args.flags);
   Esetgroups(0, &args.gid);
   Esetgid(args.gid);
   Esetuid(args.uid);