1 // Copyright 2015 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_HOST_ZYGOTE_COMMUNICATION_LINUX_H_
6 #define SERVICES_SERVICE_MANAGER_ZYGOTE_HOST_ZYGOTE_COMMUNICATION_LINUX_H_
7 
8 #include <memory>
9 #include <set>
10 #include <string>
11 #include <vector>
12 
13 #include <sys/types.h>
14 
15 #include "base/callback.h"
16 #include "base/component_export.h"
17 #include "base/files/scoped_file.h"
18 #include "base/process/kill.h"
19 #include "base/process/launch.h"
20 #include "base/process/process_handle.h"
21 #include "base/synchronization/lock.h"
22 
23 namespace base {
24 class Pickle;
25 }  // namespace base
26 
27 namespace service_manager {
28 
29 // Handles interprocess communication with the Linux zygote process. The zygote
30 // does not use standard Chrome IPC or mojo, see:
31 // https://chromium.googlesource.com/chromium/src/+/master/docs/linux/sandbox_ipc.md
COMPONENT_EXPORT(SERVICE_MANAGER_ZYGOTE)32 class COMPONENT_EXPORT(SERVICE_MANAGER_ZYGOTE) ZygoteCommunication {
33  public:
34   enum class ZygoteType { kSandboxed, kUnsandboxed };
35   explicit ZygoteCommunication(ZygoteType type);
36   ~ZygoteCommunication();
37 
38   void Init(
39       base::OnceCallback<pid_t(base::CommandLine*, base::ScopedFD*)> launcher);
40 
41   // Tries to start a process of type indicated by process_type.
42   // Returns its pid on success, otherwise base::kNullProcessHandle;
43   pid_t ForkRequest(const std::vector<std::string>& command_line,
44                     const base::FileHandleMappingVector& mapping,
45                     const std::string& process_type);
46 
47   void EnsureProcessTerminated(pid_t process);
48 
49   // Should be called every time a Zygote child died.
50   void ZygoteChildDied(pid_t process);
51 
52   // Get the termination status (and, optionally, the exit code) of
53   // the process. |exit_code| is set to the exit code of the child
54   // process. (|exit_code| may be NULL.)
55   // Unfortunately the Zygote can not accurately figure out if a process
56   // is already dead without waiting synchronously for it.
57   // |known_dead| should be set to true when we already know that the process
58   // is dead. When |known_dead| is false, processes could be seen as
59   // still running, even when they're not. When |known_dead| is true, the
60   // process will be SIGKILL-ed first (which should have no effect if it was
61   // really dead). This is to prevent a waiting waitpid() from blocking in
62   // a single-threaded Zygote. See https://crbug.com/157458.
63   base::TerminationStatus GetTerminationStatus(base::ProcessHandle handle,
64                                                bool known_dead,
65                                                int* exit_code);
66 
67   // Returns the sandbox status of this zygote.
68   int GetSandboxStatus();
69 
70  private:
71   // Should be called every time a Zygote child is born.
72   void ZygoteChildBorn(pid_t process);
73 
74   // Read the reply from the zygote.
75   ssize_t ReadReply(void* buf, size_t buf_len);
76 
77   // Sends |data| to the zygote via |control_fd_|.  If |fds| is non-NULL, the
78   // included file descriptors will also be passed.  The caller is responsible
79   // for acquiring |control_lock_|.
80   bool SendMessage(const base::Pickle& data, const std::vector<int>* fds);
81 
82   // Get the sandbox status from the zygote.
83   ssize_t ReadSandboxStatus();
84 
85   // Indicates whether the Zygote starts unsandboxed or not.
86   const ZygoteType type_;
87 
88   base::ScopedFD control_fd_;  // the socket to the zygote.
89   // A lock protecting all communication with the zygote. This lock must be
90   // acquired before sending a command and released after the result has been
91   // received.
92   base::Lock control_lock_;
93   // The pid of the zygote.
94   pid_t pid_;
95   // The list of running zygote children.
96   std::set<pid_t> list_of_running_zygote_children_;
97   // The lock to guard the list of running zygote children.
98   base::Lock child_tracking_lock_;
99   int sandbox_status_;
100   bool have_read_sandbox_status_word_;
101   // Set to true when the zygote is initialized successfully.
102   bool init_;
103 };
104 
105 }  // namespace service_manager
106 
107 #endif  // SERVICES_SERVICE_MANAGER_ZYGOTE_HOST_ZYGOTE_COMMUNICATION_LINUX_H_
108