Home | History | Annotate | Download | only in minijail
      1 // libminijail_unittest.cpp
      2 // Copyright (C) 2016 The Android Open Source Project
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 //
     16 // Test platform independent logic of Minijail using gtest.
     17 
     18 #include <errno.h>
     19 
     20 #include <fcntl.h>
     21 #include <sys/types.h>
     22 #include <sys/stat.h>
     23 #include <sys/wait.h>
     24 
     25 #include <gtest/gtest.h>
     26 
     27 #include "libminijail.h"
     28 #include "libminijail-private.h"
     29 #include "util.h"
     30 
     31 #if defined(__ANDROID__)
     32 const char *kShellPath = "/system/bin/sh";
     33 #else
     34 const char *kShellPath = "/bin/sh";
     35 #endif
     36 
     37 /* Prototypes needed only by test. */
     38 void *consumebytes(size_t length, char **buf, size_t *buflength);
     39 char *consumestr(char **buf, size_t *buflength);
     40 size_t minijail_get_tmpfs_size(const struct minijail *);
     41 
     42 /* Silence unused variable warnings. */
     43 TEST(silence, silence_unused) {
     44   EXPECT_STREQ(kLdPreloadEnvVar, kLdPreloadEnvVar);
     45   EXPECT_STREQ(kFdEnvVar, kFdEnvVar);
     46   EXPECT_STRNE(kFdEnvVar, kLdPreloadEnvVar);
     47 }
     48 
     49 TEST(consumebytes, zero) {
     50   char buf[1024];
     51   size_t len = sizeof(buf);
     52   char *pos = &buf[0];
     53   EXPECT_NE(nullptr, consumebytes(0, &pos, &len));
     54   EXPECT_EQ(&buf[0], pos);
     55   EXPECT_EQ(sizeof(buf), len);
     56 }
     57 
     58 TEST(consumebytes, exact) {
     59   char buf[1024];
     60   size_t len = sizeof(buf);
     61   char *pos = &buf[0];
     62   /* One past the end since it consumes the whole buffer. */
     63   char *end = &buf[sizeof(buf)];
     64   EXPECT_NE(nullptr, consumebytes(len, &pos, &len));
     65   EXPECT_EQ((size_t)0, len);
     66   EXPECT_EQ(end, pos);
     67 }
     68 
     69 TEST(consumebytes, half) {
     70   char buf[1024];
     71   size_t len = sizeof(buf);
     72   char *pos = &buf[0];
     73   /* One past the end since it consumes the whole buffer. */
     74   char *end = &buf[sizeof(buf) / 2];
     75   EXPECT_NE(nullptr, consumebytes(len / 2, &pos, &len));
     76   EXPECT_EQ(sizeof(buf) / 2, len);
     77   EXPECT_EQ(end, pos);
     78 }
     79 
     80 TEST(consumebytes, toolong) {
     81   char buf[1024];
     82   size_t len = sizeof(buf);
     83   char *pos = &buf[0];
     84   /* One past the end since it consumes the whole buffer. */
     85   EXPECT_EQ(nullptr, consumebytes(len + 1, &pos, &len));
     86   EXPECT_EQ(sizeof(buf), len);
     87   EXPECT_EQ(&buf[0], pos);
     88 }
     89 
     90 TEST(consumestr, zero) {
     91   char buf[1024];
     92   size_t len = 0;
     93   char *pos = &buf[0];
     94   memset(buf, 0xff, sizeof(buf));
     95   EXPECT_EQ(nullptr, consumestr(&pos, &len));
     96   EXPECT_EQ((size_t)0, len);
     97   EXPECT_EQ(&buf[0], pos);
     98 }
     99 
    100 TEST(consumestr, nonul) {
    101   char buf[1024];
    102   size_t len = sizeof(buf);
    103   char *pos = &buf[0];
    104   memset(buf, 0xff, sizeof(buf));
    105   EXPECT_EQ(nullptr, consumestr(&pos, &len));
    106   EXPECT_EQ(sizeof(buf), len);
    107   EXPECT_EQ(&buf[0], pos);
    108 }
    109 
    110 TEST(consumestr, full) {
    111   char buf[1024];
    112   size_t len = sizeof(buf);
    113   char *pos = &buf[0];
    114   memset(buf, 0xff, sizeof(buf));
    115   buf[sizeof(buf)-1] = '\0';
    116   EXPECT_EQ((void *)buf, consumestr(&pos, &len));
    117   EXPECT_EQ((size_t)0, len);
    118   EXPECT_EQ(&buf[sizeof(buf)], pos);
    119 }
    120 
    121 TEST(consumestr, trailing_nul) {
    122   char buf[1024];
    123   size_t len = sizeof(buf) - 1;
    124   char *pos = &buf[0];
    125   memset(buf, 0xff, sizeof(buf));
    126   buf[sizeof(buf)-1] = '\0';
    127   EXPECT_EQ(nullptr, consumestr(&pos, &len));
    128   EXPECT_EQ(sizeof(buf) - 1, len);
    129   EXPECT_EQ(&buf[0], pos);
    130 }
    131 
    132 class MarshalTest : public ::testing::Test {
    133  protected:
    134   virtual void SetUp() {
    135     m_ = minijail_new();
    136     j_ = minijail_new();
    137     size_ = minijail_size(m_);
    138   }
    139   virtual void TearDown() {
    140     minijail_destroy(m_);
    141     minijail_destroy(j_);
    142   }
    143 
    144   char buf_[4096];
    145   struct minijail *m_;
    146   struct minijail *j_;
    147   size_t size_;
    148 };
    149 
    150 TEST_F(MarshalTest, empty) {
    151   ASSERT_EQ(0, minijail_marshal(m_, buf_, sizeof(buf_)));
    152   EXPECT_EQ(0, minijail_unmarshal(j_, buf_, size_));
    153 }
    154 
    155 TEST_F(MarshalTest, 0xff) {
    156   memset(buf_, 0xff, sizeof(buf_));
    157   /* Should fail on the first consumestr since a NUL will never be found. */
    158   EXPECT_EQ(-EINVAL, minijail_unmarshal(j_, buf_, sizeof(buf_)));
    159 }
    160 
    161 TEST(Test, minijail_run_pid_pipes_no_preload) {
    162   pid_t pid;
    163   int child_stdin, child_stdout, child_stderr;
    164   int mj_run_ret;
    165   ssize_t write_ret, read_ret;
    166   const size_t buf_len = 128;
    167   char buf[buf_len];
    168   int status;
    169 #if defined(__ANDROID__)
    170   char filename[] = "/system/bin/cat";
    171 #else
    172   char filename[] = "/bin/cat";
    173 #endif
    174   char teststr[] = "test\n";
    175   size_t teststr_len = strlen(teststr);
    176   char *argv[4];
    177 
    178   struct minijail *j = minijail_new();
    179 
    180   argv[0] = filename;
    181   argv[1] = NULL;
    182   mj_run_ret = minijail_run_pid_pipes_no_preload(j, argv[0], argv,
    183                                                  &pid,
    184                                                  &child_stdin, &child_stdout,
    185                                                  NULL);
    186   EXPECT_EQ(mj_run_ret, 0);
    187 
    188   write_ret = write(child_stdin, teststr, teststr_len);
    189   EXPECT_EQ(write_ret, (int)teststr_len);
    190 
    191   read_ret = read(child_stdout, buf, 8);
    192   EXPECT_EQ(read_ret, (int)teststr_len);
    193   buf[teststr_len] = 0;
    194   EXPECT_EQ(strcmp(buf, teststr), 0);
    195 
    196   EXPECT_EQ(kill(pid, SIGTERM), 0);
    197   waitpid(pid, &status, 0);
    198   ASSERT_TRUE(WIFSIGNALED(status));
    199   EXPECT_EQ(WTERMSIG(status), SIGTERM);
    200 
    201   argv[0] = (char*)kShellPath;
    202   argv[1] = "-c";
    203   argv[2] = "echo test >&2";
    204   argv[3] = NULL;
    205   mj_run_ret = minijail_run_pid_pipes_no_preload(j, argv[0], argv, &pid,
    206                                                  &child_stdin, &child_stdout,
    207                                                  &child_stderr);
    208   EXPECT_EQ(mj_run_ret, 0);
    209 
    210   read_ret = read(child_stderr, buf, buf_len);
    211   EXPECT_GE(read_ret, (int)teststr_len);
    212 
    213   waitpid(pid, &status, 0);
    214   ASSERT_TRUE(WIFEXITED(status));
    215   EXPECT_EQ(WEXITSTATUS(status), 0);
    216 
    217   minijail_destroy(j);
    218 }
    219 
    220 TEST(Test, test_minijail_no_fd_leaks) {
    221   pid_t pid;
    222   int child_stdout;
    223   int mj_run_ret;
    224   ssize_t read_ret;
    225   const size_t buf_len = 128;
    226   char buf[buf_len];
    227   char script[buf_len];
    228   int status;
    229   char *argv[4];
    230 
    231   int dev_null = open("/dev/null", O_RDONLY);
    232   ASSERT_NE(dev_null, -1);
    233   snprintf(script,
    234            sizeof(script),
    235            "[ -e /proc/self/fd/%d ] && echo yes || echo no",
    236            dev_null);
    237 
    238   struct minijail *j = minijail_new();
    239 
    240   argv[0] = (char*)kShellPath;
    241   argv[1] = "-c";
    242   argv[2] = script;
    243   argv[3] = NULL;
    244   mj_run_ret = minijail_run_pid_pipes_no_preload(
    245       j, argv[0], argv, &pid, NULL, &child_stdout, NULL);
    246   EXPECT_EQ(mj_run_ret, 0);
    247 
    248   read_ret = read(child_stdout, buf, buf_len);
    249   EXPECT_GE(read_ret, 0);
    250   buf[read_ret] = '\0';
    251   EXPECT_STREQ(buf, "yes\n");
    252 
    253   waitpid(pid, &status, 0);
    254   ASSERT_TRUE(WIFEXITED(status));
    255   EXPECT_EQ(WEXITSTATUS(status), 0);
    256 
    257   minijail_close_open_fds(j);
    258   mj_run_ret = minijail_run_pid_pipes_no_preload(
    259       j, argv[0], argv, &pid, NULL, &child_stdout, NULL);
    260   EXPECT_EQ(mj_run_ret, 0);
    261 
    262   read_ret = read(child_stdout, buf, buf_len);
    263   EXPECT_GE(read_ret, 0);
    264   buf[read_ret] = '\0';
    265   EXPECT_STREQ(buf, "no\n");
    266 
    267   waitpid(pid, &status, 0);
    268   ASSERT_TRUE(WIFEXITED(status));
    269   EXPECT_EQ(WEXITSTATUS(status), 0);
    270 
    271   minijail_destroy(j);
    272 
    273   close(dev_null);
    274 }
    275 
    276 TEST(Test, parse_size) {
    277   size_t size;
    278 
    279   ASSERT_EQ(0, parse_size(&size, "42"));
    280   ASSERT_EQ(42U, size);
    281 
    282   ASSERT_EQ(0, parse_size(&size, "16K"));
    283   ASSERT_EQ(16384U, size);
    284 
    285   ASSERT_EQ(0, parse_size(&size, "1M"));
    286   ASSERT_EQ(1024U * 1024, size);
    287 
    288   uint64_t gigabyte = 1024ULL * 1024 * 1024;
    289   ASSERT_EQ(0, parse_size(&size, "3G"));
    290   ASSERT_EQ(3U, size / gigabyte);
    291   ASSERT_EQ(0U, size % gigabyte);
    292 
    293   ASSERT_EQ(0, parse_size(&size, "4294967294"));
    294   ASSERT_EQ(3U, size / gigabyte);
    295   ASSERT_EQ(gigabyte - 2, size % gigabyte);
    296 
    297 #if __WORDSIZE == 64
    298   uint64_t exabyte = gigabyte * 1024 * 1024 * 1024;
    299   ASSERT_EQ(0, parse_size(&size, "9E"));
    300   ASSERT_EQ(9U, size / exabyte);
    301   ASSERT_EQ(0U, size % exabyte);
    302 
    303   ASSERT_EQ(0, parse_size(&size, "15E"));
    304   ASSERT_EQ(15U, size / exabyte);
    305   ASSERT_EQ(0U, size % exabyte);
    306 
    307   ASSERT_EQ(0, parse_size(&size, "18446744073709551614"));
    308   ASSERT_EQ(15U, size / exabyte);
    309   ASSERT_EQ(exabyte - 2, size % exabyte);
    310 
    311   ASSERT_EQ(-ERANGE, parse_size(&size, "16E"));
    312   ASSERT_EQ(-ERANGE, parse_size(&size, "19E"));
    313   ASSERT_EQ(-EINVAL, parse_size(&size, "7GTPE"));
    314 #elif __WORDSIZE == 32
    315   ASSERT_EQ(-ERANGE, parse_size(&size, "5G"));
    316   ASSERT_EQ(-ERANGE, parse_size(&size, "9G"));
    317   ASSERT_EQ(-ERANGE, parse_size(&size, "9E"));
    318   ASSERT_EQ(-ERANGE, parse_size(&size, "7GTPE"));
    319 #endif
    320 
    321   ASSERT_EQ(-EINVAL, parse_size(&size, ""));
    322   ASSERT_EQ(-EINVAL, parse_size(&size, "14u"));
    323   ASSERT_EQ(-EINVAL, parse_size(&size, "14.2G"));
    324   ASSERT_EQ(-EINVAL, parse_size(&size, "-1G"));
    325   ASSERT_EQ(-EINVAL, parse_size(&size, "; /bin/rm -- "));
    326 }
    327