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 #ifndef SERVICES_SERVICE_MANAGER_ZYGOTE_ZYGOTE_LINUX_H_ 6 #define SERVICES_SERVICE_MANAGER_ZYGOTE_ZYGOTE_LINUX_H_ 7 8 #include <stddef.h> 9 10 #include <memory> 11 #include <string> 12 #include <vector> 13 14 #include "base/containers/small_map.h" 15 #include "base/files/scoped_file.h" 16 #include "base/posix/global_descriptors.h" 17 #include "base/process/kill.h" 18 #include "base/process/process.h" 19 #include "base/process/process_handle.h" 20 #include "base/time/time.h" 21 22 namespace base { 23 class PickleIterator; 24 } 25 26 namespace service_manager { 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: 35 Zygote(int sandbox_flags, 36 std::vector<std::unique_ptr<ZygoteForkDelegate>> helpers, 37 const base::GlobalDescriptors::Descriptor& ipc_backchannel); 38 ~Zygote(); 39 40 bool ProcessRequests(); 41 42 private: 43 struct ZygoteProcessInfo { 44 // Pid from inside the Zygote's PID namespace. 45 base::ProcessHandle internal_pid; 46 // Keeps track of which fork delegate helper the process was started from. 47 ZygoteForkDelegate* started_from_helper; 48 // Records when the browser requested the zygote to reap this process. 49 base::TimeTicks time_of_reap_request; 50 // Notes whether the zygote has sent SIGKILL to this process. 51 bool sent_sigkill; 52 }; 53 using ZygoteProcessMap = 54 base::small_map<std::map<base::ProcessHandle, ZygoteProcessInfo>>; 55 56 // Retrieve a ZygoteProcessInfo from the process_info_map_. 57 // Returns true and write to process_info if |pid| can be found, return 58 // false otherwise. 59 bool GetProcessInfo(base::ProcessHandle pid, ZygoteProcessInfo* process_info); 60 61 // Returns true if the SUID sandbox is active. 62 bool UsingSUIDSandbox() const; 63 // Returns true if the NS sandbox is active. 64 bool UsingNSSandbox() const; 65 66 // --------------------------------------------------------------------------- 67 // Requests from the browser... 68 69 // Read and process a request from the browser. Returns true if we are in a 70 // new process and thus need to unwind back into ChromeMain. 71 bool HandleRequestFromBrowser(int fd); 72 73 void HandleReapRequest(int fd, base::PickleIterator iter); 74 75 // Get the termination status of |real_pid|. |real_pid| is the PID as it 76 // appears outside of the sandbox. 77 // Return true if it managed to get the termination status and return the 78 // status in |status| and the exit code in |exit_code|. 79 bool GetTerminationStatus(base::ProcessHandle real_pid, 80 bool known_dead, 81 base::TerminationStatus* status, 82 int* exit_code); 83 84 void HandleGetTerminationStatus(int fd, base::PickleIterator iter); 85 86 // This is equivalent to fork(), except that, when using the SUID sandbox, it 87 // returns the real PID of the child process as it appears outside the 88 // sandbox, rather than returning the PID inside the sandbox. The child's 89 // real PID is determined by having it call 90 // service_manager::SendZygoteChildPing(int) using the |pid_oracle| 91 // 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. 95 int ForkWithRealPid(const std::string& process_type, 96 const base::GlobalDescriptors::Mapping& fd_mapping, 97 const std::string& channel_id, 98 base::ScopedFD pid_oracle, 99 std::string* uma_name, 100 int* uma_sample, 101 int* uma_boundary_value); 102 103 // Unpacks process type and arguments from |iter| and forks a new process. 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(). 106 base::ProcessId ReadArgsAndFork(base::PickleIterator iter, 107 std::vector<base::ScopedFD> fds, 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, 117 base::PickleIterator iter, 118 std::vector<base::ScopedFD> fds); 119 120 bool HandleGetSandboxStatus(int fd, base::PickleIterator iter); 121 122 // Attempt to reap the child process by calling waitpid, and return 123 // whether successful. If the process has not terminated within 124 // 2 seconds of its reap request, send it SIGKILL. 125 bool ReapChild(const base::TimeTicks& now, ZygoteProcessInfo* child); 126 127 // Attempt to reap all outstanding children in |to_reap_|. 128 void ReapChildren(); 129 130 // The Zygote needs to keep some information about each process. Most 131 // notably what the PID of the process is inside the PID namespace of 132 // the Zygote and whether or not a process was started by the 133 // ZygoteForkDelegate helper. 134 ZygoteProcessMap process_info_map_; 135 136 const int sandbox_flags_; 137 std::vector<std::unique_ptr<ZygoteForkDelegate>> helpers_; 138 139 // Count of how many fork delegates for which we've invoked InitialUMA(). 140 size_t initial_uma_index_; 141 142 // The vector contains the child processes that need to be reaped. 143 std::vector<ZygoteProcessInfo> to_reap_; 144 145 // Sandbox IPC channel for renderers to invoke services from the browser. See 146 // https://chromium.googlesource.com/chromium/src/+/master/docs/linux/sandbox_ipc.md 147 base::GlobalDescriptors::Descriptor ipc_backchannel_; 148 }; 149 150 } // namespace service_manager 151 152 #endif // SERVICES_SERVICE_MANAGER_ZYGOTE_ZYGOTE_LINUX_H_ 153