• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2016 The Chromium OS Authors. All rights reserved.
2  * Use of this source code is governed by a BSD-style license that can be
3  * found in the LICENSE file.
4  *
5  * Test platform independent logic of Minijail using gtest.
6  */
7 
8 #include <errno.h>
9 
10 #include <dirent.h>
11 #include <fcntl.h>
12 #include <sys/mount.h>
13 #include <sys/stat.h>
14 #include <sys/types.h>
15 #include <sys/wait.h>
16 #include <unistd.h>
17 
18 #include <gtest/gtest.h>
19 
20 #include <functional>
21 #include <map>
22 #include <set>
23 #include <string>
24 
25 #include "libminijail-private.h"
26 #include "libminijail.h"
27 #include "scoped_minijail.h"
28 #include "util.h"
29 
30 namespace {
31 
32 #if defined(__ANDROID__)
33 # define ROOT_PREFIX "/system"
34 #else
35 # define ROOT_PREFIX ""
36 #endif
37 
38 constexpr char kShellPath[] = ROOT_PREFIX "/bin/sh";
39 constexpr char kCatPath[] = ROOT_PREFIX "/bin/cat";
40 constexpr char kPreloadPath[] = "./libminijailpreload.so";
41 constexpr size_t kBufferSize = 128;
42 
GetProcessSubtreePids(pid_t root_pid)43 std::set<pid_t> GetProcessSubtreePids(pid_t root_pid) {
44   std::set<pid_t> pids{root_pid};
45   bool progress = false;
46 
47   do {
48     progress = false;
49     DIR* d = opendir("/proc");
50     if (!d)
51       pdie("opendir(\"/proc\")");
52 
53     struct dirent* dir_entry;
54     while ((dir_entry = readdir(d)) != nullptr) {
55       if (dir_entry->d_type != DT_DIR)
56         continue;
57       char* end;
58       const int pid = strtol(dir_entry->d_name, &end, 10);
59       if (*end != '\0')
60         continue;
61       std::string path = "/proc/" + std::to_string(pid) + "/stat";
62 
63       FILE* f = fopen(path.c_str(), "re");
64       if (!f)
65         pdie("fopen(%s)", path.c_str());
66       pid_t ppid;
67       int ret = fscanf(f, "%*d (%*[^)]) %*c %d", &ppid);
68       fclose(f);
69       if (ret != 1) {
70         continue;
71       }
72       if (pids.find(ppid) == pids.end())
73         continue;
74       progress |= pids.insert(pid).second;
75     }
76     closedir(d);
77   } while (progress);
78   return pids;
79 }
80 
GetNamespaces(pid_t pid,const std::vector<std::string> & namespace_names)81 std::map<std::string, std::string> GetNamespaces(
82     pid_t pid,
83     const std::vector<std::string>& namespace_names) {
84   std::map<std::string, std::string> namespaces;
85   char buf[kBufferSize];
86   for (const auto& namespace_name : namespace_names) {
87     std::string path = "/proc/" + std::to_string(pid) + "/ns/" + namespace_name;
88     ssize_t len = readlink(path.c_str(), buf, sizeof(buf));
89     if (len == -1)
90       pdie("readlink(\"%s\")", path.c_str());
91     namespaces.emplace(namespace_name, std::string(buf, len));
92   }
93   return namespaces;
94 }
95 
96 }  // namespace
97 
98 /* Prototypes needed only by test. */
99 size_t minijail_get_tmpfs_size(const struct minijail *);
100 
101 /* Silence unused variable warnings. */
TEST(silence,silence_unused)102 TEST(silence, silence_unused) {
103   EXPECT_STREQ(kLdPreloadEnvVar, kLdPreloadEnvVar);
104   EXPECT_STREQ(kFdEnvVar, kFdEnvVar);
105   EXPECT_STRNE(kFdEnvVar, kLdPreloadEnvVar);
106 }
107 
TEST(consumebytes,zero)108 TEST(consumebytes, zero) {
109   char buf[1024];
110   size_t len = sizeof(buf);
111   char *pos = &buf[0];
112   EXPECT_NE(nullptr, consumebytes(0, &pos, &len));
113   EXPECT_EQ(&buf[0], pos);
114   EXPECT_EQ(sizeof(buf), len);
115 }
116 
TEST(consumebytes,exact)117 TEST(consumebytes, exact) {
118   char buf[1024];
119   size_t len = sizeof(buf);
120   char *pos = &buf[0];
121   /* One past the end since it consumes the whole buffer. */
122   char *end = &buf[sizeof(buf)];
123   EXPECT_NE(nullptr, consumebytes(len, &pos, &len));
124   EXPECT_EQ((size_t)0, len);
125   EXPECT_EQ(end, pos);
126 }
127 
TEST(consumebytes,half)128 TEST(consumebytes, half) {
129   char buf[1024];
130   size_t len = sizeof(buf);
131   char *pos = &buf[0];
132   /* One past the end since it consumes the whole buffer. */
133   char *end = &buf[sizeof(buf) / 2];
134   EXPECT_NE(nullptr, consumebytes(len / 2, &pos, &len));
135   EXPECT_EQ(sizeof(buf) / 2, len);
136   EXPECT_EQ(end, pos);
137 }
138 
TEST(consumebytes,toolong)139 TEST(consumebytes, toolong) {
140   char buf[1024];
141   size_t len = sizeof(buf);
142   char *pos = &buf[0];
143   /* One past the end since it consumes the whole buffer. */
144   EXPECT_EQ(nullptr, consumebytes(len + 1, &pos, &len));
145   EXPECT_EQ(sizeof(buf), len);
146   EXPECT_EQ(&buf[0], pos);
147 }
148 
TEST(consumestr,zero)149 TEST(consumestr, zero) {
150   char buf[1024];
151   size_t len = 0;
152   char *pos = &buf[0];
153   memset(buf, 0xff, sizeof(buf));
154   EXPECT_EQ(nullptr, consumestr(&pos, &len));
155   EXPECT_EQ((size_t)0, len);
156   EXPECT_EQ(&buf[0], pos);
157 }
158 
TEST(consumestr,nonul)159 TEST(consumestr, nonul) {
160   char buf[1024];
161   size_t len = sizeof(buf);
162   char *pos = &buf[0];
163   memset(buf, 0xff, sizeof(buf));
164   EXPECT_EQ(nullptr, consumestr(&pos, &len));
165   EXPECT_EQ(sizeof(buf), len);
166   EXPECT_EQ(&buf[0], pos);
167 }
168 
TEST(consumestr,full)169 TEST(consumestr, full) {
170   char buf[1024];
171   size_t len = sizeof(buf);
172   char *pos = &buf[0];
173   memset(buf, 0xff, sizeof(buf));
174   buf[sizeof(buf)-1] = '\0';
175   EXPECT_EQ((void *)buf, consumestr(&pos, &len));
176   EXPECT_EQ((size_t)0, len);
177   EXPECT_EQ(&buf[sizeof(buf)], pos);
178 }
179 
TEST(consumestr,trailing_nul)180 TEST(consumestr, trailing_nul) {
181   char buf[1024];
182   size_t len = sizeof(buf) - 1;
183   char *pos = &buf[0];
184   memset(buf, 0xff, sizeof(buf));
185   buf[sizeof(buf)-1] = '\0';
186   EXPECT_EQ(nullptr, consumestr(&pos, &len));
187   EXPECT_EQ(sizeof(buf) - 1, len);
188   EXPECT_EQ(&buf[0], pos);
189 }
190 
191 class MarshalTest : public ::testing::Test {
192  protected:
SetUp()193   virtual void SetUp() {
194     m_ = minijail_new();
195     j_ = minijail_new();
196     size_ = minijail_size(m_);
197   }
TearDown()198   virtual void TearDown() {
199     minijail_destroy(m_);
200     minijail_destroy(j_);
201   }
202 
203   char buf_[4096];
204   struct minijail *m_;
205   struct minijail *j_;
206   size_t size_;
207 };
208 
TEST_F(MarshalTest,empty)209 TEST_F(MarshalTest, empty) {
210   ASSERT_EQ(0, minijail_marshal(m_, buf_, sizeof(buf_)));
211   EXPECT_EQ(0, minijail_unmarshal(j_, buf_, size_));
212 }
213 
214 TEST_F(MarshalTest, 0xff) {
215   memset(buf_, 0xff, sizeof(buf_));
216   /* Should fail on the first consumestr since a NUL will never be found. */
217   EXPECT_EQ(-EINVAL, minijail_unmarshal(j_, buf_, sizeof(buf_)));
218 }
219 
TEST(Test,minijail_run_pid_pipes)220 TEST(Test, minijail_run_pid_pipes) {
221   constexpr char teststr[] = "test\n";
222 
223   struct minijail* j = minijail_new();
224   minijail_set_preload_path(j, kPreloadPath);
225 
226   char* argv[4];
227   argv[0] = const_cast<char*>(kCatPath);
228   argv[1] = nullptr;
229   pid_t pid;
230   int child_stdin, child_stdout;
231   int mj_run_ret = minijail_run_pid_pipes(j, argv[0], argv, &pid, &child_stdin,
232                                           &child_stdout, nullptr);
233   EXPECT_EQ(mj_run_ret, 0);
234 
235   const size_t teststr_len = strlen(teststr);
236   ssize_t write_ret = write(child_stdin, teststr, teststr_len);
237   EXPECT_EQ(write_ret, static_cast<ssize_t>(teststr_len));
238 
239   char buf[kBufferSize];
240   ssize_t read_ret = read(child_stdout, buf, 8);
241   EXPECT_EQ(read_ret, static_cast<ssize_t>(teststr_len));
242   buf[teststr_len] = 0;
243   EXPECT_EQ(strcmp(buf, teststr), 0);
244 
245   int status;
246   EXPECT_EQ(kill(pid, SIGTERM), 0);
247   waitpid(pid, &status, 0);
248   ASSERT_TRUE(WIFSIGNALED(status));
249   EXPECT_EQ(WTERMSIG(status), SIGTERM);
250 
251   argv[0] = const_cast<char*>(kShellPath);
252   argv[1] = "-c";
253   argv[2] = "echo test >&2";
254   argv[3] = nullptr;
255   int child_stderr;
256   mj_run_ret = minijail_run_pid_pipes(j, argv[0], argv, &pid, &child_stdin,
257                                       &child_stdout, &child_stderr);
258   EXPECT_EQ(mj_run_ret, 0);
259 
260   read_ret = read(child_stderr, buf, sizeof(buf));
261   EXPECT_GE(read_ret, static_cast<ssize_t>(teststr_len));
262 
263   waitpid(pid, &status, 0);
264   ASSERT_TRUE(WIFEXITED(status));
265   EXPECT_EQ(WEXITSTATUS(status), 0);
266 
267   minijail_destroy(j);
268 }
269 
TEST(Test,minijail_run_pid_pipes_no_preload)270 TEST(Test, minijail_run_pid_pipes_no_preload) {
271   pid_t pid;
272   int child_stdin, child_stdout, child_stderr;
273   int mj_run_ret;
274   ssize_t write_ret, read_ret;
275   char buf[kBufferSize];
276   int status;
277   char teststr[] = "test\n";
278   size_t teststr_len = strlen(teststr);
279   char *argv[4];
280 
281   struct minijail *j = minijail_new();
282 
283   argv[0] = (char*)kCatPath;
284   argv[1] = NULL;
285   mj_run_ret = minijail_run_pid_pipes_no_preload(j, argv[0], argv,
286                                                  &pid,
287                                                  &child_stdin, &child_stdout,
288                                                  NULL);
289   EXPECT_EQ(mj_run_ret, 0);
290 
291   write_ret = write(child_stdin, teststr, teststr_len);
292   EXPECT_EQ(write_ret, (int)teststr_len);
293 
294   read_ret = read(child_stdout, buf, 8);
295   EXPECT_EQ(read_ret, (int)teststr_len);
296   buf[teststr_len] = 0;
297   EXPECT_EQ(strcmp(buf, teststr), 0);
298 
299   EXPECT_EQ(kill(pid, SIGTERM), 0);
300   waitpid(pid, &status, 0);
301   ASSERT_TRUE(WIFSIGNALED(status));
302   EXPECT_EQ(WTERMSIG(status), SIGTERM);
303 
304   argv[0] = (char*)kShellPath;
305   argv[1] = "-c";
306   argv[2] = "echo test >&2";
307   argv[3] = NULL;
308   mj_run_ret = minijail_run_pid_pipes_no_preload(j, argv[0], argv, &pid,
309                                                  &child_stdin, &child_stdout,
310                                                  &child_stderr);
311   EXPECT_EQ(mj_run_ret, 0);
312 
313   read_ret = read(child_stderr, buf, sizeof(buf));
314   EXPECT_GE(read_ret, (int)teststr_len);
315 
316   waitpid(pid, &status, 0);
317   ASSERT_TRUE(WIFEXITED(status));
318   EXPECT_EQ(WEXITSTATUS(status), 0);
319 
320   minijail_destroy(j);
321 }
322 
TEST(Test,minijail_run_env_pid_pipes_no_preload)323 TEST(Test, minijail_run_env_pid_pipes_no_preload) {
324   pid_t pid;
325   int child_stdin, child_stdout, child_stderr;
326   int mj_run_ret;
327   ssize_t read_ret;
328   char buf[kBufferSize];
329   int status;
330   char test_envvar[] = "TEST_VAR=test";
331   size_t testvar_len = strlen("test");
332   char *argv[4];
333   char *envp[2];
334 
335   struct minijail *j = minijail_new();
336 
337   argv[0] = (char*)kShellPath;
338   argv[1] = "-c";
339   argv[2] = "echo \"${TEST_PARENT+set}|${TEST_VAR}\"";
340   argv[3] = NULL;
341 
342   envp[0] = test_envvar;
343   envp[1] = NULL;
344 
345   // Set a canary env var in the parent that should not be present in the child.
346   ASSERT_EQ(setenv("TEST_PARENT", "test", 1 /*overwrite*/), 0);
347 
348   mj_run_ret = minijail_run_env_pid_pipes_no_preload(
349       j, argv[0], argv, envp, &pid, &child_stdin, &child_stdout, &child_stderr);
350   EXPECT_EQ(mj_run_ret, 0);
351 
352   read_ret = read(child_stdout, buf, sizeof(buf));
353   EXPECT_GE(read_ret, (int)testvar_len);
354 
355   EXPECT_EQ("|test\n", std::string(buf));
356 
357   EXPECT_EQ(waitpid(pid, &status, 0), pid);
358   ASSERT_TRUE(WIFEXITED(status));
359   EXPECT_EQ(WEXITSTATUS(status), 0);
360 
361   minijail_destroy(j);
362 }
363 
TEST(Test,test_minijail_no_fd_leaks)364 TEST(Test, test_minijail_no_fd_leaks) {
365   pid_t pid;
366   int child_stdout;
367   int mj_run_ret;
368   ssize_t read_ret;
369   char buf[kBufferSize];
370   char script[kBufferSize];
371   int status;
372   char *argv[4];
373 
374   int dev_null = open("/dev/null", O_RDONLY);
375   ASSERT_NE(dev_null, -1);
376   snprintf(script,
377            sizeof(script),
378            "[ -e /proc/self/fd/%d ] && echo yes || echo no",
379            dev_null);
380 
381   struct minijail *j = minijail_new();
382 
383   argv[0] = (char*)kShellPath;
384   argv[1] = "-c";
385   argv[2] = script;
386   argv[3] = NULL;
387   mj_run_ret = minijail_run_pid_pipes_no_preload(
388       j, argv[0], argv, &pid, NULL, &child_stdout, NULL);
389   EXPECT_EQ(mj_run_ret, 0);
390 
391   read_ret = read(child_stdout, buf, sizeof(buf));
392   EXPECT_GE(read_ret, 0);
393   buf[read_ret] = '\0';
394   EXPECT_STREQ(buf, "yes\n");
395 
396   waitpid(pid, &status, 0);
397   ASSERT_TRUE(WIFEXITED(status));
398   EXPECT_EQ(WEXITSTATUS(status), 0);
399 
400   minijail_close_open_fds(j);
401   mj_run_ret = minijail_run_pid_pipes_no_preload(
402       j, argv[0], argv, &pid, NULL, &child_stdout, NULL);
403   EXPECT_EQ(mj_run_ret, 0);
404 
405   read_ret = read(child_stdout, buf, sizeof(buf));
406   EXPECT_GE(read_ret, 0);
407   buf[read_ret] = '\0';
408   EXPECT_STREQ(buf, "no\n");
409 
410   waitpid(pid, &status, 0);
411   ASSERT_TRUE(WIFEXITED(status));
412   EXPECT_EQ(WEXITSTATUS(status), 0);
413 
414   minijail_destroy(j);
415 
416   close(dev_null);
417 }
418 
TEST(Test,test_minijail_fork)419 TEST(Test, test_minijail_fork) {
420   pid_t mj_fork_ret;
421   int status;
422   int pipe_fds[2];
423   ssize_t pid_size = sizeof(mj_fork_ret);
424 
425   struct minijail *j = minijail_new();
426 
427   ASSERT_EQ(pipe(pipe_fds), 0);
428 
429   mj_fork_ret = minijail_fork(j);
430   ASSERT_GE(mj_fork_ret, 0);
431   if (mj_fork_ret == 0) {
432     pid_t pid_in_parent;
433     // Wait for the parent to tell us the pid in the parent namespace.
434     ASSERT_EQ(read(pipe_fds[0], &pid_in_parent, pid_size), pid_size);
435     ASSERT_EQ(pid_in_parent, getpid());
436     minijail_destroy(j);
437     exit(0);
438   }
439 
440   EXPECT_EQ(write(pipe_fds[1], &mj_fork_ret, pid_size), pid_size);
441   waitpid(mj_fork_ret, &status, 0);
442   ASSERT_TRUE(WIFEXITED(status));
443   EXPECT_EQ(WEXITSTATUS(status), 0);
444 
445   minijail_destroy(j);
446 }
447 
early_exit(void * payload)448 static int early_exit(void* payload) {
449   exit(static_cast<int>(reinterpret_cast<intptr_t>(payload)));
450 }
451 
TEST(Test,test_minijail_callback)452 TEST(Test, test_minijail_callback) {
453   pid_t pid;
454   int mj_run_ret;
455   int status;
456   char *argv[2];
457   int exit_code = 42;
458 
459   struct minijail *j = minijail_new();
460 
461   status =
462       minijail_add_hook(j, &early_exit, reinterpret_cast<void *>(exit_code),
463                         MINIJAIL_HOOK_EVENT_PRE_DROP_CAPS);
464   EXPECT_EQ(status, 0);
465 
466   argv[0] = (char*)kCatPath;
467   argv[1] = NULL;
468   mj_run_ret = minijail_run_pid_pipes_no_preload(j, argv[0], argv, &pid, NULL,
469                                                  NULL, NULL);
470   EXPECT_EQ(mj_run_ret, 0);
471 
472   status = minijail_wait(j);
473   EXPECT_EQ(status, exit_code);
474 
475   minijail_destroy(j);
476 }
477 
TEST(Test,test_minijail_preserve_fd)478 TEST(Test, test_minijail_preserve_fd) {
479   int mj_run_ret;
480   int status;
481   char *argv[2];
482   char teststr[] = "test\n";
483   size_t teststr_len = strlen(teststr);
484   int read_pipe[2];
485   int write_pipe[2];
486   char buf[1024];
487 
488   struct minijail *j = minijail_new();
489 
490   status = pipe(read_pipe);
491   ASSERT_EQ(status, 0);
492   status = pipe(write_pipe);
493   ASSERT_EQ(status, 0);
494 
495   status = minijail_preserve_fd(j, write_pipe[0], STDIN_FILENO);
496   ASSERT_EQ(status, 0);
497   status = minijail_preserve_fd(j, read_pipe[1], STDOUT_FILENO);
498   ASSERT_EQ(status, 0);
499   minijail_close_open_fds(j);
500 
501   argv[0] = (char*)kCatPath;
502   argv[1] = NULL;
503   mj_run_ret = minijail_run_no_preload(j, argv[0], argv);
504   EXPECT_EQ(mj_run_ret, 0);
505 
506   close(write_pipe[0]);
507   status = write(write_pipe[1], teststr, teststr_len);
508   EXPECT_EQ(status, (int)teststr_len);
509   close(write_pipe[1]);
510 
511   close(read_pipe[1]);
512   status = read(read_pipe[0], buf, 8);
513   EXPECT_EQ(status, (int)teststr_len);
514   buf[teststr_len] = 0;
515   EXPECT_EQ(strcmp(buf, teststr), 0);
516 
517   status = minijail_wait(j);
518   EXPECT_EQ(status, 0);
519 
520   minijail_destroy(j);
521 }
522 
TEST(Test,test_minijail_reset_signal_mask)523 TEST(Test, test_minijail_reset_signal_mask) {
524   struct minijail *j = minijail_new();
525 
526   sigset_t original_signal_mask;
527   {
528     sigset_t signal_mask;
529     ASSERT_EQ(0, sigemptyset(&signal_mask));
530     ASSERT_EQ(0, sigaddset(&signal_mask, SIGUSR1));
531     ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &signal_mask, &original_signal_mask));
532   }
533 
534   minijail_reset_signal_mask(j);
535 
536   pid_t mj_fork_ret = minijail_fork(j);
537   ASSERT_GE(mj_fork_ret, 0);
538   if (mj_fork_ret == 0) {
539     sigset_t signal_mask;
540     ASSERT_EQ(0, sigprocmask(SIG_SETMASK, NULL, &signal_mask));
541     ASSERT_EQ(0, sigismember(&signal_mask, SIGUSR1));
542     minijail_destroy(j);
543     exit(0);
544   }
545 
546   ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &original_signal_mask, NULL));
547 
548   int status;
549   waitpid(mj_fork_ret, &status, 0);
550   ASSERT_TRUE(WIFEXITED(status));
551   EXPECT_EQ(WEXITSTATUS(status), 0);
552 
553   minijail_destroy(j);
554 }
555 
TEST(Test,test_minijail_reset_signal_handlers)556 TEST(Test, test_minijail_reset_signal_handlers) {
557   struct minijail *j = minijail_new();
558 
559   ASSERT_EQ(SIG_DFL, signal(SIGUSR1, SIG_DFL));
560   ASSERT_EQ(SIG_DFL, signal(SIGUSR1, SIG_IGN));
561   ASSERT_EQ(SIG_IGN, signal(SIGUSR1, SIG_IGN));
562 
563   minijail_reset_signal_handlers(j);
564 
565   pid_t mj_fork_ret = minijail_fork(j);
566   ASSERT_GE(mj_fork_ret, 0);
567   if (mj_fork_ret == 0) {
568     ASSERT_EQ(SIG_DFL, signal(SIGUSR1, SIG_DFL));
569     minijail_destroy(j);
570     exit(0);
571   }
572 
573   ASSERT_NE(SIG_ERR, signal(SIGUSR1, SIG_DFL));
574 
575   int status;
576   waitpid(mj_fork_ret, &status, 0);
577   ASSERT_TRUE(WIFEXITED(status));
578   EXPECT_EQ(WEXITSTATUS(status), 0);
579 
580   minijail_destroy(j);
581 }
582 
583 namespace {
584 
585 // Tests that require userns access.
586 // Android unit tests don't currently support entering user namespaces as
587 // unprivileged users due to having an older kernel.  Chrome OS unit tests
588 // don't support it either due to being in a chroot environment (see man 2
589 // clone for more information about failure modes with the CLONE_NEWUSER flag).
590 class NamespaceTest : public ::testing::Test {
591  protected:
SetUpTestCase()592   static void SetUpTestCase() {
593     userns_supported_ = UsernsSupported();
594   }
595 
596   // Whether userns is supported.
597   static bool userns_supported_;
598 
UsernsSupported()599   static bool UsernsSupported() {
600     pid_t pid = fork();
601     if (pid == -1)
602       pdie("could not fork");
603 
604     if (pid == 0)
605       _exit(unshare(CLONE_NEWUSER) == 0 ? 0 : 1);
606 
607     int status;
608     if (waitpid(pid, &status, 0) < 0)
609       pdie("could not wait");
610 
611     if (!WIFEXITED(status))
612       die("child did not exit properly: %#x", status);
613 
614     bool ret = WEXITSTATUS(status) == 0;
615     if (!ret)
616       warn("Skipping userns related tests");
617     return ret;
618   }
619 };
620 
621 bool NamespaceTest::userns_supported_;
622 
623 }  // namespace
624 
TEST_F(NamespaceTest,test_tmpfs_userns)625 TEST_F(NamespaceTest, test_tmpfs_userns) {
626   int mj_run_ret;
627   int status;
628   char *argv[4];
629   char uidmap[kBufferSize], gidmap[kBufferSize];
630   constexpr uid_t kTargetUid = 1000;  // Any non-zero value will do.
631   constexpr gid_t kTargetGid = 1000;
632 
633   if (!userns_supported_) {
634     SUCCEED();
635     return;
636   }
637 
638   struct minijail *j = minijail_new();
639 
640   minijail_namespace_pids(j);
641   minijail_namespace_vfs(j);
642   minijail_mount_tmp(j);
643   minijail_run_as_init(j);
644 
645   // Perform userns mapping.
646   minijail_namespace_user(j);
647   snprintf(uidmap, sizeof(uidmap), "%d %d 1", kTargetUid, getuid());
648   snprintf(gidmap, sizeof(gidmap), "%d %d 1", kTargetGid, getgid());
649   minijail_change_uid(j, kTargetUid);
650   minijail_change_gid(j, kTargetGid);
651   minijail_uidmap(j, uidmap);
652   minijail_gidmap(j, gidmap);
653   minijail_namespace_user_disable_setgroups(j);
654 
655   argv[0] = (char*)kShellPath;
656   argv[1] = "-c";
657   argv[2] = "exec touch /tmp/foo";
658   argv[3] = NULL;
659   mj_run_ret = minijail_run_no_preload(j, argv[0], argv);
660   EXPECT_EQ(mj_run_ret, 0);
661 
662   status = minijail_wait(j);
663   EXPECT_EQ(status, 0);
664 
665   minijail_destroy(j);
666 }
667 
TEST_F(NamespaceTest,test_namespaces)668 TEST_F(NamespaceTest, test_namespaces) {
669   constexpr char teststr[] = "test\n";
670 
671   if (!userns_supported_) {
672     SUCCEED();
673     return;
674   }
675 
676   std::string uidmap = "0 " + std::to_string(getuid()) + " 1";
677   std::string gidmap = "0 " + std::to_string(getgid()) + " 1";
678 
679   const std::vector<std::string> namespace_names = {"pid", "mnt",    "user",
680                                                     "net", "cgroup", "uts"};
681   // Grab the set of namespaces outside the container.
682   std::map<std::string, std::string> init_namespaces =
683       GetNamespaces(getpid(), namespace_names);
684   std::function<void(struct minijail*)> test_functions[] = {
685       [](struct minijail* j attribute_unused) {},
686       [](struct minijail* j) {
687         minijail_mount(j, "/", "/", "", MS_BIND | MS_REC | MS_RDONLY);
688         minijail_enter_pivot_root(j, "/tmp");
689       },
690       [](struct minijail* j) { minijail_enter_chroot(j, "/"); },
691   };
692 
693   // This test is run with and without the preload library.
694   for (const auto& run_function :
695        {minijail_run_pid_pipes, minijail_run_pid_pipes_no_preload}) {
696     for (const auto& test_function : test_functions) {
697       ScopedMinijail j(minijail_new());
698       minijail_set_preload_path(j.get(), kPreloadPath);
699 
700       // Enter all the namespaces we can.
701       minijail_namespace_cgroups(j.get());
702       minijail_namespace_net(j.get());
703       minijail_namespace_pids(j.get());
704       minijail_namespace_user(j.get());
705       minijail_namespace_vfs(j.get());
706       minijail_namespace_uts(j.get());
707 
708       // Set up the user namespace.
709       minijail_uidmap(j.get(), uidmap.c_str());
710       minijail_gidmap(j.get(), gidmap.c_str());
711       minijail_namespace_user_disable_setgroups(j.get());
712 
713       minijail_close_open_fds(j.get());
714       test_function(j.get());
715 
716       const char* argv[] = {kCatPath, nullptr};
717       pid_t container_pid;
718       int child_stdin, child_stdout;
719       int mj_run_ret =
720           run_function(j.get(), argv[0], const_cast<char* const*>(argv),
721                        &container_pid, &child_stdin, &child_stdout, nullptr);
722       EXPECT_EQ(mj_run_ret, 0);
723 
724       // Send some data to stdin and read it back to ensure that the child
725       // process is running.
726       const size_t teststr_len = strlen(teststr);
727       ssize_t write_ret = write(child_stdin, teststr, teststr_len);
728       EXPECT_EQ(write_ret, static_cast<ssize_t>(teststr_len));
729 
730       char buf[kBufferSize];
731       ssize_t read_ret = read(child_stdout, buf, 8);
732       EXPECT_EQ(read_ret, static_cast<ssize_t>(teststr_len));
733       buf[teststr_len] = 0;
734       EXPECT_EQ(strcmp(buf, teststr), 0);
735 
736       // Grab the set of namespaces in every container process. They must not
737       // match the ones in the init namespace, and they must all match each
738       // other.
739       std::map<std::string, std::string> container_namespaces =
740           GetNamespaces(container_pid, namespace_names);
741       EXPECT_NE(container_namespaces, init_namespaces);
742       for (pid_t pid : GetProcessSubtreePids(container_pid))
743         EXPECT_EQ(container_namespaces, GetNamespaces(pid, namespace_names));
744 
745       EXPECT_EQ(0, close(child_stdin));
746 
747       int status = minijail_wait(j.get());
748       EXPECT_EQ(status, 0);
749     }
750   }
751 }
752 
TEST_F(NamespaceTest,test_enter_ns)753 TEST_F(NamespaceTest, test_enter_ns) {
754   char uidmap[kBufferSize], gidmap[kBufferSize];
755 
756   if (!userns_supported_) {
757     SUCCEED();
758     return;
759   }
760 
761   // We first create a child in a new userns so we have privs to run more tests.
762   // We can't combine the steps as the kernel disallows many resource sharing
763   // from outside the userns.
764   struct minijail *j = minijail_new();
765 
766   minijail_namespace_vfs(j);
767   minijail_namespace_pids(j);
768   minijail_run_as_init(j);
769 
770   // Perform userns mapping.
771   minijail_namespace_user(j);
772   snprintf(uidmap, sizeof(uidmap), "0 %d 1", getuid());
773   snprintf(gidmap, sizeof(gidmap), "0 %d 1", getgid());
774   minijail_uidmap(j, uidmap);
775   minijail_gidmap(j, gidmap);
776   minijail_namespace_user_disable_setgroups(j);
777 
778   pid_t pid = minijail_fork(j);
779   if (pid == 0) {
780     // Child.
781     minijail_destroy(j);
782 
783     // Create new namespaces inside this userns which we may enter.
784     j = minijail_new();
785     minijail_namespace_net(j);
786     minijail_namespace_vfs(j);
787     pid = minijail_fork(j);
788     if (pid == 0) {
789       // Child.
790       minijail_destroy(j);
791 
792       // Finally enter those namespaces.
793       j = minijail_new();
794 
795       // We need to get the absolute path because entering a new mntns will
796       // implicitly chdir(/) for us.
797       char *path = realpath(kPreloadPath, nullptr);
798       ASSERT_NE(nullptr, path);
799       minijail_set_preload_path(j, path);
800 
801       minijail_namespace_net(j);
802       minijail_namespace_vfs(j);
803 
804       minijail_namespace_enter_net(j, "/proc/self/ns/net");
805       minijail_namespace_enter_vfs(j, "/proc/self/ns/mnt");
806 
807       char *argv[] = {"/bin/true", nullptr};
808       EXPECT_EQ(0, minijail_run(j, argv[0], argv));
809       EXPECT_EQ(0, minijail_wait(j));
810       minijail_destroy(j);
811       exit(0);
812     } else {
813       ASSERT_GT(pid, 0);
814       EXPECT_EQ(0, minijail_wait(j));
815       minijail_destroy(j);
816       exit(0);
817     }
818   } else {
819     ASSERT_GT(pid, 0);
820     EXPECT_EQ(0, minijail_wait(j));
821     minijail_destroy(j);
822   }
823 }
824 
TEST(Test,parse_size)825 TEST(Test, parse_size) {
826   size_t size;
827 
828   ASSERT_EQ(0, parse_size(&size, "42"));
829   ASSERT_EQ(42U, size);
830 
831   ASSERT_EQ(0, parse_size(&size, "16K"));
832   ASSERT_EQ(16384U, size);
833 
834   ASSERT_EQ(0, parse_size(&size, "1M"));
835   ASSERT_EQ(1024U * 1024, size);
836 
837   uint64_t gigabyte = 1024ULL * 1024 * 1024;
838   ASSERT_EQ(0, parse_size(&size, "3G"));
839   ASSERT_EQ(3U, size / gigabyte);
840   ASSERT_EQ(0U, size % gigabyte);
841 
842   ASSERT_EQ(0, parse_size(&size, "4294967294"));
843   ASSERT_EQ(3U, size / gigabyte);
844   ASSERT_EQ(gigabyte - 2, size % gigabyte);
845 
846 #if __WORDSIZE == 64
847   uint64_t exabyte = gigabyte * 1024 * 1024 * 1024;
848   ASSERT_EQ(0, parse_size(&size, "9E"));
849   ASSERT_EQ(9U, size / exabyte);
850   ASSERT_EQ(0U, size % exabyte);
851 
852   ASSERT_EQ(0, parse_size(&size, "15E"));
853   ASSERT_EQ(15U, size / exabyte);
854   ASSERT_EQ(0U, size % exabyte);
855 
856   ASSERT_EQ(0, parse_size(&size, "18446744073709551614"));
857   ASSERT_EQ(15U, size / exabyte);
858   ASSERT_EQ(exabyte - 2, size % exabyte);
859 
860   ASSERT_EQ(-ERANGE, parse_size(&size, "16E"));
861   ASSERT_EQ(-ERANGE, parse_size(&size, "19E"));
862   ASSERT_EQ(-EINVAL, parse_size(&size, "7GTPE"));
863 #elif __WORDSIZE == 32
864   ASSERT_EQ(-ERANGE, parse_size(&size, "5G"));
865   ASSERT_EQ(-ERANGE, parse_size(&size, "9G"));
866   ASSERT_EQ(-ERANGE, parse_size(&size, "9E"));
867   ASSERT_EQ(-ERANGE, parse_size(&size, "7GTPE"));
868 #endif
869 
870   ASSERT_EQ(-EINVAL, parse_size(&size, ""));
871   ASSERT_EQ(-EINVAL, parse_size(&size, "14u"));
872   ASSERT_EQ(-EINVAL, parse_size(&size, "14.2G"));
873   ASSERT_EQ(-EINVAL, parse_size(&size, "-1G"));
874   ASSERT_EQ(-EINVAL, parse_size(&size, "; /bin/rm -- "));
875 }
876