| 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 |