process_util_unittest.cc 49 KB

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