[email protected] | b75346c | 2012-05-13 03:48:38 | [diff] [blame] | 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 | |
tfarina | bccc34c7 | 2015-02-27 21:32:15 | [diff] [blame] | 5 | #ifndef CONTENT_ZYGOTE_ZYGOTE_LINUX_H_ |
| 6 | #define CONTENT_ZYGOTE_ZYGOTE_LINUX_H_ |
[email protected] | b75346c | 2012-05-13 03:48:38 | [diff] [blame] | 7 | |
[email protected] | 54ad01a | 2014-05-11 01:17:47 | [diff] [blame] | 8 | #include <stddef.h> |
| 9 | |
leon.han | 79db18e | 2017-01-27 05:26:26 | [diff] [blame] | 10 | #include <memory> |
[email protected] | b75346c | 2012-05-13 03:48:38 | [diff] [blame] | 11 | #include <string> |
mdempsky | f12295a | 2015-12-09 22:54:46 | [diff] [blame] | 12 | #include <vector> |
[email protected] | b75346c | 2012-05-13 03:48:38 | [diff] [blame] | 13 | |
[email protected] | 9f2bdf12 | 2013-08-21 02:59:34 | [diff] [blame] | 14 | #include "base/containers/small_map.h" |
[email protected] | 8feaa67 | 2014-04-30 21:57:10 | [diff] [blame] | 15 | #include "base/files/scoped_file.h" |
[email protected] | 9e5a0a6 | 2013-10-11 19:39:41 | [diff] [blame] | 16 | #include "base/posix/global_descriptors.h" |
[email protected] | 9f2bdf12 | 2013-08-21 02:59:34 | [diff] [blame] | 17 | #include "base/process/kill.h" |
[email protected] | 54724e2 | 2013-07-25 13:02:15 | [diff] [blame] | 18 | #include "base/process/process.h" |
kerrnel | 26b892f | 2015-11-10 19:06:31 | [diff] [blame] | 19 | #include "base/process/process_handle.h" |
| 20 | #include "base/time/time.h" |
[email protected] | b75346c | 2012-05-13 03:48:38 | [diff] [blame] | 21 | |
brettw | 05cfd8ddb | 2015-06-02 07:02:47 | [diff] [blame] | 22 | namespace base { |
[email protected] | b75346c | 2012-05-13 03:48:38 | [diff] [blame] | 23 | class PickleIterator; |
brettw | 05cfd8ddb | 2015-06-02 07:02:47 | [diff] [blame] | 24 | } |
[email protected] | b75346c | 2012-05-13 03:48:38 | [diff] [blame] | 25 | |
| 26 | namespace content { |
| 27 | |
| 28 | class ZygoteForkDelegate; |
| 29 | |
| 30 | // This is the object which implements the zygote. The ZygoteMain function, |
| 31 | // which is called from ChromeMain, simply constructs one of these objects and |
| 32 | // runs it. |
| 33 | class Zygote { |
| 34 | public: |
leon.han | 79db18e | 2017-01-27 05:26:26 | [diff] [blame] | 35 | Zygote(int sandbox_flags, |
| 36 | std::vector<std::unique_ptr<ZygoteForkDelegate>> helpers, |
[email protected] | 655abd52 | 2014-06-02 15:23:43 | [diff] [blame] | 37 | const std::vector<base::ProcessHandle>& extra_children, |
| 38 | const std::vector<int>& extra_fds); |
[email protected] | b75346c | 2012-05-13 03:48:38 | [diff] [blame] | 39 | ~Zygote(); |
| 40 | |
| 41 | bool ProcessRequests(); |
| 42 | |
[email protected] | b75346c | 2012-05-13 03:48:38 | [diff] [blame] | 43 | private: |
[email protected] | 9f2bdf12 | 2013-08-21 02:59:34 | [diff] [blame] | 44 | struct ZygoteProcessInfo { |
| 45 | // Pid from inside the Zygote's PID namespace. |
| 46 | base::ProcessHandle internal_pid; |
[email protected] | 54ad01a | 2014-05-11 01:17:47 | [diff] [blame] | 47 | // Keeps track of which fork delegate helper the process was started from. |
| 48 | ZygoteForkDelegate* started_from_helper; |
kerrnel | 26b892f | 2015-11-10 19:06:31 | [diff] [blame] | 49 | // Records when the browser requested the zygote to reap this process. |
| 50 | base::TimeTicks time_of_reap_request; |
| 51 | // Notes whether the zygote has sent SIGKILL to this process. |
| 52 | bool sent_sigkill; |
[email protected] | 9f2bdf12 | 2013-08-21 02:59:34 | [diff] [blame] | 53 | }; |
brettw | ca2ec763 | 2017-04-20 06:10:20 | [diff] [blame] | 54 | using ZygoteProcessMap = |
| 55 | base::small_map<std::map<base::ProcessHandle, ZygoteProcessInfo>>; |
[email protected] | 9f2bdf12 | 2013-08-21 02:59:34 | [diff] [blame] | 56 | |
[email protected] | 500d24e | 2013-08-21 19:55:32 | [diff] [blame] | 57 | // Retrieve a ZygoteProcessInfo from the process_info_map_. |
| 58 | // Returns true and write to process_info if |pid| can be found, return |
| 59 | // false otherwise. |
brettw | ca2ec763 | 2017-04-20 06:10:20 | [diff] [blame] | 60 | bool GetProcessInfo(base::ProcessHandle pid, ZygoteProcessInfo* process_info); |
[email protected] | 500d24e | 2013-08-21 19:55:32 | [diff] [blame] | 61 | |
[email protected] | b75346c | 2012-05-13 03:48:38 | [diff] [blame] | 62 | // Returns true if the SUID sandbox is active. |
| 63 | bool UsingSUIDSandbox() const; |
jln | 151ebd7 | 2015-02-19 02:21:55 | [diff] [blame] | 64 | // Returns true if the NS sandbox is active. |
| 65 | bool UsingNSSandbox() const; |
[email protected] | b75346c | 2012-05-13 03:48:38 | [diff] [blame] | 66 | |
| 67 | // --------------------------------------------------------------------------- |
| 68 | // Requests from the browser... |
| 69 | |
| 70 | // Read and process a request from the browser. Returns true if we are in a |
| 71 | // new process and thus need to unwind back into ChromeMain. |
| 72 | bool HandleRequestFromBrowser(int fd); |
| 73 | |
brettw | 05cfd8ddb | 2015-06-02 07:02:47 | [diff] [blame] | 74 | void HandleReapRequest(int fd, base::PickleIterator iter); |
[email protected] | b75346c | 2012-05-13 03:48:38 | [diff] [blame] | 75 | |
[email protected] | 9f2bdf12 | 2013-08-21 02:59:34 | [diff] [blame] | 76 | // Get the termination status of |real_pid|. |real_pid| is the PID as it |
| 77 | // appears outside of the sandbox. |
| 78 | // Return true if it managed to get the termination status and return the |
| 79 | // status in |status| and the exit code in |exit_code|. |
| 80 | bool GetTerminationStatus(base::ProcessHandle real_pid, bool known_dead, |
| 81 | base::TerminationStatus* status, |
| 82 | int* exit_code); |
| 83 | |
[email protected] | b75346c | 2012-05-13 03:48:38 | [diff] [blame] | 84 | void HandleGetTerminationStatus(int fd, |
brettw | 05cfd8ddb | 2015-06-02 07:02:47 | [diff] [blame] | 85 | base::PickleIterator iter); |
[email protected] | b75346c | 2012-05-13 03:48:38 | [diff] [blame] | 86 | |
| 87 | // This is equivalent to fork(), except that, when using the SUID sandbox, it |
| 88 | // returns the real PID of the child process as it appears outside the |
[email protected] | 53cbbe25 | 2014-05-08 01:26:28 | [diff] [blame] | 89 | // sandbox, rather than returning the PID inside the sandbox. The child's |
| 90 | // real PID is determined by having it call content::SendZygoteChildPing(int) |
| 91 | // using the |pid_oracle| descriptor. |
| 92 | // Finally, when using a ZygoteForkDelegate helper, |uma_name|, |uma_sample|, |
| 93 | // and |uma_boundary_value| may be set if the helper wants to make a UMA |
| 94 | // report via UMA_HISTOGRAM_ENUMERATION. |
[email protected] | b75346c | 2012-05-13 03:48:38 | [diff] [blame] | 95 | int ForkWithRealPid(const std::string& process_type, |
[email protected] | 9e5a0a6 | 2013-10-11 19:39:41 | [diff] [blame] | 96 | const base::GlobalDescriptors::Mapping& fd_mapping, |
[email protected] | 3a16124 | 2014-04-18 00:07:33 | [diff] [blame] | 97 | const std::string& channel_id, |
[email protected] | 53cbbe25 | 2014-05-08 01:26:28 | [diff] [blame] | 98 | base::ScopedFD pid_oracle, |
[email protected] | b75346c | 2012-05-13 03:48:38 | [diff] [blame] | 99 | std::string* uma_name, |
| 100 | int* uma_sample, |
| 101 | int* uma_boundary_value); |
| 102 | |
avi | 48fc13b | 2014-12-28 23:31:48 | [diff] [blame] | 103 | // Unpacks process type and arguments from |iter| and forks a new process. |
[email protected] | b75346c | 2012-05-13 03:48:38 | [diff] [blame] | 104 | // Returns -1 on error, otherwise returns twice, returning 0 to the child |
| 105 | // process and the child process ID to the parent process, like fork(). |
brettw | 05cfd8ddb | 2015-06-02 07:02:47 | [diff] [blame] | 106 | base::ProcessId ReadArgsAndFork(base::PickleIterator iter, |
mdempsky | f12295a | 2015-12-09 22:54:46 | [diff] [blame] | 107 | std::vector<base::ScopedFD> fds, |
[email protected] | b75346c | 2012-05-13 03:48:38 | [diff] [blame] | 108 | std::string* uma_name, |
| 109 | int* uma_sample, |
| 110 | int* uma_boundary_value); |
| 111 | |
| 112 | // Handle a 'fork' request from the browser: this means that the browser |
| 113 | // wishes to start a new renderer. Returns true if we are in a new process, |
| 114 | // otherwise writes the child_pid back to the browser via |fd|. Writes a |
| 115 | // child_pid of -1 on error. |
| 116 | bool HandleForkRequest(int fd, |
brettw | 05cfd8ddb | 2015-06-02 07:02:47 | [diff] [blame] | 117 | base::PickleIterator iter, |
mdempsky | f12295a | 2015-12-09 22:54:46 | [diff] [blame] | 118 | std::vector<base::ScopedFD> fds); |
[email protected] | b75346c | 2012-05-13 03:48:38 | [diff] [blame] | 119 | |
| 120 | bool HandleGetSandboxStatus(int fd, |
brettw | 05cfd8ddb | 2015-06-02 07:02:47 | [diff] [blame] | 121 | base::PickleIterator iter); |
[email protected] | b75346c | 2012-05-13 03:48:38 | [diff] [blame] | 122 | |
kerrnel | 26b892f | 2015-11-10 19:06:31 | [diff] [blame] | 123 | // Attempt to reap the child process by calling waitpid, and return |
| 124 | // whether successful. If the process has not terminated within |
| 125 | // 2 seconds of its reap request, send it SIGKILL. |
| 126 | bool ReapChild(const base::TimeTicks& now, ZygoteProcessInfo* child); |
| 127 | |
| 128 | // Attempt to reap all outstanding children in |to_reap_|. |
| 129 | void ReapChildren(); |
| 130 | |
[email protected] | 9f2bdf12 | 2013-08-21 02:59:34 | [diff] [blame] | 131 | // The Zygote needs to keep some information about each process. Most |
| 132 | // notably what the PID of the process is inside the PID namespace of |
| 133 | // the Zygote and whether or not a process was started by the |
| 134 | // ZygoteForkDelegate helper. |
| 135 | ZygoteProcessMap process_info_map_; |
[email protected] | b75346c | 2012-05-13 03:48:38 | [diff] [blame] | 136 | |
| 137 | const int sandbox_flags_; |
leon.han | 79db18e | 2017-01-27 05:26:26 | [diff] [blame] | 138 | std::vector<std::unique_ptr<ZygoteForkDelegate>> helpers_; |
[email protected] | b75346c | 2012-05-13 03:48:38 | [diff] [blame] | 139 | |
[email protected] | 54ad01a | 2014-05-11 01:17:47 | [diff] [blame] | 140 | // Count of how many fork delegates for which we've invoked InitialUMA(). |
| 141 | size_t initial_uma_index_; |
[email protected] | 655abd52 | 2014-06-02 15:23:43 | [diff] [blame] | 142 | |
| 143 | // This vector contains the PIDs of any child processes which have been |
| 144 | // created prior to the construction of the Zygote object, and must be reaped |
| 145 | // before the Zygote exits. The Zygote will perform a blocking wait on these |
| 146 | // children, so they must be guaranteed to be exiting by the time the Zygote |
| 147 | // exits. |
| 148 | std::vector<base::ProcessHandle> extra_children_; |
| 149 | |
| 150 | // This vector contains the FDs that must be closed before reaping the extra |
| 151 | // children. |
| 152 | std::vector<int> extra_fds_; |
kerrnel | 26b892f | 2015-11-10 19:06:31 | [diff] [blame] | 153 | |
| 154 | // The vector contains the child processes that need to be reaped. |
| 155 | std::vector<ZygoteProcessInfo> to_reap_; |
[email protected] | b75346c | 2012-05-13 03:48:38 | [diff] [blame] | 156 | }; |
| 157 | |
| 158 | } // namespace content |
| 159 | |
tfarina | bccc34c7 | 2015-02-27 21:32:15 | [diff] [blame] | 160 | #endif // CONTENT_ZYGOTE_ZYGOTE_LINUX_H_ |