OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <unistd.h> | 5 #include <unistd.h> |
6 #include <sys/epoll.h> | 6 #include <sys/epoll.h> |
7 #include <sys/types.h> | 7 #include <sys/types.h> |
8 #include <sys/socket.h> | 8 #include <sys/socket.h> |
9 #include <sys/signal.h> | 9 #include <sys/signal.h> |
10 #include <sys/prctl.h> | 10 #include <sys/prctl.h> |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 return false; | 208 return false; |
209 const int fd = fd_long; | 209 const int fd = fd_long; |
210 | 210 |
211 // Before entering the sandbox, "prime" any systems that need to open | 211 // Before entering the sandbox, "prime" any systems that need to open |
212 // files and cache the results or the descriptors. | 212 // files and cache the results or the descriptors. |
213 base::RandUint64(); | 213 base::RandUint64(); |
214 | 214 |
215 static const char kChrootMe = 'C'; | 215 static const char kChrootMe = 'C'; |
216 static const char kChrootMeSuccess = 'O'; | 216 static const char kChrootMeSuccess = 'O'; |
217 | 217 |
218 if (HANDLE_EINTR(write(fd, &kChrootMe, 1)) != 1) | 218 if (HANDLE_EINTR(write(fd, &kChrootMe, 1)) != 1) { |
| 219 LOG(ERROR) << "Failed to write to chroot pipe: " << errno; |
219 return false; | 220 return false; |
| 221 } |
220 | 222 |
221 char reply; | 223 char reply; |
222 if (HANDLE_EINTR(read(fd, &reply, 1)) != 1) | 224 std::vector<int> fds; |
| 225 if (!base::RecvMsg(fd, &reply, 1, &fds)) { |
| 226 LOG(ERROR) << "Failed to read from chroot pipe: " << errno; |
223 return false; | 227 return false; |
224 if (reply != kChrootMeSuccess) | 228 } |
| 229 if (reply != kChrootMeSuccess) { |
| 230 LOG(ERROR) << "Error code reply from chroot helper"; |
| 231 for (size_t i = 0; i < fds.size(); ++i) |
| 232 HANDLE_EINTR(close(fds[i])); |
225 return false; | 233 return false; |
226 if (chdir("/") == -1) | 234 } |
| 235 if (fds.size() != 1) { |
| 236 LOG(ERROR) << "Bad number of file descriptors from chroot helper"; |
| 237 for (size_t i = 0; i < fds.size(); ++i) |
| 238 HANDLE_EINTR(close(fds[i])); |
227 return false; | 239 return false; |
| 240 } |
| 241 if (fchdir(fds[0]) == -1) { |
| 242 LOG(ERROR) << "Failed to chdir to root directory: " << errno; |
| 243 HANDLE_EINTR(close(fds[0])); |
| 244 return false; |
| 245 } |
| 246 HANDLE_EINTR(close(fds[0])); |
228 | 247 |
229 static const int kMagicSandboxIPCDescriptor = 5; | 248 static const int kMagicSandboxIPCDescriptor = 5; |
230 SkiaFontConfigUseIPCImplementation(kMagicSandboxIPCDescriptor); | 249 SkiaFontConfigUseIPCImplementation(kMagicSandboxIPCDescriptor); |
231 | 250 |
232 // Previously, we required that the binary be non-readable. This causes the | 251 // Previously, we required that the binary be non-readable. This causes the |
233 // kernel to mark the process as non-dumpable at startup. The thinking was | 252 // kernel to mark the process as non-dumpable at startup. The thinking was |
234 // that, although we were putting the renderers into a PID namespace (with | 253 // that, although we were putting the renderers into a PID namespace (with |
235 // the SUID sandbox), they would nonetheless be in the /same/ PID | 254 // the SUID sandbox), they would nonetheless be in the /same/ PID |
236 // namespace. So they could ptrace each other unless they were non-dumpable. | 255 // namespace. So they could ptrace each other unless they were non-dumpable. |
237 // | 256 // |
238 // If the binary was readable, then there would be a window between process | 257 // If the binary was readable, then there would be a window between process |
239 // startup and the point where we set the non-dumpable flag in which a | 258 // startup and the point where we set the non-dumpable flag in which a |
240 // compromised renderer could ptrace attach. | 259 // compromised renderer could ptrace attach. |
241 // | 260 // |
242 // However, now that we have a zygote model, only the (trusted) zygote | 261 // However, now that we have a zygote model, only the (trusted) zygote |
243 // exists at this point and we can set the non-dumpable flag which is | 262 // exists at this point and we can set the non-dumpable flag which is |
244 // inherited by all our renderer children. | 263 // inherited by all our renderer children. |
245 prctl(PR_SET_DUMPABLE, 0, 0, 0, 0); | 264 prctl(PR_SET_DUMPABLE, 0, 0, 0, 0); |
246 if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) | 265 if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) { |
| 266 LOG(ERROR) << "Failed to set non-dumpable flag"; |
247 return false; | 267 return false; |
| 268 } |
248 } else { | 269 } else { |
249 SkiaFontConfigUseDirectImplementation(); | 270 SkiaFontConfigUseDirectImplementation(); |
250 } | 271 } |
251 | 272 |
252 return true; | 273 return true; |
253 } | 274 } |
254 | 275 |
255 bool ZygoteMain(const MainFunctionParams& params) { | 276 bool ZygoteMain(const MainFunctionParams& params) { |
256 if (!MaybeEnterChroot()) { | 277 if (!MaybeEnterChroot()) { |
257 LOG(FATAL) << "Failed to enter sandbox. Fail safe abort. (errno: " | 278 LOG(FATAL) << "Failed to enter sandbox. Fail safe abort. (errno: " |
258 << errno << ")"; | 279 << errno << ")"; |
259 return false; | 280 return false; |
260 } | 281 } |
261 | 282 |
262 Zygote zygote; | 283 Zygote zygote; |
263 return zygote.ProcessRequests(); | 284 return zygote.ProcessRequests(); |
264 } | 285 } |
OLD | NEW |