Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(289)

Side by Side Diff: content/zygote/zygote_main_linux.cc

Issue 10388013: Move the Linux zygote stuff into its own per-process directory. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « content/public/common/sandbox_linux.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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 "content/browser/zygote_host_impl_linux.h"
6
7 #include <dlfcn.h> 5 #include <dlfcn.h>
8 #include <fcntl.h> 6 #include <fcntl.h>
9 #include <pthread.h> 7 #include <pthread.h>
10 #include <stdio.h> 8 #include <stdio.h>
11 #include <sys/socket.h> 9 #include <sys/socket.h>
12 #include <sys/stat.h> 10 #include <sys/stat.h>
13 #include <sys/types.h> 11 #include <sys/types.h>
14 #include <sys/wait.h> 12 #include <sys/wait.h>
15 #include <unistd.h> 13 #include <unistd.h>
16 14
(...skipping 14 matching lines...) Expand all
31 #include "base/sys_info.h" 29 #include "base/sys_info.h"
32 #include "build/build_config.h" 30 #include "build/build_config.h"
33 #include "crypto/nss_util.h" 31 #include "crypto/nss_util.h"
34 #include "content/common/chrome_descriptors.h" 32 #include "content/common/chrome_descriptors.h"
35 #include "content/common/font_config_ipc_linux.h" 33 #include "content/common/font_config_ipc_linux.h"
36 #include "content/common/pepper_plugin_registry.h" 34 #include "content/common/pepper_plugin_registry.h"
37 #include "content/common/sandbox_methods_linux.h" 35 #include "content/common/sandbox_methods_linux.h"
38 #include "content/common/seccomp_sandbox.h" 36 #include "content/common/seccomp_sandbox.h"
39 #include "content/common/set_process_title.h" 37 #include "content/common/set_process_title.h"
40 #include "content/common/unix_domain_socket_posix.h" 38 #include "content/common/unix_domain_socket_posix.h"
39 #include "content/common/zygote_commands_linux.h"
41 #include "content/public/common/content_switches.h" 40 #include "content/public/common/content_switches.h"
42 #include "content/public/common/main_function_params.h" 41 #include "content/public/common/main_function_params.h"
43 #include "content/public/common/result_codes.h" 42 #include "content/public/common/result_codes.h"
43 #include "content/public/common/sandbox_linux.h"
44 #include "content/public/common/zygote_fork_delegate_linux.h" 44 #include "content/public/common/zygote_fork_delegate_linux.h"
45 #include "skia/ext/SkFontHost_fontconfig_control.h" 45 #include "skia/ext/SkFontHost_fontconfig_control.h"
46 #include "unicode/timezone.h" 46 #include "unicode/timezone.h"
47 #include "ipc/ipc_channel.h" 47 #include "ipc/ipc_channel.h"
48 #include "ipc/ipc_switches.h" 48 #include "ipc/ipc_switches.h"
49 49
50 #if defined(OS_LINUX) 50 #if defined(OS_LINUX)
51 #include <sys/epoll.h> 51 #include <sys/epoll.h>
52 #include <sys/prctl.h> 52 #include <sys/prctl.h>
53 #include <sys/signal.h> 53 #include <sys/signal.h>
54 #else 54 #else
55 #include <signal.h> 55 #include <signal.h>
56 #endif 56 #endif
57 57
58 #if defined(CHROMIUM_SELINUX) 58 #if defined(CHROMIUM_SELINUX)
59 #include <selinux/selinux.h> 59 #include <selinux/selinux.h>
60 #include <selinux/context.h> 60 #include <selinux/context.h>
61 #endif 61 #endif
62 62
63 namespace content {
64
63 // http://code.google.com/p/chromium/wiki/LinuxZygote 65 // http://code.google.com/p/chromium/wiki/LinuxZygote
64 66
65 static const int kBrowserDescriptor = 3; 67 static const int kBrowserDescriptor = 3;
66 static const int kMagicSandboxIPCDescriptor = 5; 68 static const int kMagicSandboxIPCDescriptor = 5;
67 static const int kZygoteIdDescriptor = 7; 69 static const int kZygoteIdDescriptor = 7;
68 static bool g_suid_sandbox_active = false; 70 static bool g_suid_sandbox_active = false;
69 71
70 static const char kUrandomDevPath[] = "/dev/urandom"; 72 static const char kUrandomDevPath[] = "/dev/urandom";
71 73
72 #if defined(SECCOMP_SANDBOX) 74 #if defined(SECCOMP_SANDBOX)
(...skipping 18 matching lines...) Expand all
91 "the policies haven't been loaded into the kernel?)"; 93 "the policies haven't been loaded into the kernel?)";
92 } 94 }
93 } 95 }
94 #endif // CHROMIUM_SELINUX 96 #endif // CHROMIUM_SELINUX
95 97
96 // This is the object which implements the zygote. The ZygoteMain function, 98 // This is the object which implements the zygote. The ZygoteMain function,
97 // which is called from ChromeMain, simply constructs one of these objects and 99 // which is called from ChromeMain, simply constructs one of these objects and
98 // runs it. 100 // runs it.
99 class Zygote { 101 class Zygote {
100 public: 102 public:
101 Zygote(int sandbox_flags, content::ZygoteForkDelegate* helper) 103 Zygote(int sandbox_flags, ZygoteForkDelegate* helper)
102 : sandbox_flags_(sandbox_flags), 104 : sandbox_flags_(sandbox_flags),
103 helper_(helper), 105 helper_(helper),
104 initial_uma_sample_(0), 106 initial_uma_sample_(0),
105 initial_uma_boundary_value_(0) { 107 initial_uma_boundary_value_(0) {
106 if (helper_) 108 if (helper_)
107 helper_->InitialUMA(&initial_uma_name_, 109 helper_->InitialUMA(&initial_uma_name_,
108 &initial_uma_sample_, 110 &initial_uma_sample_,
109 &initial_uma_boundary_value_); 111 &initial_uma_boundary_value_);
110 } 112 }
111 113
112 bool ProcessRequests() { 114 bool ProcessRequests() {
113 // A SOCK_SEQPACKET socket is installed in fd 3. We get commands from the 115 // A SOCK_SEQPACKET socket is installed in fd 3. We get commands from the
114 // browser on it. 116 // browser on it.
115 // A SOCK_DGRAM is installed in fd 5. This is the sandbox IPC channel. 117 // A SOCK_DGRAM is installed in fd 5. This is the sandbox IPC channel.
116 // See http://code.google.com/p/chromium/wiki/LinuxSandboxIPC 118 // See http://code.google.com/p/chromium/wiki/LinuxSandboxIPC
117 119
118 // We need to accept SIGCHLD, even though our handler is a no-op because 120 // We need to accept SIGCHLD, even though our handler is a no-op because
119 // otherwise we cannot wait on children. (According to POSIX 2001.) 121 // otherwise we cannot wait on children. (According to POSIX 2001.)
120 struct sigaction action; 122 struct sigaction action;
121 memset(&action, 0, sizeof(action)); 123 memset(&action, 0, sizeof(action));
122 action.sa_handler = SIGCHLDHandler; 124 action.sa_handler = SIGCHLDHandler;
123 CHECK(sigaction(SIGCHLD, &action, NULL) == 0); 125 CHECK(sigaction(SIGCHLD, &action, NULL) == 0);
124 126
125 if (g_suid_sandbox_active) { 127 if (g_suid_sandbox_active) {
126 // Let the ZygoteHost know we are ready to go. 128 // Let the ZygoteHost know we are ready to go.
127 // The receiving code is in content/browser/zygote_host_linux.cc. 129 // The receiving code is in content/browser/zygote_host_linux.cc.
128 std::vector<int> empty; 130 std::vector<int> empty;
129 bool r = UnixDomainSocket::SendMsg(kBrowserDescriptor, kZygoteMagic, 131 bool r = UnixDomainSocket::SendMsg(kBrowserDescriptor,
130 sizeof(kZygoteMagic), empty); 132 kZygoteHelloMessage,
133 sizeof(kZygoteHelloMessage), empty);
131 #if defined(OS_CHROMEOS) 134 #if defined(OS_CHROMEOS)
132 LOG_IF(WARNING, !r) << "Sending zygote magic failed"; 135 LOG_IF(WARNING, !r) << "Sending zygote magic failed";
133 // Exit normally on chromeos because session manager may send SIGTERM 136 // Exit normally on chromeos because session manager may send SIGTERM
134 // right after the process starts and it may fail to send zygote magic 137 // right after the process starts and it may fail to send zygote magic
135 // number to browser process. 138 // number to browser process.
136 if (!r) 139 if (!r)
137 _exit(content::RESULT_CODE_NORMAL_EXIT); 140 _exit(RESULT_CODE_NORMAL_EXIT);
138 #else 141 #else
139 CHECK(r) << "Sending zygote magic failed"; 142 CHECK(r) << "Sending zygote magic failed";
140 #endif 143 #endif
141 } 144 }
142 145
143 for (;;) { 146 for (;;) {
144 // This function call can return multiple times, once per fork(). 147 // This function call can return multiple times, once per fork().
145 if (HandleRequestFromBrowser(kBrowserDescriptor)) 148 if (HandleRequestFromBrowser(kBrowserDescriptor))
146 return true; 149 return true;
147 } 150 }
(...skipping 24 matching lines...) Expand all
172 PLOG(ERROR) << "Error reading message from browser"; 175 PLOG(ERROR) << "Error reading message from browser";
173 return false; 176 return false;
174 } 177 }
175 178
176 Pickle pickle(buf, len); 179 Pickle pickle(buf, len);
177 PickleIterator iter(pickle); 180 PickleIterator iter(pickle);
178 181
179 int kind; 182 int kind;
180 if (pickle.ReadInt(&iter, &kind)) { 183 if (pickle.ReadInt(&iter, &kind)) {
181 switch (kind) { 184 switch (kind) {
182 case ZygoteHostImpl::kCmdFork: 185 case kZygoteCommandFork:
183 // This function call can return multiple times, once per fork(). 186 // This function call can return multiple times, once per fork().
184 return HandleForkRequest(fd, pickle, iter, fds); 187 return HandleForkRequest(fd, pickle, iter, fds);
185 188
186 case ZygoteHostImpl::kCmdReap: 189 case kZygoteCommandReap:
187 if (!fds.empty()) 190 if (!fds.empty())
188 break; 191 break;
189 HandleReapRequest(fd, pickle, iter); 192 HandleReapRequest(fd, pickle, iter);
190 return false; 193 return false;
191 case ZygoteHostImpl::kCmdGetTerminationStatus: 194 case kZygoteCommandGetTerminationStatus:
192 if (!fds.empty()) 195 if (!fds.empty())
193 break; 196 break;
194 HandleGetTerminationStatus(fd, pickle, iter); 197 HandleGetTerminationStatus(fd, pickle, iter);
195 return false; 198 return false;
196 case ZygoteHostImpl::kCmdGetSandboxStatus: 199 case kZygoteCommandGetSandboxStatus:
197 HandleGetSandboxStatus(fd, pickle, iter); 200 HandleGetSandboxStatus(fd, pickle, iter);
198 return false; 201 return false;
199 default: 202 default:
200 NOTREACHED(); 203 NOTREACHED();
201 break; 204 break;
202 } 205 }
203 } 206 }
204 207
205 LOG(WARNING) << "Error parsing message from browser"; 208 LOG(WARNING) << "Error parsing message from browser";
206 for (std::vector<int>::const_iterator 209 for (std::vector<int>::const_iterator
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 base::TerminationStatus status; 247 base::TerminationStatus status;
245 int exit_code; 248 int exit_code;
246 if (g_suid_sandbox_active) 249 if (g_suid_sandbox_active)
247 child = real_pids_to_sandbox_pids[child]; 250 child = real_pids_to_sandbox_pids[child];
248 if (child) { 251 if (child) {
249 status = base::GetTerminationStatus(child, &exit_code); 252 status = base::GetTerminationStatus(child, &exit_code);
250 } else { 253 } else {
251 // Assume that if we can't find the child in the sandbox, then 254 // Assume that if we can't find the child in the sandbox, then
252 // it terminated normally. 255 // it terminated normally.
253 status = base::TERMINATION_STATUS_NORMAL_TERMINATION; 256 status = base::TERMINATION_STATUS_NORMAL_TERMINATION;
254 exit_code = content::RESULT_CODE_NORMAL_EXIT; 257 exit_code = RESULT_CODE_NORMAL_EXIT;
255 } 258 }
256 259
257 Pickle write_pickle; 260 Pickle write_pickle;
258 write_pickle.WriteInt(static_cast<int>(status)); 261 write_pickle.WriteInt(static_cast<int>(status));
259 write_pickle.WriteInt(exit_code); 262 write_pickle.WriteInt(exit_code);
260 ssize_t written = 263 ssize_t written =
261 HANDLE_EINTR(write(fd, write_pickle.data(), write_pickle.size())); 264 HANDLE_EINTR(write(fd, write_pickle.data(), write_pickle.size()));
262 if (written != static_cast<ssize_t>(write_pickle.size())) 265 if (written != static_cast<ssize_t>(write_pickle.size()))
263 PLOG(ERROR) << "write"; 266 PLOG(ERROR) << "write";
264 } 267 }
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
543 return false; 546 return false;
544 } 547 }
545 548
546 // In the SUID sandbox, we try to use a new PID namespace. Thus the PIDs 549 // In the SUID sandbox, we try to use a new PID namespace. Thus the PIDs
547 // fork() returns are not the real PIDs, so we need to map the Real PIDS 550 // fork() returns are not the real PIDs, so we need to map the Real PIDS
548 // into the sandbox PID namespace. 551 // into the sandbox PID namespace.
549 typedef base::hash_map<base::ProcessHandle, base::ProcessHandle> ProcessMap; 552 typedef base::hash_map<base::ProcessHandle, base::ProcessHandle> ProcessMap;
550 ProcessMap real_pids_to_sandbox_pids; 553 ProcessMap real_pids_to_sandbox_pids;
551 554
552 const int sandbox_flags_; 555 const int sandbox_flags_;
553 content::ZygoteForkDelegate* helper_; 556 ZygoteForkDelegate* helper_;
554 557
555 // These might be set by helper_->InitialUMA. They supply a UMA 558 // These might be set by helper_->InitialUMA. They supply a UMA
556 // enumeration sample we should report on the first fork. 559 // enumeration sample we should report on the first fork.
557 std::string initial_uma_name_; 560 std::string initial_uma_name_;
558 int initial_uma_sample_; 561 int initial_uma_sample_;
559 int initial_uma_boundary_value_; 562 int initial_uma_boundary_value_;
560 }; 563 };
561 564
562 // With SELinux we can carve out a precise sandbox, so we don't have to play 565 // With SELinux we can carve out a precise sandbox, so we don't have to play
563 // with intercepting libc calls. 566 // with intercepting libc calls.
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after
936 939
937 static bool EnterSandbox() { 940 static bool EnterSandbox() {
938 PreSandboxInit(); 941 PreSandboxInit();
939 SkiaFontConfigSetImplementation( 942 SkiaFontConfigSetImplementation(
940 new FontConfigIPC(kMagicSandboxIPCDescriptor)); 943 new FontConfigIPC(kMagicSandboxIPCDescriptor));
941 return true; 944 return true;
942 } 945 }
943 946
944 #endif // CHROMIUM_SELINUX 947 #endif // CHROMIUM_SELINUX
945 948
946 bool ZygoteMain(const content::MainFunctionParams& params, 949 bool ZygoteMain(const MainFunctionParams& params,
947 content::ZygoteForkDelegate* forkdelegate) { 950 ZygoteForkDelegate* forkdelegate) {
948 #if !defined(CHROMIUM_SELINUX) 951 #if !defined(CHROMIUM_SELINUX)
949 g_am_zygote_or_renderer = true; 952 g_am_zygote_or_renderer = true;
950 #endif 953 #endif
951 954
952 #if defined(SECCOMP_SANDBOX) 955 #if defined(SECCOMP_SANDBOX)
953 if (SeccompSandboxEnabled()) { 956 if (SeccompSandboxEnabled()) {
954 // The seccomp sandbox needs access to files in /proc, which might be denied 957 // The seccomp sandbox needs access to files in /proc, which might be denied
955 // after one of the other sandboxes have been started. So, obtain a suitable 958 // after one of the other sandboxes have been started. So, obtain a suitable
956 // file handle in advance. 959 // file handle in advance.
957 g_proc_fd = open("/proc", O_DIRECTORY | O_RDONLY); 960 g_proc_fd = open("/proc", O_DIRECTORY | O_RDONLY);
(...skipping 15 matching lines...) Expand all
973 976
974 // Turn on the SELinux or SUID sandbox 977 // Turn on the SELinux or SUID sandbox
975 if (!EnterSandbox()) { 978 if (!EnterSandbox()) {
976 LOG(FATAL) << "Failed to enter sandbox. Fail safe abort. (errno: " 979 LOG(FATAL) << "Failed to enter sandbox. Fail safe abort. (errno: "
977 << errno << ")"; 980 << errno << ")";
978 return false; 981 return false;
979 } 982 }
980 983
981 int sandbox_flags = 0; 984 int sandbox_flags = 0;
982 if (getenv("SBX_D")) 985 if (getenv("SBX_D"))
983 sandbox_flags |= ZygoteHostImpl::kSandboxSUID; 986 sandbox_flags |= kSandboxLinuxSUID;
984 if (getenv("SBX_PID_NS")) 987 if (getenv("SBX_PID_NS"))
985 sandbox_flags |= ZygoteHostImpl::kSandboxPIDNS; 988 sandbox_flags |= kSandboxLinuxPIDNS;
986 if (getenv("SBX_NET_NS")) 989 if (getenv("SBX_NET_NS"))
987 sandbox_flags |= ZygoteHostImpl::kSandboxNetNS; 990 sandbox_flags |= kSandboxLinuxNetNS;
988 991
989 #if defined(SECCOMP_SANDBOX) 992 #if defined(SECCOMP_SANDBOX)
990 // The seccomp sandbox will be turned on when the renderers start. But we can 993 // The seccomp sandbox will be turned on when the renderers start. But we can
991 // already check if sufficient support is available so that we only need to 994 // already check if sufficient support is available so that we only need to
992 // print one error message for the entire browser session. 995 // print one error message for the entire browser session.
993 if (g_proc_fd >= 0 && SeccompSandboxEnabled()) { 996 if (g_proc_fd >= 0 && SeccompSandboxEnabled()) {
994 if (!SupportsSeccompSandbox(g_proc_fd)) { 997 if (!SupportsSeccompSandbox(g_proc_fd)) {
995 // There are a good number of users who cannot use the seccomp sandbox 998 // There are a good number of users who cannot use the seccomp sandbox
996 // (e.g. because their distribution does not enable seccomp mode by 999 // (e.g. because their distribution does not enable seccomp mode by
997 // default). While we would prefer to deny execution in this case, it 1000 // default). While we would prefer to deny execution in this case, it
998 // seems more realistic to continue in degraded mode. 1001 // seems more realistic to continue in degraded mode.
999 LOG(ERROR) << "WARNING! This machine lacks support needed for the " 1002 LOG(ERROR) << "WARNING! This machine lacks support needed for the "
1000 "Seccomp sandbox. Running renderers with Seccomp " 1003 "Seccomp sandbox. Running renderers with Seccomp "
1001 "sandboxing disabled."; 1004 "sandboxing disabled.";
1002 } else { 1005 } else {
1003 VLOG(1) << "Enabling experimental Seccomp sandbox."; 1006 VLOG(1) << "Enabling experimental Seccomp sandbox.";
1004 sandbox_flags |= ZygoteHostImpl::kSandboxSeccomp; 1007 sandbox_flags |= kSandboxLinuxSeccomp;
1005 } 1008 }
1006 } 1009 }
1007 #endif // SECCOMP_SANDBOX 1010 #endif // SECCOMP_SANDBOX
1008 1011
1009 Zygote zygote(sandbox_flags, forkdelegate); 1012 Zygote zygote(sandbox_flags, forkdelegate);
1010 // This function call can return multiple times, once per fork(). 1013 // This function call can return multiple times, once per fork().
1011 return zygote.ProcessRequests(); 1014 return zygote.ProcessRequests();
1012 } 1015 }
1016
1017 } // namespace content
OLDNEW
« no previous file with comments | « content/public/common/sandbox_linux.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698