OLD | NEW |
1 // Copyright 2014 The Crashpad Authors. All rights reserved. | 1 // Copyright 2014 The Crashpad Authors. All rights reserved. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and |
13 // limitations under the License. | 13 // limitations under the License. |
14 | 14 |
15 #ifndef CRASHPAD_UTIL_MACH_CHILD_PORT_HANDSHAKE_H_ | 15 #ifndef CRASHPAD_UTIL_MACH_CHILD_PORT_HANDSHAKE_H_ |
16 #define CRASHPAD_UTIL_MACH_CHILD_PORT_HANDSHAKE_H_ | 16 #define CRASHPAD_UTIL_MACH_CHILD_PORT_HANDSHAKE_H_ |
17 | 17 |
18 #include <mach/mach.h> | 18 #include <mach/mach.h> |
19 | 19 |
20 #include <string> | 20 #include <string> |
21 | 21 |
22 #include "base/basictypes.h" | 22 #include "base/basictypes.h" |
23 #include "base/files/scoped_file.h" | 23 #include "base/files/scoped_file.h" |
24 #include "util/mach/child_port_server.h" | 24 #include "util/mach/child_port_types.h" |
25 | 25 |
26 namespace crashpad { | 26 namespace crashpad { |
27 | 27 |
28 namespace test { | 28 namespace test { |
29 namespace { | 29 namespace { |
30 class ChildPortHandshakeTest; | 30 class ChildPortHandshakeTest; |
31 } // namespace | 31 } // namespace |
32 } // namespace test | 32 } // namespace test |
33 | 33 |
34 //! \brief Implements a handshake protocol that allows a parent process to | 34 //! \brief Implements a handshake protocol that allows processes to exchange |
35 //! obtain a Mach port right from a child process. | 35 //! port rights. |
36 //! | 36 //! |
37 //! Ordinarily, there is no way for parent and child processes to exchange port | 37 //! Ordinarily, there is no way for parent and child processes to exchange port |
38 //! rights, outside of the rights that children inherit from their parents. | 38 //! rights, outside of the rights that children inherit from their parents. |
39 //! These include task-special ports and exception ports, but all of these have | 39 //! These include task-special ports and exception ports, but all of these have |
40 //! system-defined uses, and cannot reliably be replaced: in a multi-threaded | 40 //! system-defined uses, and cannot reliably be replaced: in a multi-threaded |
41 //! parent, it is impossible to temporarily change one an inheritable port while | 41 //! parent, it is impossible to temporarily change an inheritable port while |
42 //! maintaining a guarantee that another thread will not attempt to use it, and | 42 //! maintaining a guarantee that another thread will not attempt to use it, and |
43 //! in children, it difficult to guarantee that nothing will attempt to use an | 43 //! in children, it difficult to guarantee that nothing will attempt to use an |
44 //! inheritable port before it can be replaced with the correct one. This latter | 44 //! inheritable port before it can be replaced with the correct one. This latter |
45 //! concern is becoming increasingly more pronounced as system libraries perform | 45 //! concern is becoming increasingly more pronounced as system libraries perform |
46 //! more operations that rely on an inheritable port in module initializers. | 46 //! more operations that rely on an inherited port in module initializers. |
47 //! | 47 //! |
48 //! The protocol implemented by this class involves a server that runs in the | 48 //! The protocol implemented by this class involves a server that runs in one |
49 //! parent process. The server is published with the bootstrap server, which the | 49 //! process. The server is published with the bootstrap server, which the other |
50 //! child has access to because the bootstrap port is one of the inherited | 50 //! process has access to because the bootstrap port is one of the inherited |
51 //! task-special ports. The parent and child also share a pipe, which the parent | 51 //! task-special ports. The two processes also share a pipe, which the server |
52 //! can write to and the child can read from. After launching a child process, | 52 //! can write to and the client can read from. The server will write a random |
53 //! the parent will write a random token to this pipe, along with the name under | 53 //! token to this pipe, along with the name under which its service has been |
54 //! which its server has been registered with the bootstrap server. The child | 54 //! registered with the bootstrap server. The client can then obtain a send |
55 //! can then obtain a send right to this server with `bootstrap_look_up()`, and | 55 //! right to this service with `bootstrap_look_up()`, and send a check-in |
56 //! send a check-in message containing the token value and the port right of its | 56 //! message containing the token value and the port right of its choice by |
57 //! choice by calling `child_port_check_in()`. | 57 //! calling `child_port_check_in()`. |
58 //! | 58 //! |
59 //! The inclusion of the token authenticates the child to its parent. This is | 59 //! The inclusion of the token authenticates the client to the server. This is |
60 //! necessary because the service is published with the bootstrap server, which | 60 //! necessary because the service is published with the bootstrap server, which |
61 //! opens up access to it to more than the child process. Because the token is | 61 //! opens up access to it to more than the intended client. Because the token is |
62 //! passed to the child by a shared pipe, it constitutes a shared secret not | 62 //! passed to the client by a shared pipe, it constitutes a shared secret not |
63 //! known by other processes that may have incidental access to the server. The | 63 //! known by other processes that may have incidental access to the server. The |
64 //! ChildPortHandshake server considers its randomly-generated token valid until | 64 //! ChildPortHandshake server considers its randomly-generated token valid until |
65 //! a client checks in with it. This mechanism is used instead of examining the | 65 //! a client checks in with it. This mechanism is used instead of examining the |
66 //! request message’s audit trailer to verify the sender’s process ID because in | 66 //! request message’s audit trailer to verify the sender’s process ID because in |
67 //! some process architectures, it may be impossible to verify the child’s | 67 //! some process architectures, it may be impossible to verify the client’s |
68 //! process ID. This may happen when the child disassociates from the parent | 68 //! process ID. |
69 //! with a double fork(), and the actual client is the parent’s grandchild. In | |
70 //! this case, the child would not check in, but the grandchild, in possession | |
71 //! of the token, would check in. | |
72 //! | 69 //! |
73 //! The shared pipe serves another purpose: the server monitors it for an | 70 //! The shared pipe serves another purpose: the server monitors it for an |
74 //! end-of-file (no readers) condition. Once detected, it will stop its blocking | 71 //! end-of-file (no readers) condition. Once detected, it will stop its blocking |
75 //! wait for a client to check in. This mechanism was chosen over monitoring a | 72 //! wait for a client to check in. This mechanism was also chosen for its |
76 //! child process directly for exit to account for the possibility that the | 73 //! ability to function properly in diverse process architectures. |
77 //! child might disassociate with a double fork(). | |
78 //! | 74 //! |
79 //! This class can be used to allow a child process to provide its parent with | 75 //! This class can be used to allow a child process to provide its parent with a |
80 //! a send right to its task port, in cases where it is desirable for the parent | 76 //! send right to its task port, in cases where it is desirable for the parent |
81 //! to have such access. It can also be used to allow a child process to | 77 //! to have such access. It can also be used to allow a parent process to |
82 //! establish its own server and provide its parent with a send right to that | 78 //! transfer a receive right to a child process that implements the server for |
83 //! server, for cases where a service is provided and it is undesirable or | 79 //! that right, or for a child process to establish its own server and provide |
84 //! impossible to provide it via the bootstrap or launchd interfaces. | 80 //! its parent with a send right to that server, for cases where a service is |
85 class ChildPortHandshake : public ChildPortServer::Interface { | 81 //! provided and it is undesirable or impossible to provide it via the bootstrap |
| 82 //! or launchd interfaces. |
| 83 //! |
| 84 //! Example parent process, running a client that sends a receive right to its |
| 85 //! child: |
| 86 //! \code |
| 87 //! ChildPortHandshake child_port_handshake; |
| 88 //! base::ScopedFD server_write_fd = child_port_handshake.ServerWriteFD(); |
| 89 //! std::string server_write_fd_string = |
| 90 //! base::StringPrintf("%d", server_write_fd); |
| 91 //! |
| 92 //! pid_t pid = fork(); |
| 93 //! if (pid == 0) { |
| 94 //! // Child |
| 95 //! |
| 96 //! // Close all file descriptors above STDERR_FILENO except for |
| 97 //! // server_write_fd. Let the child know what file descriptor to use for |
| 98 //! // server_write_fd by passing it as argv[1]. Example code for the child |
| 99 //! // process is below. |
| 100 //! CloseMultipleNowOrOnExec(STDERR_FILENO + 1, server_write_fd); |
| 101 //! execlp("child", "child", server_write_fd_string.c_str(), nullptr); |
| 102 //! } |
| 103 //! |
| 104 //! // Parent |
| 105 //! |
| 106 //! // Close the child’s end of the pipe. |
| 107 //! server_write_fd.reset(); |
| 108 //! |
| 109 //! // Make a new Mach receive right. |
| 110 //! base::mac::ScopedMachReceiveRight |
| 111 //! receive_right(NewMachPort(MACH_PORT_RIGHT_RECEIVE)); |
| 112 //! |
| 113 //! // Make a send right corresponding to the receive right. |
| 114 //! mach_port_t send_right; |
| 115 //! mach_msg_type_name_t send_right_type; |
| 116 //! mach_port_extract_right(mach_task_self(), |
| 117 //! receive_right.get(), |
| 118 //! MACH_MSG_TYPE_MAKE_SEND, |
| 119 //! &send_right, |
| 120 //! &send_right_type); |
| 121 //! base::mac::ScopedMachSendRight send_right_owner(send_right); |
| 122 //! |
| 123 //! // Send the receive right to the child process, retaining the send right |
| 124 //! // for use in the parent process. |
| 125 //! if (child_port_handshake.RunClient(receive_right, |
| 126 //! MACH_MSG_TYPE_MOVE_RECEIVE)) { |
| 127 //! ignore_result(receive_right.release()); |
| 128 //! } |
| 129 //! \endcode |
| 130 //! |
| 131 //! Example child process, running a server that receives a receive right from |
| 132 //! its parent: |
| 133 //! \code |
| 134 //! int main(int argc, char* argv[]) { |
| 135 //! // The parent passed server_write_fd in argv[1]. |
| 136 //! base::ScopedFD server_write_fd(atoi(argv[1])); |
| 137 //! |
| 138 //! // Obtain a receive right from the parent process. |
| 139 //! base::mac::ScopedMachReceiveRight receive_right( |
| 140 //! ChildPortHandshake::RunServerForFD( |
| 141 //! server_write_fd.Pass(), |
| 142 //! ChildPortHandshake::PortRightType::kReceiveRight)); |
| 143 //! } |
| 144 //! \endcode |
| 145 class ChildPortHandshake { |
86 public: | 146 public: |
87 //! \brief Initializes the server. | 147 //! \brief Controls whether a receive or send right is expected to be |
88 //! | 148 //! obtained from the client by the server’s call to RunServer(). |
89 //! This creates the pipe so that the “read” side can be obtained by calling | 149 enum class PortRightType { |
90 //! ReadPipeFD(). | 150 //! \brief The server expects to receive a receive right. |
| 151 kReceiveRight = 0, |
| 152 |
| 153 //! \brief The server expects to receive a send or send-once right. |
| 154 kSendRight, |
| 155 }; |
| 156 |
91 ChildPortHandshake(); | 157 ChildPortHandshake(); |
92 | |
93 ~ChildPortHandshake(); | 158 ~ChildPortHandshake(); |
94 | 159 |
95 //! \brief Obtains the “read” side of the pipe, to be used by the client. | 160 //! \brief Obtains the “read” side of the pipe, to be used by the client. |
96 //! | 161 //! |
97 //! Callers must obtain this file descriptor and arrange for the caller to | 162 //! This file descriptor must be passed to RunClientForFD(). |
98 //! have access to it before calling RunServer(). | |
99 //! | 163 //! |
100 //! \return The file descriptor that the client should read from. | 164 //! \return The file descriptor that the client should read from. |
101 int ReadPipeFD() const; | 165 base::ScopedFD ClientReadFD(); |
| 166 |
| 167 //! \brief Obtains the “write” side of the pipe, to be used by the server. |
| 168 //! |
| 169 //! This file descriptor must be passed to RunServerForFD(). |
| 170 //! |
| 171 //! \return The file descriptor that the server should write to. |
| 172 base::ScopedFD ServerWriteFD(); |
102 | 173 |
103 //! \brief Runs the server. | 174 //! \brief Runs the server. |
104 //! | 175 //! |
105 //! This method performs these tasks: | 176 //! This method closes the “read” side of the pipe in-process, so that the |
106 //! - Closes the “read” side of the pipe in-process, so that the client | 177 //! client process holds the only file descriptor that can read from the pipe. |
107 //! process holds the only file descriptor that can read from the pipe. | 178 //! It then calls RunServerForFD() using the “write” side of the pipe. If |
| 179 //! ClientReadFD() has already been called in the server process, the caller |
| 180 //! must ensure that the file descriptor returned by ClientReadFD() is closed |
| 181 //! prior to calling this method. |
| 182 mach_port_t RunServer(PortRightType port_right_type); |
| 183 |
| 184 //! \brief Runs the client. |
| 185 //! |
| 186 //! This method closes the “write” side of the pipe in-process, so that the |
| 187 //! server process holds the only file descriptor that can write to the pipe. |
| 188 //! It then calls RunClientForFD() using the “read” side of the pipe. If |
| 189 //! ServerWriteFD() has already been called in the client process, the caller |
| 190 //! must ensure that the file descriptor returned by ServerWriteFD() is closed |
| 191 //! prior to calling this method. |
| 192 //! |
| 193 //! \return `true` on success, `false` on failure with a message logged. |
| 194 bool RunClient(mach_port_t port, mach_msg_type_name_t right_type); |
| 195 |
| 196 //! \brief Runs the server. |
| 197 //! |
| 198 //! If a ChildPortHandshake object is available, don’t call this static |
| 199 //! function. Instead, call RunServer(), which wraps this function. When using |
| 200 //! this function, the caller is responsible for ensuring that the client |
| 201 //! “read” side of the pipe is closed in the server process prior to calling |
| 202 //! this function. |
| 203 //! |
| 204 //! This function performs these tasks: |
108 //! - Creates a random token and sends it via the pipe. | 205 //! - Creates a random token and sends it via the pipe. |
109 //! - Checks its service in with the bootstrap server, and sends the name | 206 //! - Checks its service in with the bootstrap server, and sends the name |
110 //! of its bootstrap service mapping via the pipe. | 207 //! of its bootstrap service mapping via the pipe. |
111 //! - Simultaneously receives messages on its Mach server and monitors the | 208 //! - Simultaneously receives messages on its Mach server and monitors the |
112 //! pipe for end-of-file. This is a blocking operation. | 209 //! pipe for end-of-file. This is a blocking operation. |
113 //! - When a Mach message is received, calls HandleChildPortCheckIn() to | 210 //! - When a Mach message is received, calls HandleChildPortCheckIn() to |
114 //! interpret and validate it, and if the message is valid, returns the | 211 //! interpret and validate it, and if the message is valid, returns the |
115 //! port right extracted from the message. If the message is not valid, | 212 //! port right extracted from the message. If the message is not valid, |
116 //! this method will continue waiting for a valid message. Valid messages | 213 //! this method will continue waiting for a valid message. Valid messages |
117 //! are properly formatted and have the correct token. If a valid message | 214 //! are properly formatted and have the correct token. The right carried in |
118 //! carries a send or send-once right, it will be returned. If a valid | 215 //! a valid message will be returned. If a message is not valid, this |
119 //! message contains a receive right, it will be destroyed and | |
120 //! `MACH_PORT_NULL` will be returned. If a message is not valid, this | |
121 //! method will continue waiting for pipe EOF or a valid message. | 216 //! method will continue waiting for pipe EOF or a valid message. |
122 //! - When notified of pipe EOF, returns `MACH_PORT_NULL`. | 217 //! - When notified of pipe EOF, returns `MACH_PORT_NULL`. |
123 //! - Regardless of return value, destroys the server’s receive right and | 218 //! - Regardless of return value, destroys the server’s receive right and |
124 //! closes the pipe. | 219 //! closes the pipe. |
125 //! | 220 //! |
126 //! \return On success, the send or send-once right to the port provided by | 221 //! \param[in] port_right_type The port right type expected to be received |
127 //! the client. The caller takes ownership of this right. On failure, | 222 //! from the client. If the port right received from the client does not |
128 //! `MACH_PORT_NULL`, indicating that the client did not check in properly | 223 //! match the expected type, the received port right will be destroyed, |
129 //! before terminating, where termination is detected by noticing that the | 224 //! and `MACH_PORT_NULL` will be returned. |
130 //! read side of the shared pipe has closed. On failure, a message | 225 //! |
131 //! indiciating the nature of the failure will be logged. | 226 //! \return On success, the port right provided by the client. The caller |
132 mach_port_t RunServer(); | 227 //! takes ownership of this right. On failure, `MACH_PORT_NULL`, |
133 | 228 //! indicating that the client did not check in properly before |
134 // ChildPortServer::Interface: | 229 //! terminating, where termination is detected by detecting that the read |
135 kern_return_t HandleChildPortCheckIn(child_port_server_t server, | 230 //! side of the shared pipe has closed. On failure, a message indicating |
136 child_port_token_t token, | 231 //! the nature of the failure will be logged. |
137 mach_port_t port, | 232 static mach_port_t RunServerForFD(base::ScopedFD server_write_fd, |
138 mach_msg_type_name_t right_type, | 233 PortRightType port_right_type); |
139 const mach_msg_trailer_t* trailer, | |
140 bool* destroy_request) override; | |
141 | 234 |
142 //! \brief Runs the client. | 235 //! \brief Runs the client. |
143 //! | 236 //! |
| 237 //! If a ChildPortHandshake object is available, don’t call this static |
| 238 //! function. Instead, call RunClient(), which wraps this function. When using |
| 239 //! this function, the caller is responsible for ensuring that the server |
| 240 //! “write” side of the pipe is closed in the client process prior to calling |
| 241 //! this function. |
| 242 //! |
144 //! This function performs these tasks: | 243 //! This function performs these tasks: |
145 //! - Reads the token from the pipe. | 244 //! - Reads the token from the pipe. |
146 //! - Reads the bootstrap service name from the pipe. | 245 //! - Reads the bootstrap service name from the pipe. |
147 //! - Obtains a send right to the server by calling `bootstrap_look_up()`. | 246 //! - Obtains a send right to the server by calling `bootstrap_look_up()`. |
148 //! - Sends a check-in message to the server by calling | 247 //! - Sends a check-in message to the server by calling |
149 //! `child_port_check_in()`, providing the token and the user-supplied port | 248 //! `child_port_check_in()`, providing the token and the user-supplied port |
150 //! right. | 249 //! right. |
151 //! - Deallocates the send right to the server, and closes the pipe. | 250 //! - Deallocates the send right to the server, and closes the pipe. |
152 //! | 251 //! |
153 //! There is no return value because `child_port_check_in()` is a MIG | 252 //! There is no return value because `child_port_check_in()` is a MIG |
154 //! `simpleroutine`, and the server does not send a reply. This allows | 253 //! `simpleroutine`, and the server does not send a reply. This allows |
155 //! check-in to occur without blocking to wait for a reply. | 254 //! check-in to occur without blocking to wait for a reply. |
156 //! | 255 //! |
157 //! \param[in] pipe_read The “read” side of the pipe shared with the server | 256 //! \param[in] pipe_read The “read” side of the pipe shared with the server |
158 //! process. | 257 //! process. This function takes ownership of this file descriptor, and |
159 //! \param[in] port The port that will be passed to the server by | 258 //! will close it prior to returning. |
| 259 //! \param[in] port The port right that will be passed to the server by |
160 //! `child_port_check_in()`. | 260 //! `child_port_check_in()`. |
161 //! \param[in] right_type The right type to furnish the parent with. If \a | 261 //! \param[in] right_type The right type to furnish the server with. If \a |
162 //! port is a send right, this can be `MACH_MSG_TYPE_COPY_SEND` or | 262 //! port is a send right, this can be `MACH_MSG_TYPE_COPY_SEND` or |
163 //! `MACH_MSG_TYPE_MOVE_SEND`. If \a port is a send-once right, this can | 263 //! `MACH_MSG_TYPE_MOVE_SEND`. If \a port is a send-once right, this can |
164 //! be `MACH_MSG_TYPE_MOVE_SEND_ONCE`. If \a port is a receive right, | 264 //! be `MACH_MSG_TYPE_MOVE_SEND_ONCE`. If \a port is a receive right, this |
165 //! this can be `MACH_MSG_TYPE_MAKE_SEND`. `MACH_MSG_TYPE_MOVE_RECEIVE` | 265 //! can be `MACH_MSG_TYPE_MAKE_SEND`, `MACH_MSG_TYPE_MAKE_SEND_ONCE`, or |
166 //! is supported by the client interface but will be silently rejected by | 266 //! `MACH_MSG_TYPE_MOVE_RECEIVE`. |
167 //! server run by RunServer(), which expects to receive only send or | 267 //! |
168 //! send-once rights. | 268 //! \return `true` on success, `false` on failure with a message logged. On |
169 static void RunClient(int pipe_read, | 269 //! failure, the port right corresponding to a \a right_type of |
170 mach_port_t port, | 270 //! `MACH_MSG_TYPE_MOVE_*` is not consumed, and the caller must dispose of |
171 mach_msg_type_name_t right_type); | 271 //! the right if necessary. |
| 272 static bool RunClientForFD(base::ScopedFD client_read_fd, |
| 273 mach_port_t port, |
| 274 mach_msg_type_name_t right_type); |
172 | 275 |
173 private: | 276 private: |
174 //! \brief Runs the read-from-pipe portion of the client’s side of the | 277 //! \brief Runs the read-from-pipe portion of the client’s side of the |
175 //! handshake. This is an implementation detail of RunClient and is only | 278 //! handshake. This is an implementation detail of RunClient and is only |
176 //! exposed for testing purposes. | 279 //! exposed for testing purposes. |
177 //! | 280 //! |
| 281 //! When using this function and RunClientInternal_SendCheckIn(), the caller |
| 282 //! is responsible for closing \a pipe_read at an appropriate time, normally |
| 283 //! after calling RunClientInternal_SendCheckIn(). |
| 284 //! |
178 //! \param[in] pipe_read The “read” side of the pipe shared with the server | 285 //! \param[in] pipe_read The “read” side of the pipe shared with the server |
179 //! process. | 286 //! process. |
180 //! \param[out] token The token value read from \a pipe_read. | 287 //! \param[out] token The token value read from \a pipe_read. |
181 //! \param[out] service_name The service name as registered with the bootstrap | 288 //! \param[out] service_name The service name as registered with the bootstrap |
182 //! server, read from \a pipe_read. | 289 //! server, read from \a pipe_read. |
183 static void RunClientInternal_ReadPipe(int pipe_read, | 290 //! |
| 291 //! \return `true` on success, `false` on failure with a message logged. |
| 292 static bool RunClientInternal_ReadPipe(int pipe_read, |
184 child_port_token_t* token, | 293 child_port_token_t* token, |
185 std::string* service_name); | 294 std::string* service_name); |
186 | 295 |
187 //! \brief Runs the check-in portion of the client’s side of the handshake. | 296 //! \brief Runs the check-in portion of the client’s side of the handshake. |
188 //! This is an implementation detail of RunClient and is only exposed for | 297 //! This is an implementation detail of RunClient and is only exposed for |
189 //! testing purposes. | 298 //! testing purposes. |
190 //! | 299 //! |
| 300 //! When using this RunClientInternal_ReadPipe() and this function, the caller |
| 301 //! is responsible for closing the “read” side of the pipe at an appropriate |
| 302 //! time, normally after calling this function. |
| 303 //! |
191 //! \param[in] service_name The service name as registered with the bootstrap | 304 //! \param[in] service_name The service name as registered with the bootstrap |
192 //! server, to be looked up with `bootstrap_look_up()`. | 305 //! server, to be looked up with `bootstrap_look_up()`. |
193 //! \param[in] token The token value to provide during check-in. | 306 //! \param[in] token The token value to provide during check-in. |
194 //! \param[in] port The port that will be passed to the server by | 307 //! \param[in] port The port that will be passed to the server by |
195 //! `child_port_check_in()`. | 308 //! `child_port_check_in()`. |
196 //! \param[in] right_type The right type to furnish the parent with. | 309 //! \param[in] right_type The right type to furnish the server with. |
197 static void RunClientInternal_SendCheckIn(const std::string& service_name, | 310 //! |
| 311 //! \return `true` on success, `false` on failure with a message logged. |
| 312 static bool RunClientInternal_SendCheckIn(const std::string& service_name, |
198 child_port_token_t token, | 313 child_port_token_t token, |
199 mach_port_t port, | 314 mach_port_t port, |
200 mach_msg_type_name_t right_type); | 315 mach_msg_type_name_t right_type); |
201 | 316 |
202 // Communicates the token from RunServer(), where it’s generated, to | 317 base::ScopedFD client_read_fd_; |
203 // HandleChildPortCheckIn(), where it’s validated. | 318 base::ScopedFD server_write_fd_; |
204 child_port_token_t token_; | |
205 | |
206 base::ScopedFD pipe_read_; | |
207 base::ScopedFD pipe_write_; | |
208 | |
209 // Communicates the port received from the client from | |
210 // HandleChildPortCheckIn(), where it’s received, to RunServer(), where it’s | |
211 // returned. This is strongly-owned, but ownership is transferred to | |
212 // RunServer()’s caller. | |
213 mach_port_t child_port_; | |
214 | |
215 // Communicates that a check-in with a valid token was received by | |
216 // HandleChildPortCheckIn(), and that the value of child_port_ should be | |
217 // returned to RunServer()’s caller. | |
218 bool checked_in_; | |
219 | 319 |
220 friend class test::ChildPortHandshakeTest; | 320 friend class test::ChildPortHandshakeTest; |
221 | 321 |
222 DISALLOW_COPY_AND_ASSIGN(ChildPortHandshake); | 322 DISALLOW_COPY_AND_ASSIGN(ChildPortHandshake); |
223 }; | 323 }; |
224 | 324 |
225 } // namespace crashpad | 325 } // namespace crashpad |
226 | 326 |
227 #endif // CRASHPAD_UTIL_MACH_CHILD_PORT_HANDSHAKE_H_ | 327 #endif // CRASHPAD_UTIL_MACH_CHILD_PORT_HANDSHAKE_H_ |
OLD | NEW |