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