libminijailpreload: proper env cleaning

We add two utility functions in util.c:
- minijail_unsetenv, which removes a var from a given envp array
- minijail_getenv, which returns a var value from a given envp array
  (same as getenv but working on an arbitrary array)

And a static utility function in util.c:
- getenv_index, which returns the index number of a passed variable
  name, or the size of the passed array if not found
  It's used by the above two utility functions, and has also been
  integrated to minijail_setenv

And use them in libminijailpreload.c to:
- properly remove the minijail-injected .so in LD_PRELOAD, without
  completely trashing any preexisting LD_PRELOAD, as was done before
  in the code. A static func truncate_preload_env() only existing in
  libminijailpreload.c is tasked to do this, and
- properly remove the __MINIJAIL_FD (kFdEnvVar) internal variable from
  the child environment before spawning it. Before, this was done by
  zeroing the proper envp entry, which is flagged as being an invalid
  environment by some programs, such as the MongoDB official client:

Without minijail:
$ /tmp/m/bin/mongo --help >/dev/null; echo $?
0

$ env -i ./minijail0 /tmp/m/bin/mongo --help >/dev/null; echo $?
Failed global initialization: BadValue malformed environment block
libminijail[4045108]: child process 4045109 exited with status 1
1

With minijail, with this patch:
$ env -i ./minijail0 /tmp/m/bin/mongo --help >/dev/null; echo $?
0

This can also be seen using `env`:

Without minijail:
$ env -i /usr/bin/env | xxd
$

With minijail, before this patch:
$ env -i ./minijail0 /usr/bin/env | xxd
00000000: 0a0a                                     ..
$

With minijail, with this patch:
$ env -i ./minijail0 /usr/bin/env | xxd
$

Change-Id: I79739a4c6f527c49a31ce31aaa9085fa574a25ee
diff --git a/util_unittest.cc b/util_unittest.cc
index 5bbc172..b9e6dfc 100644
--- a/util_unittest.cc
+++ b/util_unittest.cc
@@ -158,6 +158,42 @@
   EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\nnew1=7\nnew2=8\n",
             dump_env(env));
 
+  EXPECT_EQ(nullptr, minijail_getenv(nullptr, "dup"));
+  EXPECT_EQ(nullptr, minijail_getenv(nullptr, nullptr));
+  EXPECT_EQ(nullptr, minijail_getenv(env, nullptr));
+  EXPECT_EQ(nullptr, minijail_getenv(env, "dup="));
+  EXPECT_EQ(nullptr, minijail_getenv(env, "du"));
+  EXPECT_EQ(std::string("8"), minijail_getenv(env, "new2"));
+  EXPECT_EQ(std::string("3"), minijail_getenv(env, "val1"));
+  EXPECT_EQ(std::string("5"), minijail_getenv(env, "dup"));
+
+  EXPECT_EQ(false, minijail_unsetenv(env, "nonexisting"));
+  EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\nnew1=7\nnew2=8\n",
+            dump_env(env));
+  EXPECT_EQ(false, minijail_unsetenv(env, ""));
+  EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\nnew1=7\nnew2=8\n",
+            dump_env(env));
+  EXPECT_EQ(false, minijail_unsetenv(env, nullptr));
+  EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\nnew1=7\nnew2=8\n",
+            dump_env(env));
+  EXPECT_EQ(false, minijail_unsetenv(nullptr, nullptr));
+  EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\nnew1=7\nnew2=8\n",
+            dump_env(env));
+  EXPECT_EQ(false, minijail_unsetenv(nullptr, "nonexisting"));
+  EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\nnew1=7\nnew2=8\n",
+            dump_env(env));
+  EXPECT_EQ(false, minijail_unsetenv(env, "val1="));
+  EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\nnew1=7\nnew2=8\n",
+            dump_env(env));
+  EXPECT_EQ(true, minijail_unsetenv(env, "val1"));
+  EXPECT_EQ("new2=8\nval2=4\ndup=5\ndup=2\nempty=\nnew1=7\n", dump_env(env));
+  EXPECT_EQ(true, minijail_unsetenv(env, "empty"));
+  EXPECT_EQ("new2=8\nval2=4\ndup=5\ndup=2\nnew1=7\n", dump_env(env));
+  EXPECT_EQ(true, minijail_unsetenv(env, "new2"));
+  EXPECT_EQ("new1=7\nval2=4\ndup=5\ndup=2\n", dump_env(env));
+  EXPECT_EQ(true, minijail_unsetenv(env, "new1"));
+  EXPECT_EQ("dup=2\nval2=4\ndup=5\n", dump_env(env));
+
   minijail_free_env(env);
 }