libminijail: move over to using marshalled binary for preload

Move libminijail and libminijailpreload over to using the marshalling
helper functions and add to/from_fd.  The format itself is not terribly
robust, but we can change it underneath the functions in the future
(or move struct minijail to a protobuf :).

These changes lay the groundwork for sending seccomp_filter policy. A
subsequent change will implement that and disable use in the parent.

BUG=chromium-os:19459
TEST=tested as per previous commits:
     minijail0 -[pvrcuGg] -- /bin/cat /proc/self/status
     .. /bin/ps aux
     .. /bin/bash -c 'env'

Change-Id: I565816611b31ce49f85fee2241c55a3328d7b770
Reviewed-on: http://gerrit.chromium.org/gerrit/7892
Reviewed-by: Elly Jones <ellyjones@chromium.org>
Tested-by: Will Drewry <wad@chromium.org>
diff --git a/libminijailpreload.c b/libminijailpreload.c
index a4970bc..fb74e93 100644
--- a/libminijailpreload.c
+++ b/libminijailpreload.c
@@ -34,11 +34,6 @@
       envp[i][0] = '\0';
 }
 
-static void splitarg(char *str, char **key, char **val) {
-  *key = strsep(&str, "=");
-  *val = strsep(&str, "");
-}
-
 /** @brief Fake main(), spliced in before the real call to main() by
  *         __libc_start_main (see below).
  *  We get serialized commands from our invoking process over an fd specified
@@ -48,10 +43,7 @@
  */
 static int fake_main(int argc, char **argv, char **envp) {
   char *fd_name = getenv(kFdEnvVar);
-  char *arg = NULL;
-  size_t arg_len;
   int fd = -1;
-  FILE *args;
   struct minijail *j;
   if (geteuid() != getuid() || getegid() != getgid())
     /* If we didn't do this check, an attacker could set kFdEnvVar for
@@ -64,43 +56,20 @@
   fd = atoi(fd_name);
   if (fd < 0)
     return MINIJAIL_ERR_PRELOAD;
-  args = fdopen(fd, "r");
-  if (!args)
-    return MINIJAIL_ERR_PRELOAD;
 
   j = minijail_new();
   if (!j)
     die("preload: out of memory");
-  while (getline(&arg, &arg_len, args) > 0) {
-    char *key, *val;
-    unsigned long v;
-    splitarg(arg, &key, &val);
-    if (!strcmp(arg, "eom\n")) {
-      break;
-    } else if (!strcmp(key, "caps")) {
-      v = strtoul(val, NULL, 16);
-      minijail_use_caps(j, v);
-    } else if (!strcmp(key, "ptrace")) {
-      minijail_disable_ptrace(j);
-    } else if (!strcmp(key, "uid")) {
-      v = atoi(val);
-      minijail_change_uid(j, v);
-    } else if (!strcmp(key, "gid")) {
-      v = atoi(val);
-      minijail_change_gid(j, v);
-    } else if (!strcmp(key, "seccomp")) {
-      minijail_use_seccomp(j);
-    }
-    free(arg);
-    arg = NULL;
-  }
-  if (!feof(args) && ferror(args))
-    die("preload: unexpected failure during unmarshalling");
-  fclose(args);
+  if (minijail_from_fd(fd, j))
+    die("preload: failed to parse minijail from parent");
+  close(fd);
+
   /* TODO(ellyjones): this trashes existing preloads, so one can't do:
    * LD_PRELOAD="/tmp/test.so libminijailpreload.so" prog; the descendants of
    * prog will have no LD_PRELOAD set at all. */
   unset_in_env(envp, kLdPreloadEnvVar);
+  /* Strip out flags meant for the parent. */
+  minijail_preenter(j);
   minijail_enter(j);
   minijail_destroy(j);
   dlclose(libc_handle);