• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium 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 #define _CRT_SECURE_NO_WARNINGS
6 
7 #include <stddef.h>
8 #include <stdint.h>
9 
10 #include <limits>
11 
12 #include "base/command_line.h"
13 #include "base/debug/alias.h"
14 #include "base/debug/stack_trace.h"
15 #include "base/files/file_enumerator.h"
16 #include "base/files/file_path.h"
17 #include "base/files/file_util.h"
18 #include "base/files/scoped_file.h"
19 #include "base/logging.h"
20 #include "base/macros.h"
21 #include "base/path_service.h"
22 #include "base/posix/eintr_wrapper.h"
23 #include "base/process/kill.h"
24 #include "base/process/launch.h"
25 #include "base/process/memory.h"
26 #include "base/process/process.h"
27 #include "base/process/process_metrics.h"
28 #include "base/strings/string_number_conversions.h"
29 #include "base/strings/utf_string_conversions.h"
30 #include "base/synchronization/waitable_event.h"
31 #include "base/test/multiprocess_test.h"
32 #include "base/test/scoped_task_environment.h"
33 #include "base/test/test_timeouts.h"
34 #include "base/threading/platform_thread.h"
35 #include "base/threading/thread.h"
36 #include "build/build_config.h"
37 #include "testing/gtest/include/gtest/gtest.h"
38 #include "testing/multiprocess_func_list.h"
39 
40 #if defined(OS_LINUX)
41 #include <malloc.h>
42 #include <sched.h>
43 #include <sys/syscall.h>
44 #endif
45 #if defined(OS_POSIX)
46 #include <sys/resource.h>
47 #endif
48 #if defined(OS_POSIX)
49 #include <dlfcn.h>
50 #include <errno.h>
51 #include <sched.h>
52 #include <signal.h>
53 #include <sys/wait.h>
54 #include <unistd.h>
55 #endif
56 #if defined(OS_POSIX) || defined(OS_FUCHSIA)
57 #include <fcntl.h>
58 #include <sys/socket.h>
59 #include <sys/types.h>
60 #endif
61 #if defined(OS_WIN)
62 #include <windows.h>
63 #endif
64 #if defined(OS_MACOSX)
65 #include <mach/vm_param.h>
66 #include <malloc/malloc.h>
67 #endif
68 #if defined(OS_ANDROID)
69 #include "third_party/lss/linux_syscall_support.h"
70 #endif
71 #if defined(OS_FUCHSIA)
72 #include <lib/fdio/limits.h>
73 #include <zircon/process.h>
74 #include <zircon/processargs.h>
75 #include <zircon/syscalls.h>
76 #include "base/base_paths_fuchsia.h"
77 #include "base/files/scoped_temp_dir.h"
78 #include "base/fuchsia/file_utils.h"
79 #include "base/fuchsia/fuchsia_logging.h"
80 #endif
81 
82 namespace base {
83 
84 namespace {
85 
86 const char kSignalFileSlow[] = "SlowChildProcess.die";
87 const char kSignalFileKill[] = "KilledChildProcess.die";
88 const char kTestHelper[] = "test_child_process";
89 
90 #if defined(OS_POSIX)
91 const char kSignalFileTerm[] = "TerminatedChildProcess.die";
92 #endif
93 
94 #if defined(OS_FUCHSIA)
95 const char kSignalFileClone[] = "ClonedTmpDir.die";
96 const char kDataDirHasStaged[] = "DataDirHasStaged.die";
97 const char kFooDirHasStaged[] = "FooDirHasStaged.die";
98 const char kFooDirDoesNotHaveStaged[] = "FooDirDoesNotHaveStaged.die";
99 #endif
100 
101 #if defined(OS_WIN)
102 const int kExpectedStillRunningExitCode = 0x102;
103 const int kExpectedKilledExitCode = 1;
104 #elif defined(OS_POSIX) || defined(OS_FUCHSIA)
105 const int kExpectedStillRunningExitCode = 0;
106 #endif
107 
108 // Sleeps until file filename is created.
WaitToDie(const char * filename)109 void WaitToDie(const char* filename) {
110   FILE* fp;
111   do {
112     PlatformThread::Sleep(TimeDelta::FromMilliseconds(10));
113     fp = fopen(filename, "r");
114   } while (!fp);
115   fclose(fp);
116 }
117 
118 // Signals children they should die now.
SignalChildren(const char * filename)119 void SignalChildren(const char* filename) {
120   FILE* fp = fopen(filename, "w");
121   fclose(fp);
122 }
123 
124 // Using a pipe to the child to wait for an event was considered, but
125 // there were cases in the past where pipes caused problems (other
126 // libraries closing the fds, child deadlocking). This is a simple
127 // case, so it's not worth the risk.  Using wait loops is discouraged
128 // in most instances.
WaitForChildTermination(ProcessHandle handle,int * exit_code)129 TerminationStatus WaitForChildTermination(ProcessHandle handle,
130                                           int* exit_code) {
131   // Now we wait until the result is something other than STILL_RUNNING.
132   TerminationStatus status = TERMINATION_STATUS_STILL_RUNNING;
133   const TimeDelta kInterval = TimeDelta::FromMilliseconds(20);
134   TimeDelta waited;
135   do {
136     status = GetTerminationStatus(handle, exit_code);
137     PlatformThread::Sleep(kInterval);
138     waited += kInterval;
139   } while (status == TERMINATION_STATUS_STILL_RUNNING &&
140            waited < TestTimeouts::action_max_timeout());
141 
142   return status;
143 }
144 
145 }  // namespace
146 
147 const int kSuccess = 0;
148 
149 class ProcessUtilTest : public MultiProcessTest {
150  public:
SetUp()151   void SetUp() override {
152     ASSERT_TRUE(PathService::Get(DIR_ASSETS, &test_helper_path_));
153     test_helper_path_ = test_helper_path_.AppendASCII(kTestHelper);
154   }
155 
156 #if defined(OS_POSIX) || defined(OS_FUCHSIA)
157   // Spawn a child process that counts how many file descriptors are open.
158   int CountOpenFDsInChild();
159 #endif
160   // Converts the filename to a platform specific filepath.
161   // On Android files can not be created in arbitrary directories.
162   static std::string GetSignalFilePath(const char* filename);
163 
164  protected:
165   base::FilePath test_helper_path_;
166 };
167 
GetSignalFilePath(const char * filename)168 std::string ProcessUtilTest::GetSignalFilePath(const char* filename) {
169 #if defined(OS_ANDROID) || defined(OS_FUCHSIA)
170   FilePath tmp_dir;
171   PathService::Get(DIR_TEMP, &tmp_dir);
172   tmp_dir = tmp_dir.Append(filename);
173   return tmp_dir.value();
174 #else
175   return filename;
176 #endif
177 }
178 
MULTIPROCESS_TEST_MAIN(SimpleChildProcess)179 MULTIPROCESS_TEST_MAIN(SimpleChildProcess) {
180   return kSuccess;
181 }
182 
183 // TODO(viettrungluu): This should be in a "MultiProcessTestTest".
TEST_F(ProcessUtilTest,SpawnChild)184 TEST_F(ProcessUtilTest, SpawnChild) {
185   Process process = SpawnChild("SimpleChildProcess");
186   ASSERT_TRUE(process.IsValid());
187   int exit_code;
188   EXPECT_TRUE(process.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(),
189                                              &exit_code));
190 }
191 
MULTIPROCESS_TEST_MAIN(SlowChildProcess)192 MULTIPROCESS_TEST_MAIN(SlowChildProcess) {
193   WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileSlow).c_str());
194   return kSuccess;
195 }
196 
TEST_F(ProcessUtilTest,KillSlowChild)197 TEST_F(ProcessUtilTest, KillSlowChild) {
198   const std::string signal_file =
199       ProcessUtilTest::GetSignalFilePath(kSignalFileSlow);
200   remove(signal_file.c_str());
201   Process process = SpawnChild("SlowChildProcess");
202   ASSERT_TRUE(process.IsValid());
203   SignalChildren(signal_file.c_str());
204   int exit_code;
205   EXPECT_TRUE(process.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(),
206                                              &exit_code));
207   remove(signal_file.c_str());
208 }
209 
210 // Times out on Linux and Win, flakes on other platforms, http://crbug.com/95058
TEST_F(ProcessUtilTest,DISABLED_GetTerminationStatusExit)211 TEST_F(ProcessUtilTest, DISABLED_GetTerminationStatusExit) {
212   const std::string signal_file =
213       ProcessUtilTest::GetSignalFilePath(kSignalFileSlow);
214   remove(signal_file.c_str());
215   Process process = SpawnChild("SlowChildProcess");
216   ASSERT_TRUE(process.IsValid());
217 
218   int exit_code = 42;
219   EXPECT_EQ(TERMINATION_STATUS_STILL_RUNNING,
220             GetTerminationStatus(process.Handle(), &exit_code));
221   EXPECT_EQ(kExpectedStillRunningExitCode, exit_code);
222 
223   SignalChildren(signal_file.c_str());
224   exit_code = 42;
225   TerminationStatus status =
226       WaitForChildTermination(process.Handle(), &exit_code);
227   EXPECT_EQ(TERMINATION_STATUS_NORMAL_TERMINATION, status);
228   EXPECT_EQ(kSuccess, exit_code);
229   remove(signal_file.c_str());
230 }
231 
232 #if defined(OS_FUCHSIA)
233 
MULTIPROCESS_TEST_MAIN(CheckDataDirHasStaged)234 MULTIPROCESS_TEST_MAIN(CheckDataDirHasStaged) {
235   if (!PathExists(base::FilePath("/data/staged"))) {
236     return 1;
237   }
238   WaitToDie(ProcessUtilTest::GetSignalFilePath(kDataDirHasStaged).c_str());
239   return kSuccess;
240 }
241 
242 // Test transferred paths override cloned paths.
TEST_F(ProcessUtilTest,HandleTransfersOverrideClones)243 TEST_F(ProcessUtilTest, HandleTransfersOverrideClones) {
244   const std::string signal_file =
245       ProcessUtilTest::GetSignalFilePath(kDataDirHasStaged);
246   remove(signal_file.c_str());
247 
248   // Create a tempdir with "staged" as its contents.
249   ScopedTempDir tmpdir_with_staged;
250   ASSERT_TRUE(tmpdir_with_staged.CreateUniqueTempDir());
251   {
252     base::FilePath staged_file_path =
253         tmpdir_with_staged.GetPath().Append("staged");
254     base::File staged_file(staged_file_path,
255                            base::File::FLAG_CREATE | base::File::FLAG_WRITE);
256     ASSERT_TRUE(staged_file.created());
257     staged_file.Close();
258   }
259 
260   base::LaunchOptions options;
261   options.spawn_flags = FDIO_SPAWN_CLONE_STDIO;
262 
263   // Attach the tempdir to "data", but also try to duplicate the existing "data"
264   // directory.
265   options.paths_to_clone.push_back(base::FilePath("/data"));
266   options.paths_to_clone.push_back(base::FilePath("/tmp"));
267   options.paths_to_transfer.push_back(
268       {FilePath("/data"),
269        fuchsia::GetHandleFromFile(
270            base::File(base::FilePath(tmpdir_with_staged.GetPath()),
271                       base::File::FLAG_OPEN | base::File::FLAG_READ))
272            .release()});
273 
274   // Verify from that "/data/staged" exists from the child process' perspective.
275   Process process(SpawnChildWithOptions("CheckDataDirHasStaged", options));
276   ASSERT_TRUE(process.IsValid());
277   SignalChildren(signal_file.c_str());
278 
279   int exit_code = 42;
280   EXPECT_TRUE(process.WaitForExit(&exit_code));
281   EXPECT_EQ(kSuccess, exit_code);
282 }
283 
MULTIPROCESS_TEST_MAIN(CheckMountedDir)284 MULTIPROCESS_TEST_MAIN(CheckMountedDir) {
285   if (!PathExists(base::FilePath("/foo/staged"))) {
286     return 1;
287   }
288   WaitToDie(ProcessUtilTest::GetSignalFilePath(kFooDirHasStaged).c_str());
289   return kSuccess;
290 }
291 
292 // Test that we can install an opaque handle in the child process' namespace.
TEST_F(ProcessUtilTest,TransferHandleToPath)293 TEST_F(ProcessUtilTest, TransferHandleToPath) {
294   const std::string signal_file =
295       ProcessUtilTest::GetSignalFilePath(kFooDirHasStaged);
296   remove(signal_file.c_str());
297 
298   // Create a tempdir with "staged" as its contents.
299   ScopedTempDir new_tmpdir;
300   ASSERT_TRUE(new_tmpdir.CreateUniqueTempDir());
301   base::FilePath staged_file_path = new_tmpdir.GetPath().Append("staged");
302   base::File staged_file(staged_file_path,
303                          base::File::FLAG_CREATE | base::File::FLAG_WRITE);
304   ASSERT_TRUE(staged_file.created());
305   staged_file.Close();
306 
307   // Mount the tempdir to "/foo".
308   zx::handle tmp_handle = fuchsia::GetHandleFromFile(
309       base::File(base::FilePath(new_tmpdir.GetPath()),
310                  base::File::FLAG_OPEN | base::File::FLAG_READ));
311   ASSERT_TRUE(tmp_handle.is_valid());
312   LaunchOptions options;
313   options.paths_to_clone.push_back(base::FilePath("/tmp"));
314   options.paths_to_transfer.push_back(
315       {base::FilePath("/foo"), tmp_handle.release()});
316   options.spawn_flags = FDIO_SPAWN_CLONE_STDIO;
317 
318   // Verify from that "/foo/staged" exists from the child process' perspective.
319   Process process(SpawnChildWithOptions("CheckMountedDir", options));
320   ASSERT_TRUE(process.IsValid());
321   SignalChildren(signal_file.c_str());
322 
323   int exit_code = 42;
324   EXPECT_TRUE(process.WaitForExit(&exit_code));
325   EXPECT_EQ(kSuccess, exit_code);
326 }
327 
MULTIPROCESS_TEST_MAIN(CheckTmpFileExists)328 MULTIPROCESS_TEST_MAIN(CheckTmpFileExists) {
329   // Look through the filesystem to ensure that no other directories
330   // besides "tmp" are in the namespace.
331   base::FileEnumerator enumerator(
332       base::FilePath("/"), false,
333       base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
334   base::FilePath next_path;
335   while (!(next_path = enumerator.Next()).empty()) {
336     if (next_path != base::FilePath("/tmp")) {
337       LOG(ERROR) << "Clone policy violation: found non-tmp directory "
338                  << next_path.MaybeAsASCII();
339       return 1;
340     }
341   }
342   WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileClone).c_str());
343   return kSuccess;
344 }
345 
TEST_F(ProcessUtilTest,CloneTmp)346 TEST_F(ProcessUtilTest, CloneTmp) {
347   const std::string signal_file =
348       ProcessUtilTest::GetSignalFilePath(kSignalFileClone);
349   remove(signal_file.c_str());
350 
351   LaunchOptions options;
352   options.paths_to_clone.push_back(base::FilePath("/tmp"));
353   options.spawn_flags = FDIO_SPAWN_CLONE_STDIO;
354 
355   Process process(SpawnChildWithOptions("CheckTmpFileExists", options));
356   ASSERT_TRUE(process.IsValid());
357 
358   SignalChildren(signal_file.c_str());
359 
360   int exit_code = 42;
361   EXPECT_TRUE(process.WaitForExit(&exit_code));
362   EXPECT_EQ(kSuccess, exit_code);
363 }
364 
MULTIPROCESS_TEST_MAIN(CheckMountedDirDoesNotExist)365 MULTIPROCESS_TEST_MAIN(CheckMountedDirDoesNotExist) {
366   if (PathExists(base::FilePath("/foo"))) {
367     return 1;
368   }
369   WaitToDie(
370       ProcessUtilTest::GetSignalFilePath(kFooDirDoesNotHaveStaged).c_str());
371   return kSuccess;
372 }
373 
TEST_F(ProcessUtilTest,TransferInvalidHandleFails)374 TEST_F(ProcessUtilTest, TransferInvalidHandleFails) {
375   LaunchOptions options;
376   options.paths_to_clone.push_back(base::FilePath("/tmp"));
377   options.paths_to_transfer.push_back(
378       {base::FilePath("/foo"), ZX_HANDLE_INVALID});
379   options.spawn_flags = FDIO_SPAWN_CLONE_STDIO;
380 
381   // Verify that the process is never constructed.
382   const std::string signal_file =
383       ProcessUtilTest::GetSignalFilePath(kFooDirDoesNotHaveStaged);
384   remove(signal_file.c_str());
385   Process process(
386       SpawnChildWithOptions("CheckMountedDirDoesNotExist", options));
387   ASSERT_FALSE(process.IsValid());
388 }
389 
TEST_F(ProcessUtilTest,CloneInvalidDirFails)390 TEST_F(ProcessUtilTest, CloneInvalidDirFails) {
391   const std::string signal_file =
392       ProcessUtilTest::GetSignalFilePath(kSignalFileClone);
393   remove(signal_file.c_str());
394 
395   LaunchOptions options;
396   options.paths_to_clone.push_back(base::FilePath("/tmp"));
397   options.paths_to_clone.push_back(base::FilePath("/definitely_not_a_dir"));
398   options.spawn_flags = FDIO_SPAWN_CLONE_STDIO;
399 
400   Process process(SpawnChildWithOptions("CheckTmpFileExists", options));
401   ASSERT_FALSE(process.IsValid());
402 }
403 
404 // Test that we can clone other directories. CheckTmpFileExists will return an
405 // error code if it detects a directory other than "/tmp", so we can use that as
406 // a signal that it successfully detected another entry in the root namespace.
TEST_F(ProcessUtilTest,CloneAlternateDir)407 TEST_F(ProcessUtilTest, CloneAlternateDir) {
408   const std::string signal_file =
409       ProcessUtilTest::GetSignalFilePath(kSignalFileClone);
410   remove(signal_file.c_str());
411 
412   LaunchOptions options;
413   options.paths_to_clone.push_back(base::FilePath("/tmp"));
414   options.paths_to_clone.push_back(base::FilePath("/data"));
415   options.spawn_flags = FDIO_SPAWN_CLONE_STDIO;
416 
417   Process process(SpawnChildWithOptions("CheckTmpFileExists", options));
418   ASSERT_TRUE(process.IsValid());
419 
420   SignalChildren(signal_file.c_str());
421 
422   int exit_code = 42;
423   EXPECT_TRUE(process.WaitForExit(&exit_code));
424   EXPECT_EQ(1, exit_code);
425 }
426 
TEST_F(ProcessUtilTest,HandlesToTransferClosedOnSpawnFailure)427 TEST_F(ProcessUtilTest, HandlesToTransferClosedOnSpawnFailure) {
428   zx::handle handles[2];
429   zx_status_t result = zx_channel_create(0, handles[0].reset_and_get_address(),
430                                          handles[1].reset_and_get_address());
431   ZX_CHECK(ZX_OK == result, result) << "zx_channel_create";
432 
433   LaunchOptions options;
434   options.handles_to_transfer.push_back({0, handles[0].get()});
435 
436   // Launch a non-existent binary, causing fdio_spawn() to fail.
437   CommandLine command_line(FilePath(
438       FILE_PATH_LITERAL("��magical_filename_that_will_never_exist_ever")));
439   Process process(LaunchProcess(command_line, options));
440   ASSERT_FALSE(process.IsValid());
441 
442   // If LaunchProcess did its job then handles[0] is no longer valid, and
443   // handles[1] should observe a channel-closed signal.
444   EXPECT_EQ(
445       zx_object_wait_one(handles[1].get(), ZX_CHANNEL_PEER_CLOSED, 0, nullptr),
446       ZX_OK);
447   EXPECT_EQ(ZX_ERR_BAD_HANDLE, zx_handle_close(handles[0].get()));
448   ignore_result(handles[0].release());
449 }
450 
TEST_F(ProcessUtilTest,HandlesToTransferClosedOnBadPathToMapFailure)451 TEST_F(ProcessUtilTest, HandlesToTransferClosedOnBadPathToMapFailure) {
452   zx::handle handles[2];
453   zx_status_t result = zx_channel_create(0, handles[0].reset_and_get_address(),
454                                          handles[1].reset_and_get_address());
455   ZX_CHECK(ZX_OK == result, result) << "zx_channel_create";
456 
457   LaunchOptions options;
458   options.handles_to_transfer.push_back({0, handles[0].get()});
459   options.spawn_flags = options.spawn_flags & ~FDIO_SPAWN_CLONE_NAMESPACE;
460   options.paths_to_clone.emplace_back(
461       "��magical_path_that_will_never_exist_ever");
462 
463   // LaunchProces should fail to open() the path_to_map, and fail before
464   // fdio_spawn().
465   Process process(LaunchProcess(CommandLine(FilePath()), options));
466   ASSERT_FALSE(process.IsValid());
467 
468   // If LaunchProcess did its job then handles[0] is no longer valid, and
469   // handles[1] should observe a channel-closed signal.
470   EXPECT_EQ(
471       zx_object_wait_one(handles[1].get(), ZX_CHANNEL_PEER_CLOSED, 0, nullptr),
472       ZX_OK);
473   EXPECT_EQ(ZX_ERR_BAD_HANDLE, zx_handle_close(handles[0].get()));
474   ignore_result(handles[0].release());
475 }
476 #endif  // defined(OS_FUCHSIA)
477 
478 // On Android SpawnProcess() doesn't use LaunchProcess() and doesn't support
479 // LaunchOptions::current_directory.
480 #if !defined(OS_ANDROID)
MULTIPROCESS_TEST_MAIN(CheckCwdProcess)481 MULTIPROCESS_TEST_MAIN(CheckCwdProcess) {
482   FilePath expected;
483   CHECK(GetTempDir(&expected));
484   expected = MakeAbsoluteFilePath(expected);
485   CHECK(!expected.empty());
486 
487   FilePath actual;
488   CHECK(GetCurrentDirectory(&actual));
489   actual = MakeAbsoluteFilePath(actual);
490   CHECK(!actual.empty());
491 
492   CHECK(expected == actual) << "Expected: " << expected.value()
493                             << "  Actual: " << actual.value();
494   return kSuccess;
495 }
496 
TEST_F(ProcessUtilTest,CurrentDirectory)497 TEST_F(ProcessUtilTest, CurrentDirectory) {
498   // TODO(rickyz): Add support for passing arguments to multiprocess children,
499   // then create a special directory for this test.
500   FilePath tmp_dir;
501   ASSERT_TRUE(GetTempDir(&tmp_dir));
502 
503   LaunchOptions options;
504   options.current_directory = tmp_dir;
505 
506   Process process(SpawnChildWithOptions("CheckCwdProcess", options));
507   ASSERT_TRUE(process.IsValid());
508 
509   int exit_code = 42;
510   EXPECT_TRUE(process.WaitForExit(&exit_code));
511   EXPECT_EQ(kSuccess, exit_code);
512 }
513 #endif  // !defined(OS_ANDROID)
514 
515 #if defined(OS_WIN)
516 // TODO(cpu): figure out how to test this in other platforms.
TEST_F(ProcessUtilTest,GetProcId)517 TEST_F(ProcessUtilTest, GetProcId) {
518   ProcessId id1 = GetProcId(GetCurrentProcess());
519   EXPECT_NE(0ul, id1);
520   Process process = SpawnChild("SimpleChildProcess");
521   ASSERT_TRUE(process.IsValid());
522   ProcessId id2 = process.Pid();
523   EXPECT_NE(0ul, id2);
524   EXPECT_NE(id1, id2);
525 }
526 #endif  // defined(OS_WIN)
527 
528 #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
529 // This test is disabled on Mac, since it's flaky due to ReportCrash
530 // taking a variable amount of time to parse and load the debug and
531 // symbol data for this unit test's executable before firing the
532 // signal handler.
533 //
534 // TODO(gspencer): turn this test process into a very small program
535 // with no symbols (instead of using the multiprocess testing
536 // framework) to reduce the ReportCrash overhead.
537 //
538 // It is disabled on Android as MultiprocessTests are started as services that
539 // the framework restarts on crashes.
540 const char kSignalFileCrash[] = "CrashingChildProcess.die";
541 
MULTIPROCESS_TEST_MAIN(CrashingChildProcess)542 MULTIPROCESS_TEST_MAIN(CrashingChildProcess) {
543   WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileCrash).c_str());
544 #if defined(OS_POSIX)
545   // Have to disable to signal handler for segv so we can get a crash
546   // instead of an abnormal termination through the crash dump handler.
547   ::signal(SIGSEGV, SIG_DFL);
548 #endif
549   // Make this process have a segmentation fault.
550   volatile int* oops = nullptr;
551   *oops = 0xDEAD;
552   return 1;
553 }
554 
555 // This test intentionally crashes, so we don't need to run it under
556 // AddressSanitizer.
557 #if defined(ADDRESS_SANITIZER) || defined(OS_FUCHSIA)
558 // TODO(crbug.com/753490): Access to the process termination reason is not
559 // implemented in Fuchsia.
560 #define MAYBE_GetTerminationStatusCrash DISABLED_GetTerminationStatusCrash
561 #else
562 #define MAYBE_GetTerminationStatusCrash GetTerminationStatusCrash
563 #endif
TEST_F(ProcessUtilTest,MAYBE_GetTerminationStatusCrash)564 TEST_F(ProcessUtilTest, MAYBE_GetTerminationStatusCrash) {
565   const std::string signal_file =
566     ProcessUtilTest::GetSignalFilePath(kSignalFileCrash);
567   remove(signal_file.c_str());
568   Process process = SpawnChild("CrashingChildProcess");
569   ASSERT_TRUE(process.IsValid());
570 
571   int exit_code = 42;
572   EXPECT_EQ(TERMINATION_STATUS_STILL_RUNNING,
573             GetTerminationStatus(process.Handle(), &exit_code));
574   EXPECT_EQ(kExpectedStillRunningExitCode, exit_code);
575 
576   SignalChildren(signal_file.c_str());
577   exit_code = 42;
578   TerminationStatus status =
579       WaitForChildTermination(process.Handle(), &exit_code);
580   EXPECT_EQ(TERMINATION_STATUS_PROCESS_CRASHED, status);
581 
582 #if defined(OS_WIN)
583   EXPECT_EQ(static_cast<int>(0xc0000005), exit_code);
584 #elif defined(OS_POSIX)
585   int signaled = WIFSIGNALED(exit_code);
586   EXPECT_NE(0, signaled);
587   int signal = WTERMSIG(exit_code);
588   EXPECT_EQ(SIGSEGV, signal);
589 #endif
590 
591   // Reset signal handlers back to "normal".
592   debug::EnableInProcessStackDumping();
593   remove(signal_file.c_str());
594 }
595 #endif  // !defined(OS_MACOSX) && !defined(OS_ANDROID)
596 
MULTIPROCESS_TEST_MAIN(KilledChildProcess)597 MULTIPROCESS_TEST_MAIN(KilledChildProcess) {
598   WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileKill).c_str());
599 #if defined(OS_WIN)
600   // Kill ourselves.
601   HANDLE handle = ::OpenProcess(PROCESS_ALL_ACCESS, 0, ::GetCurrentProcessId());
602   ::TerminateProcess(handle, kExpectedKilledExitCode);
603 #elif defined(OS_POSIX)
604   // Send a SIGKILL to this process, just like the OOM killer would.
605   ::kill(getpid(), SIGKILL);
606 #elif defined(OS_FUCHSIA)
607   zx_task_kill(zx_process_self());
608 #endif
609   return 1;
610 }
611 
612 #if defined(OS_POSIX)
MULTIPROCESS_TEST_MAIN(TerminatedChildProcess)613 MULTIPROCESS_TEST_MAIN(TerminatedChildProcess) {
614   WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileTerm).c_str());
615   // Send a SIGTERM to this process.
616   ::kill(getpid(), SIGTERM);
617   return 1;
618 }
619 #endif  // defined(OS_POSIX) || defined(OS_FUCHSIA)
620 
621 #if defined(OS_FUCHSIA)
622 // TODO(crbug.com/753490): Access to the process termination reason is not
623 // implemented in Fuchsia.
624 #define MAYBE_GetTerminationStatusSigKill DISABLED_GetTerminationStatusSigKill
625 #else
626 #define MAYBE_GetTerminationStatusSigKill GetTerminationStatusSigKill
627 #endif
TEST_F(ProcessUtilTest,MAYBE_GetTerminationStatusSigKill)628 TEST_F(ProcessUtilTest, MAYBE_GetTerminationStatusSigKill) {
629   const std::string signal_file =
630     ProcessUtilTest::GetSignalFilePath(kSignalFileKill);
631   remove(signal_file.c_str());
632   Process process = SpawnChild("KilledChildProcess");
633   ASSERT_TRUE(process.IsValid());
634 
635   int exit_code = 42;
636   EXPECT_EQ(TERMINATION_STATUS_STILL_RUNNING,
637             GetTerminationStatus(process.Handle(), &exit_code));
638   EXPECT_EQ(kExpectedStillRunningExitCode, exit_code);
639 
640   SignalChildren(signal_file.c_str());
641   exit_code = 42;
642   TerminationStatus status =
643       WaitForChildTermination(process.Handle(), &exit_code);
644 #if defined(OS_CHROMEOS)
645   EXPECT_EQ(TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM, status);
646 #else
647   EXPECT_EQ(TERMINATION_STATUS_PROCESS_WAS_KILLED, status);
648 #endif
649 
650 #if defined(OS_WIN)
651   EXPECT_EQ(kExpectedKilledExitCode, exit_code);
652 #elif defined(OS_POSIX)
653   int signaled = WIFSIGNALED(exit_code);
654   EXPECT_NE(0, signaled);
655   int signal = WTERMSIG(exit_code);
656   EXPECT_EQ(SIGKILL, signal);
657 #endif
658   remove(signal_file.c_str());
659 }
660 
661 #if defined(OS_POSIX)
662 // TODO(crbug.com/753490): Access to the process termination reason is not
663 // implemented in Fuchsia. Unix signals are not implemented in Fuchsia so this
664 // test might not be relevant anyway.
TEST_F(ProcessUtilTest,GetTerminationStatusSigTerm)665 TEST_F(ProcessUtilTest, GetTerminationStatusSigTerm) {
666   const std::string signal_file =
667     ProcessUtilTest::GetSignalFilePath(kSignalFileTerm);
668   remove(signal_file.c_str());
669   Process process = SpawnChild("TerminatedChildProcess");
670   ASSERT_TRUE(process.IsValid());
671 
672   int exit_code = 42;
673   EXPECT_EQ(TERMINATION_STATUS_STILL_RUNNING,
674             GetTerminationStatus(process.Handle(), &exit_code));
675   EXPECT_EQ(kExpectedStillRunningExitCode, exit_code);
676 
677   SignalChildren(signal_file.c_str());
678   exit_code = 42;
679   TerminationStatus status =
680       WaitForChildTermination(process.Handle(), &exit_code);
681   EXPECT_EQ(TERMINATION_STATUS_PROCESS_WAS_KILLED, status);
682 
683   int signaled = WIFSIGNALED(exit_code);
684   EXPECT_NE(0, signaled);
685   int signal = WTERMSIG(exit_code);
686   EXPECT_EQ(SIGTERM, signal);
687   remove(signal_file.c_str());
688 }
689 #endif  // defined(OS_POSIX)
690 
TEST_F(ProcessUtilTest,EnsureTerminationUndying)691 TEST_F(ProcessUtilTest, EnsureTerminationUndying) {
692   test::ScopedTaskEnvironment task_environment;
693 
694   Process child_process = SpawnChild("process_util_test_never_die");
695   ASSERT_TRUE(child_process.IsValid());
696 
697   EnsureProcessTerminated(child_process.Duplicate());
698 
699 #if defined(OS_POSIX)
700   errno = 0;
701 #endif  // defined(OS_POSIX)
702 
703   // Allow a generous timeout, to cope with slow/loaded test bots.
704   bool did_exit = child_process.WaitForExitWithTimeout(
705       TestTimeouts::action_max_timeout(), nullptr);
706 
707 #if defined(OS_POSIX)
708   // Both EnsureProcessTerminated() and WaitForExitWithTimeout() will call
709   // waitpid(). One will succeed, and the other will fail with ECHILD. If our
710   // wait failed then check for ECHILD, and assumed |did_exit| in that case.
711   did_exit = did_exit || (errno == ECHILD);
712 #endif  // defined(OS_POSIX)
713 
714   EXPECT_TRUE(did_exit);
715 }
716 
MULTIPROCESS_TEST_MAIN(process_util_test_never_die)717 MULTIPROCESS_TEST_MAIN(process_util_test_never_die) {
718   while (1) {
719     PlatformThread::Sleep(TimeDelta::FromSeconds(500));
720   }
721   return kSuccess;
722 }
723 
TEST_F(ProcessUtilTest,EnsureTerminationGracefulExit)724 TEST_F(ProcessUtilTest, EnsureTerminationGracefulExit) {
725   test::ScopedTaskEnvironment task_environment;
726 
727   Process child_process = SpawnChild("process_util_test_die_immediately");
728   ASSERT_TRUE(child_process.IsValid());
729 
730   // Wait for the child process to actually exit.
731   child_process.Duplicate().WaitForExitWithTimeout(
732       TestTimeouts::action_max_timeout(), nullptr);
733 
734   EnsureProcessTerminated(child_process.Duplicate());
735 
736   // Verify that the process is really, truly gone.
737   EXPECT_TRUE(child_process.WaitForExitWithTimeout(
738       TestTimeouts::action_max_timeout(), nullptr));
739 }
740 
MULTIPROCESS_TEST_MAIN(process_util_test_die_immediately)741 MULTIPROCESS_TEST_MAIN(process_util_test_die_immediately) {
742   return kSuccess;
743 }
744 
745 #if defined(OS_WIN)
746 // TODO(estade): if possible, port this test.
TEST_F(ProcessUtilTest,LaunchAsUser)747 TEST_F(ProcessUtilTest, LaunchAsUser) {
748   UserTokenHandle token;
749   ASSERT_TRUE(OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token));
750   LaunchOptions options;
751   options.as_user = token;
752   EXPECT_TRUE(
753       LaunchProcess(MakeCmdLine("SimpleChildProcess"), options).IsValid());
754 }
755 
756 static const char kEventToTriggerHandleSwitch[] = "event-to-trigger-handle";
757 
MULTIPROCESS_TEST_MAIN(TriggerEventChildProcess)758 MULTIPROCESS_TEST_MAIN(TriggerEventChildProcess) {
759   std::string handle_value_string =
760       CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
761           kEventToTriggerHandleSwitch);
762   CHECK(!handle_value_string.empty());
763 
764   uint64_t handle_value_uint64;
765   CHECK(StringToUint64(handle_value_string, &handle_value_uint64));
766   // Give ownership of the handle to |event|.
767   WaitableEvent event(
768       win::ScopedHandle(reinterpret_cast<HANDLE>(handle_value_uint64)));
769 
770   event.Signal();
771 
772   return 0;
773 }
774 
TEST_F(ProcessUtilTest,InheritSpecifiedHandles)775 TEST_F(ProcessUtilTest, InheritSpecifiedHandles) {
776   // Manually create the event, so that it can be inheritable.
777   SECURITY_ATTRIBUTES security_attributes = {};
778   security_attributes.nLength = static_cast<DWORD>(sizeof(security_attributes));
779   security_attributes.lpSecurityDescriptor = NULL;
780   security_attributes.bInheritHandle = true;
781 
782   // Takes ownership of the event handle.
783   WaitableEvent event(
784       win::ScopedHandle(CreateEvent(&security_attributes, true, false, NULL)));
785   LaunchOptions options;
786   options.handles_to_inherit.emplace_back(event.handle());
787 
788   CommandLine cmd_line = MakeCmdLine("TriggerEventChildProcess");
789   cmd_line.AppendSwitchASCII(
790       kEventToTriggerHandleSwitch,
791       NumberToString(reinterpret_cast<uint64_t>(event.handle())));
792 
793   // Launch the process and wait for it to trigger the event.
794   ASSERT_TRUE(LaunchProcess(cmd_line, options).IsValid());
795   EXPECT_TRUE(event.TimedWait(TestTimeouts::action_max_timeout()));
796 }
797 #endif  // defined(OS_WIN)
798 
TEST_F(ProcessUtilTest,GetAppOutput)799 TEST_F(ProcessUtilTest, GetAppOutput) {
800   base::CommandLine command(test_helper_path_);
801   command.AppendArg("hello");
802   command.AppendArg("there");
803   command.AppendArg("good");
804   command.AppendArg("people");
805   std::string output;
806   EXPECT_TRUE(GetAppOutput(command, &output));
807   EXPECT_EQ("hello there good people", output);
808   output.clear();
809 
810   const char* kEchoMessage = "blah";
811   command = base::CommandLine(test_helper_path_);
812   command.AppendArg("-x");
813   command.AppendArg("28");
814   command.AppendArg(kEchoMessage);
815   EXPECT_FALSE(GetAppOutput(command, &output));
816   EXPECT_EQ(kEchoMessage, output);
817 }
818 
TEST_F(ProcessUtilTest,GetAppOutputWithExitCode)819 TEST_F(ProcessUtilTest, GetAppOutputWithExitCode) {
820   const char* kEchoMessage1 = "doge";
821   int exit_code = -1;
822   base::CommandLine command(test_helper_path_);
823   command.AppendArg(kEchoMessage1);
824   std::string output;
825   EXPECT_TRUE(GetAppOutputWithExitCode(command, &output, &exit_code));
826   EXPECT_EQ(kEchoMessage1, output);
827   EXPECT_EQ(0, exit_code);
828   output.clear();
829 
830   const char* kEchoMessage2 = "pupper";
831   const int kExpectedExitCode = 42;
832   command = base::CommandLine(test_helper_path_);
833   command.AppendArg("-x");
834   command.AppendArg(base::IntToString(kExpectedExitCode));
835   command.AppendArg(kEchoMessage2);
836 #if defined(OS_WIN)
837   // On Windows, anything that quits with a nonzero status code is handled as a
838   // "crash", so just ignore GetAppOutputWithExitCode's return value.
839   GetAppOutputWithExitCode(command, &output, &exit_code);
840 #elif defined(OS_POSIX) || defined(OS_FUCHSIA)
841   EXPECT_TRUE(GetAppOutputWithExitCode(command, &output, &exit_code));
842 #endif
843   EXPECT_EQ(kEchoMessage2, output);
844   EXPECT_EQ(kExpectedExitCode, exit_code);
845 }
846 
847 #if defined(OS_POSIX) || defined(OS_FUCHSIA)
848 
849 namespace {
850 
851 // Returns the maximum number of files that a process can have open.
852 // Returns 0 on error.
GetMaxFilesOpenInProcess()853 int GetMaxFilesOpenInProcess() {
854 #if defined(OS_FUCHSIA)
855   return FDIO_MAX_FD;
856 #else
857   struct rlimit rlim;
858   if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) {
859     return 0;
860   }
861 
862   // rlim_t is a uint64_t - clip to maxint. We do this since FD #s are ints
863   // which are all 32 bits on the supported platforms.
864   rlim_t max_int = static_cast<rlim_t>(std::numeric_limits<int32_t>::max());
865   if (rlim.rlim_cur > max_int) {
866     return max_int;
867   }
868 
869   return rlim.rlim_cur;
870 #endif  // defined(OS_FUCHSIA)
871 }
872 
873 const int kChildPipe = 20;  // FD # for write end of pipe in child process.
874 
875 #if defined(OS_MACOSX)
876 
877 // <http://opensource.apple.com/source/xnu/xnu-2422.1.72/bsd/sys/guarded.h>
878 #if !defined(_GUARDID_T)
879 #define _GUARDID_T
880 typedef __uint64_t guardid_t;
881 #endif  // _GUARDID_T
882 
883 // From .../MacOSX10.9.sdk/usr/include/sys/syscall.h
884 #if !defined(SYS_change_fdguard_np)
885 #define SYS_change_fdguard_np 444
886 #endif
887 
888 // <http://opensource.apple.com/source/xnu/xnu-2422.1.72/bsd/sys/guarded.h>
889 #if !defined(GUARD_DUP)
890 #define GUARD_DUP (1u << 1)
891 #endif
892 
893 // <http://opensource.apple.com/source/xnu/xnu-2422.1.72/bsd/kern/kern_guarded.c?txt>
894 //
895 // Atomically replaces |guard|/|guardflags| with |nguard|/|nguardflags| on |fd|.
change_fdguard_np(int fd,const guardid_t * guard,u_int guardflags,const guardid_t * nguard,u_int nguardflags,int * fdflagsp)896 int change_fdguard_np(int fd,
897                       const guardid_t *guard, u_int guardflags,
898                       const guardid_t *nguard, u_int nguardflags,
899                       int *fdflagsp) {
900   return syscall(SYS_change_fdguard_np, fd, guard, guardflags,
901                  nguard, nguardflags, fdflagsp);
902 }
903 
904 // Attempt to set a file-descriptor guard on |fd|.  In case of success, remove
905 // it and return |true| to indicate that it can be guarded.  Returning |false|
906 // means either that |fd| is guarded by some other code, or more likely EBADF.
907 //
908 // Starting with 10.9, libdispatch began setting GUARD_DUP on a file descriptor.
909 // Unfortunately, it is spun up as part of +[NSApplication initialize], which is
910 // not really something that Chromium can avoid using on OSX.  See
911 // <http://crbug.com/338157>.  This function allows querying whether the file
912 // descriptor is guarded before attempting to close it.
CanGuardFd(int fd)913 bool CanGuardFd(int fd) {
914   // Saves the original flags to reset later.
915   int original_fdflags = 0;
916 
917   // This can be any value at all, it just has to match up between the two
918   // calls.
919   const guardid_t kGuard = 15;
920 
921   // Attempt to change the guard.  This can fail with EBADF if the file
922   // descriptor is bad, or EINVAL if the fd already has a guard set.
923   int ret =
924       change_fdguard_np(fd, NULL, 0, &kGuard, GUARD_DUP, &original_fdflags);
925   if (ret == -1)
926     return false;
927 
928   // Remove the guard.  It should not be possible to fail in removing the guard
929   // just added.
930   ret = change_fdguard_np(fd, &kGuard, GUARD_DUP, NULL, 0, &original_fdflags);
931   DPCHECK(ret == 0);
932 
933   return true;
934 }
935 #endif  // defined(OS_MACOSX)
936 
937 }  // namespace
938 
MULTIPROCESS_TEST_MAIN(ProcessUtilsLeakFDChildProcess)939 MULTIPROCESS_TEST_MAIN(ProcessUtilsLeakFDChildProcess) {
940   // This child process counts the number of open FDs, it then writes that
941   // number out to a pipe connected to the parent.
942   int num_open_files = 0;
943   int write_pipe = kChildPipe;
944   int max_files = GetMaxFilesOpenInProcess();
945   for (int i = STDERR_FILENO + 1; i < max_files; i++) {
946 #if defined(OS_MACOSX)
947     // Ignore guarded or invalid file descriptors.
948     if (!CanGuardFd(i))
949       continue;
950 #endif
951 
952     if (i != kChildPipe) {
953       int fd;
954       if ((fd = HANDLE_EINTR(dup(i))) != -1) {
955         close(fd);
956         num_open_files += 1;
957       }
958     }
959   }
960 
961   int written = HANDLE_EINTR(write(write_pipe, &num_open_files,
962                                    sizeof(num_open_files)));
963   DCHECK_EQ(static_cast<size_t>(written), sizeof(num_open_files));
964   int ret = IGNORE_EINTR(close(write_pipe));
965   DPCHECK(ret == 0);
966 
967   return 0;
968 }
969 
CountOpenFDsInChild()970 int ProcessUtilTest::CountOpenFDsInChild() {
971   int fds[2];
972   if (pipe(fds) < 0)
973     NOTREACHED();
974 
975   LaunchOptions options;
976   options.fds_to_remap.emplace_back(fds[1], kChildPipe);
977   Process process =
978       SpawnChildWithOptions("ProcessUtilsLeakFDChildProcess", options);
979   CHECK(process.IsValid());
980   int ret = IGNORE_EINTR(close(fds[1]));
981   DPCHECK(ret == 0);
982 
983   // Read number of open files in client process from pipe;
984   int num_open_files = -1;
985   ssize_t bytes_read =
986       HANDLE_EINTR(read(fds[0], &num_open_files, sizeof(num_open_files)));
987   CHECK_EQ(bytes_read, static_cast<ssize_t>(sizeof(num_open_files)));
988 
989 #if defined(THREAD_SANITIZER)
990   // Compiler-based ThreadSanitizer makes this test slow.
991   TimeDelta timeout = TimeDelta::FromSeconds(3);
992 #else
993   TimeDelta timeout = TimeDelta::FromSeconds(1);
994 #endif
995   int exit_code;
996   CHECK(process.WaitForExitWithTimeout(timeout, &exit_code));
997   ret = IGNORE_EINTR(close(fds[0]));
998   DPCHECK(ret == 0);
999 
1000   return num_open_files;
1001 }
1002 
1003 #if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER)
1004 // ProcessUtilTest.FDRemapping is flaky when ran under xvfb-run on Precise.
1005 // The problem is 100% reproducible with both ASan and TSan.
1006 // See http://crbug.com/136720.
1007 #define MAYBE_FDRemapping DISABLED_FDRemapping
1008 #else
1009 #define MAYBE_FDRemapping FDRemapping
1010 #endif  // defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER)
TEST_F(ProcessUtilTest,MAYBE_FDRemapping)1011 TEST_F(ProcessUtilTest, MAYBE_FDRemapping) {
1012   int fds_before = CountOpenFDsInChild();
1013 
1014   // open some dummy fds to make sure they don't propagate over to the
1015   // child process.
1016   int dev_null = open("/dev/null", O_RDONLY);
1017   DPCHECK(dev_null != -1);
1018   int sockets[2];
1019   int ret = socketpair(AF_UNIX, SOCK_STREAM, 0, sockets);
1020   DPCHECK(ret == 0);
1021 
1022   int fds_after = CountOpenFDsInChild();
1023 
1024   ASSERT_EQ(fds_after, fds_before);
1025 
1026   ret = IGNORE_EINTR(close(sockets[0]));
1027   DPCHECK(ret == 0);
1028   ret = IGNORE_EINTR(close(sockets[1]));
1029   DPCHECK(ret == 0);
1030   ret = IGNORE_EINTR(close(dev_null));
1031   DPCHECK(ret == 0);
1032 }
1033 
1034 const char kPipeValue = '\xcc';
MULTIPROCESS_TEST_MAIN(ProcessUtilsVerifyStdio)1035 MULTIPROCESS_TEST_MAIN(ProcessUtilsVerifyStdio) {
1036   // Write to stdio so the parent process can observe output.
1037   CHECK_EQ(1, HANDLE_EINTR(write(STDOUT_FILENO, &kPipeValue, 1)));
1038 
1039   // Close all of the handles, to verify they are valid.
1040   CHECK_EQ(0, IGNORE_EINTR(close(STDIN_FILENO)));
1041   CHECK_EQ(0, IGNORE_EINTR(close(STDOUT_FILENO)));
1042   CHECK_EQ(0, IGNORE_EINTR(close(STDERR_FILENO)));
1043   return 0;
1044 }
1045 
TEST_F(ProcessUtilTest,FDRemappingIncludesStdio)1046 TEST_F(ProcessUtilTest, FDRemappingIncludesStdio) {
1047   int dev_null = open("/dev/null", O_RDONLY);
1048   ASSERT_LT(2, dev_null);
1049 
1050   // Backup stdio and replace it with the write end of a pipe, for our
1051   // child process to inherit.
1052   int pipe_fds[2];
1053   int result = pipe(pipe_fds);
1054   ASSERT_EQ(0, result);
1055   int backup_stdio = HANDLE_EINTR(dup(STDOUT_FILENO));
1056   ASSERT_LE(0, backup_stdio);
1057   result = dup2(pipe_fds[1], STDOUT_FILENO);
1058   ASSERT_EQ(STDOUT_FILENO, result);
1059 
1060   // Launch the test process, which should inherit our pipe stdio.
1061   LaunchOptions options;
1062   options.fds_to_remap.emplace_back(dev_null, dev_null);
1063   Process process = SpawnChildWithOptions("ProcessUtilsVerifyStdio", options);
1064   ASSERT_TRUE(process.IsValid());
1065 
1066   // Restore stdio, so we can output stuff.
1067   result = dup2(backup_stdio, STDOUT_FILENO);
1068   ASSERT_EQ(STDOUT_FILENO, result);
1069 
1070   // Close our copy of the write end of the pipe, so that the read()
1071   // from the other end will see EOF if it wasn't copied to the child.
1072   result = IGNORE_EINTR(close(pipe_fds[1]));
1073   ASSERT_EQ(0, result);
1074 
1075   result = IGNORE_EINTR(close(backup_stdio));
1076   ASSERT_EQ(0, result);
1077   result = IGNORE_EINTR(close(dev_null));
1078   ASSERT_EQ(0, result);
1079 
1080   // Read from the pipe to verify that it is connected to the child
1081   // process' stdio.
1082   char buf[16] = {};
1083   EXPECT_EQ(1, HANDLE_EINTR(read(pipe_fds[0], buf, sizeof(buf))));
1084   EXPECT_EQ(kPipeValue, buf[0]);
1085 
1086   result = IGNORE_EINTR(close(pipe_fds[0]));
1087   ASSERT_EQ(0, result);
1088 
1089   int exit_code;
1090   ASSERT_TRUE(
1091       process.WaitForExitWithTimeout(TimeDelta::FromSeconds(5), &exit_code));
1092   EXPECT_EQ(0, exit_code);
1093 }
1094 
1095 #if defined(OS_FUCHSIA)
1096 
1097 const uint16_t kStartupHandleId = 43;
MULTIPROCESS_TEST_MAIN(ProcessUtilsVerifyHandle)1098 MULTIPROCESS_TEST_MAIN(ProcessUtilsVerifyHandle) {
1099   zx_handle_t handle =
1100       zx_take_startup_handle(PA_HND(PA_USER0, kStartupHandleId));
1101   CHECK_NE(ZX_HANDLE_INVALID, handle);
1102 
1103   // Write to the pipe so the parent process can observe output.
1104   size_t bytes_written = 0;
1105   zx_status_t result = zx_socket_write(handle, 0, &kPipeValue,
1106                                        sizeof(kPipeValue), &bytes_written);
1107   CHECK_EQ(ZX_OK, result);
1108   CHECK_EQ(1u, bytes_written);
1109 
1110   CHECK_EQ(ZX_OK, zx_handle_close(handle));
1111   return 0;
1112 }
1113 
TEST_F(ProcessUtilTest,LaunchWithHandleTransfer)1114 TEST_F(ProcessUtilTest, LaunchWithHandleTransfer) {
1115   // Create a pipe to pass to the child process.
1116   zx_handle_t handles[2];
1117   zx_status_t result =
1118       zx_socket_create(ZX_SOCKET_STREAM, &handles[0], &handles[1]);
1119   ASSERT_EQ(ZX_OK, result);
1120 
1121   // Launch the test process, and pass it one end of the pipe.
1122   LaunchOptions options;
1123   options.handles_to_transfer.push_back(
1124       {PA_HND(PA_USER0, kStartupHandleId), handles[0]});
1125   Process process = SpawnChildWithOptions("ProcessUtilsVerifyHandle", options);
1126   ASSERT_TRUE(process.IsValid());
1127 
1128   // Read from the pipe to verify that the child received it.
1129   zx_signals_t signals = 0;
1130   result = zx_object_wait_one(
1131       handles[1], ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED,
1132       (base::TimeTicks::Now() + TestTimeouts::action_timeout()).ToZxTime(),
1133       &signals);
1134   ASSERT_EQ(ZX_OK, result);
1135   ASSERT_TRUE(signals & ZX_SOCKET_READABLE);
1136 
1137   size_t bytes_read = 0;
1138   char buf[16] = {0};
1139   result = zx_socket_read(handles[1], 0, buf, sizeof(buf), &bytes_read);
1140   EXPECT_EQ(ZX_OK, result);
1141   EXPECT_EQ(1u, bytes_read);
1142   EXPECT_EQ(kPipeValue, buf[0]);
1143 
1144   CHECK_EQ(ZX_OK, zx_handle_close(handles[1]));
1145 
1146   int exit_code;
1147   ASSERT_TRUE(process.WaitForExitWithTimeout(TestTimeouts::action_timeout(),
1148                                              &exit_code));
1149   EXPECT_EQ(0, exit_code);
1150 }
1151 
1152 #endif  // defined(OS_FUCHSIA)
1153 
1154 namespace {
1155 
TestLaunchProcess(const std::vector<std::string> & args,const EnvironmentMap & env_changes,const bool clear_environ,const int clone_flags)1156 std::string TestLaunchProcess(const std::vector<std::string>& args,
1157                               const EnvironmentMap& env_changes,
1158                               const bool clear_environ,
1159                               const int clone_flags) {
1160   int fds[2];
1161   PCHECK(pipe(fds) == 0);
1162 
1163   LaunchOptions options;
1164   options.wait = true;
1165   options.environ = env_changes;
1166   options.clear_environ = clear_environ;
1167   options.fds_to_remap.emplace_back(fds[1], 1);
1168 #if defined(OS_LINUX)
1169   options.clone_flags = clone_flags;
1170 #else
1171   CHECK_EQ(0, clone_flags);
1172 #endif  // defined(OS_LINUX)
1173   EXPECT_TRUE(LaunchProcess(args, options).IsValid());
1174   PCHECK(IGNORE_EINTR(close(fds[1])) == 0);
1175 
1176   char buf[512];
1177   const ssize_t n = HANDLE_EINTR(read(fds[0], buf, sizeof(buf)));
1178 
1179   PCHECK(IGNORE_EINTR(close(fds[0])) == 0);
1180 
1181   return std::string(buf, n);
1182 }
1183 
1184 const char kLargeString[] =
1185     "0123456789012345678901234567890123456789012345678901234567890123456789"
1186     "0123456789012345678901234567890123456789012345678901234567890123456789"
1187     "0123456789012345678901234567890123456789012345678901234567890123456789"
1188     "0123456789012345678901234567890123456789012345678901234567890123456789"
1189     "0123456789012345678901234567890123456789012345678901234567890123456789"
1190     "0123456789012345678901234567890123456789012345678901234567890123456789"
1191     "0123456789012345678901234567890123456789012345678901234567890123456789";
1192 
1193 }  // namespace
1194 
TEST_F(ProcessUtilTest,LaunchProcess)1195 TEST_F(ProcessUtilTest, LaunchProcess) {
1196   const int no_clone_flags = 0;
1197   const bool no_clear_environ = false;
1198   const char kBaseTest[] = "BASE_TEST";
1199   const std::vector<std::string> kPrintEnvCommand = {test_helper_path_.value(),
1200                                                      "-e", kBaseTest};
1201 
1202   EnvironmentMap env_changes;
1203   env_changes[kBaseTest] = "bar";
1204   EXPECT_EQ("bar", TestLaunchProcess(kPrintEnvCommand, env_changes,
1205                                      no_clear_environ, no_clone_flags));
1206   env_changes.clear();
1207 
1208   EXPECT_EQ(0, setenv(kBaseTest, "testing", 1 /* override */));
1209   EXPECT_EQ("testing", TestLaunchProcess(kPrintEnvCommand, env_changes,
1210                                          no_clear_environ, no_clone_flags));
1211 
1212   env_changes[kBaseTest] = std::string();
1213   EXPECT_EQ("", TestLaunchProcess(kPrintEnvCommand, env_changes,
1214                                   no_clear_environ, no_clone_flags));
1215 
1216   env_changes[kBaseTest] = "foo";
1217   EXPECT_EQ("foo", TestLaunchProcess(kPrintEnvCommand, env_changes,
1218                                      no_clear_environ, no_clone_flags));
1219 
1220   env_changes.clear();
1221   EXPECT_EQ(0, setenv(kBaseTest, kLargeString, 1 /* override */));
1222   EXPECT_EQ(std::string(kLargeString),
1223             TestLaunchProcess(kPrintEnvCommand, env_changes, no_clear_environ,
1224                               no_clone_flags));
1225 
1226   env_changes[kBaseTest] = "wibble";
1227   EXPECT_EQ("wibble", TestLaunchProcess(kPrintEnvCommand, env_changes,
1228                                         no_clear_environ, no_clone_flags));
1229 
1230 #if defined(OS_LINUX)
1231   // Test a non-trival value for clone_flags.
1232   EXPECT_EQ("wibble", TestLaunchProcess(kPrintEnvCommand, env_changes,
1233                                         no_clear_environ, CLONE_FS));
1234 
1235   EXPECT_EQ("wibble",
1236             TestLaunchProcess(kPrintEnvCommand, env_changes,
1237                               true /* clear_environ */, no_clone_flags));
1238   env_changes.clear();
1239   EXPECT_EQ("", TestLaunchProcess(kPrintEnvCommand, env_changes,
1240                                   true /* clear_environ */, no_clone_flags));
1241 #endif  // defined(OS_LINUX)
1242 }
1243 
1244 // There's no such thing as a parent process id on Fuchsia.
1245 #if !defined(OS_FUCHSIA)
TEST_F(ProcessUtilTest,GetParentProcessId)1246 TEST_F(ProcessUtilTest, GetParentProcessId) {
1247   ProcessId ppid = GetParentProcessId(GetCurrentProcessHandle());
1248   EXPECT_EQ(ppid, static_cast<ProcessId>(getppid()));
1249 }
1250 #endif  // !defined(OS_FUCHSIA)
1251 
1252 #if !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
1253 class WriteToPipeDelegate : public LaunchOptions::PreExecDelegate {
1254  public:
WriteToPipeDelegate(int fd)1255   explicit WriteToPipeDelegate(int fd) : fd_(fd) {}
1256   ~WriteToPipeDelegate() override = default;
RunAsyncSafe()1257   void RunAsyncSafe() override {
1258     RAW_CHECK(HANDLE_EINTR(write(fd_, &kPipeValue, 1)) == 1);
1259     RAW_CHECK(IGNORE_EINTR(close(fd_)) == 0);
1260   }
1261 
1262  private:
1263   int fd_;
1264   DISALLOW_COPY_AND_ASSIGN(WriteToPipeDelegate);
1265 };
1266 
TEST_F(ProcessUtilTest,PreExecHook)1267 TEST_F(ProcessUtilTest, PreExecHook) {
1268   int pipe_fds[2];
1269   ASSERT_EQ(0, pipe(pipe_fds));
1270 
1271   ScopedFD read_fd(pipe_fds[0]);
1272   ScopedFD write_fd(pipe_fds[1]);
1273 
1274   WriteToPipeDelegate write_to_pipe_delegate(write_fd.get());
1275   LaunchOptions options;
1276   options.fds_to_remap.emplace_back(write_fd.get(), write_fd.get());
1277   options.pre_exec_delegate = &write_to_pipe_delegate;
1278   Process process(SpawnChildWithOptions("SimpleChildProcess", options));
1279   ASSERT_TRUE(process.IsValid());
1280 
1281   write_fd.reset();
1282   char c;
1283   ASSERT_EQ(1, HANDLE_EINTR(read(read_fd.get(), &c, 1)));
1284   EXPECT_EQ(c, kPipeValue);
1285 
1286   int exit_code = 42;
1287   EXPECT_TRUE(process.WaitForExit(&exit_code));
1288   EXPECT_EQ(0, exit_code);
1289 }
1290 #endif  // !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
1291 
1292 #endif  // !defined(OS_MACOSX) && !defined(OS_ANDROID)
1293 
1294 #if defined(OS_LINUX)
MULTIPROCESS_TEST_MAIN(CheckPidProcess)1295 MULTIPROCESS_TEST_MAIN(CheckPidProcess) {
1296   const pid_t kInitPid = 1;
1297   const pid_t pid = syscall(__NR_getpid);
1298   CHECK(pid == kInitPid);
1299   CHECK(getpid() == pid);
1300   return kSuccess;
1301 }
1302 
1303 #if defined(CLONE_NEWUSER) && defined(CLONE_NEWPID)
TEST_F(ProcessUtilTest,CloneFlags)1304 TEST_F(ProcessUtilTest, CloneFlags) {
1305   if (!PathExists(FilePath("/proc/self/ns/user")) ||
1306       !PathExists(FilePath("/proc/self/ns/pid"))) {
1307     // User or PID namespaces are not supported.
1308     return;
1309   }
1310 
1311   LaunchOptions options;
1312   options.clone_flags = CLONE_NEWUSER | CLONE_NEWPID;
1313 
1314   Process process(SpawnChildWithOptions("CheckPidProcess", options));
1315   ASSERT_TRUE(process.IsValid());
1316 
1317   int exit_code = 42;
1318   EXPECT_TRUE(process.WaitForExit(&exit_code));
1319   EXPECT_EQ(kSuccess, exit_code);
1320 }
1321 #endif  // defined(CLONE_NEWUSER) && defined(CLONE_NEWPID)
1322 
TEST(ForkWithFlagsTest,UpdatesPidCache)1323 TEST(ForkWithFlagsTest, UpdatesPidCache) {
1324   // Warm up the libc pid cache, if there is one.
1325   ASSERT_EQ(syscall(__NR_getpid), getpid());
1326 
1327   pid_t ctid = 0;
1328   const pid_t pid = ForkWithFlags(SIGCHLD | CLONE_CHILD_SETTID, nullptr, &ctid);
1329   if (pid == 0) {
1330     // In child.  Check both the raw getpid syscall and the libc getpid wrapper
1331     // (which may rely on a pid cache).
1332     RAW_CHECK(syscall(__NR_getpid) == ctid);
1333     RAW_CHECK(getpid() == ctid);
1334     _exit(kSuccess);
1335   }
1336 
1337   ASSERT_NE(-1, pid);
1338   int status = 42;
1339   ASSERT_EQ(pid, HANDLE_EINTR(waitpid(pid, &status, 0)));
1340   ASSERT_TRUE(WIFEXITED(status));
1341   EXPECT_EQ(kSuccess, WEXITSTATUS(status));
1342 }
1343 
TEST_F(ProcessUtilTest,InvalidCurrentDirectory)1344 TEST_F(ProcessUtilTest, InvalidCurrentDirectory) {
1345   LaunchOptions options;
1346   options.current_directory = FilePath("/dev/null");
1347 
1348   Process process(SpawnChildWithOptions("SimpleChildProcess", options));
1349   ASSERT_TRUE(process.IsValid());
1350 
1351   int exit_code = kSuccess;
1352   EXPECT_TRUE(process.WaitForExit(&exit_code));
1353   EXPECT_NE(kSuccess, exit_code);
1354 }
1355 #endif  // defined(OS_LINUX)
1356 
1357 }  // namespace base
1358