OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 // A mini-zygote specifically for Native Client. | 5 // A mini-zygote specifically for Native Client. |
6 | 6 |
7 #include "chrome/common/nacl_helper_linux.h" | 7 #include "chrome/common/nacl_helper_linux.h" |
8 | 8 |
9 #include <errno.h> | 9 #include <errno.h> |
10 #include <link.h> | |
10 #include <stdlib.h> | 11 #include <stdlib.h> |
11 #include <sys/socket.h> | 12 #include <sys/socket.h> |
12 #include <sys/types.h> | 13 #include <sys/types.h> |
13 | 14 |
14 #include <string> | 15 #include <string> |
15 #include <vector> | 16 #include <vector> |
16 | 17 |
17 #include "base/at_exit.h" | 18 #include "base/at_exit.h" |
18 #include "base/command_line.h" | 19 #include "base/command_line.h" |
19 #include "base/eintr_wrapper.h" | 20 #include "base/eintr_wrapper.h" |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
111 if (HANDLE_EINTR(send(kNaClZygoteDescriptor, | 112 if (HANDLE_EINTR(send(kNaClZygoteDescriptor, |
112 &childpid, sizeof(childpid), MSG_EOR)) | 113 &childpid, sizeof(childpid), MSG_EOR)) |
113 != sizeof(childpid)) { | 114 != sizeof(childpid)) { |
114 LOG(ERROR) << "*** send() to zygote failed"; | 115 LOG(ERROR) << "*** send() to zygote failed"; |
115 } | 116 } |
116 } | 117 } |
117 | 118 |
118 } // namespace | 119 } // namespace |
119 | 120 |
120 static const char kNaClHelperAtZero[] = "at-zero"; | 121 static const char kNaClHelperAtZero[] = "at-zero"; |
122 static const char kNaClHelperRDebug[] = "r_debug"; | |
123 | |
124 /* | |
125 * Since we were started by the bootstrap program rather than in the | |
126 * usual way, the debugger cannot figure out where our executable | |
127 * or the dynamic linker or the shared libraries are in memory, | |
128 * so it won't find any symbols. But we can fake it out to find us. | |
129 * | |
130 * The zygote passes --r_debug=0xXXXXXXXXXXXXXXXX. The bootstrap | |
131 * program replaces the Xs with the address of its _r_debug | |
132 * structure. The debugger will look for that symbol by name to | |
133 * discover the addresses of key dynamic linker data structures. | |
134 * Since all it knows about is the original main executable, which | |
135 * is the bootstrap program, it finds the symbol defined there. The | |
136 * dynamic linker's structure is somewhere else, but it is filled in | |
137 * after initialization. The parts that really matter to the | |
138 * debugger never change. So we just copy the contents of the | |
139 * dynamic linker's structure into the address provided by the option. | |
140 * Hereafter, if someone attaches a debugger (or examines a core dump), | |
141 * the debugger will find all the symbols in the normal way. | |
142 */ | |
143 static void check_r_debug(char *argv0) { | |
144 std::string r_debug_switch_value = | |
145 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(kNaClHelperRDebug); | |
146 if (!r_debug_switch_value.empty()) { | |
147 char *endp = NULL; | |
148 uintptr_t r_debug_addr = strtoul(r_debug_switch_value.c_str(), &endp, 0); | |
149 if (r_debug_addr != 0 && *endp == '\0') { | |
150 struct r_debug *bootstrap_r_debug = (struct r_debug *) r_debug_addr; | |
151 *bootstrap_r_debug = _r_debug; | |
eaeltsin
2011/11/12 01:35:23
Neat.
A very useful complement would be to introd
eaeltsin
2011/11/12 01:52:19
Related note: if we want to support subsequent inv
Mark Seaborn
2011/11/14 20:15:41
Is the symbol _r_debug part of the public ABI such
| |
152 | |
153 /* | |
154 * Since the main executable (the bootstrap program) does not | |
155 * have a dynamic section, the debugger will not skip the | |
156 * first element of the link_map list as it usually would for | |
157 * an executable or PIE that was loaded normally. But the | |
158 * dynamic linker has set l_name for the PIE to "" as is | |
159 * normal for the main executable. So the debugger doesn't | |
160 * know which file it is. Fill in the actual file name, which | |
161 * came in as our argv[0]. | |
162 */ | |
163 struct link_map *l = _r_debug.r_map; | |
164 if (l->l_name[0] == '\0') | |
165 l->l_name = argv0; | |
Mark Seaborn
2011/11/14 20:15:41
I find modifying the dynamic linker's data structu
| |
166 } | |
167 } | |
168 } | |
121 | 169 |
122 int main(int argc, char *argv[]) { | 170 int main(int argc, char *argv[]) { |
123 CommandLine::Init(argc, argv); | 171 CommandLine::Init(argc, argv); |
124 base::AtExitManager exit_manager; | 172 base::AtExitManager exit_manager; |
125 base::RandUint64(); // acquire /dev/urandom fd before sandbox is raised | 173 base::RandUint64(); // acquire /dev/urandom fd before sandbox is raised |
126 std::vector<int> empty; // for SendMsg() calls | 174 std::vector<int> empty; // for SendMsg() calls |
127 | 175 |
176 check_r_debug(argv[0]); | |
177 | |
128 g_suid_sandbox_active = (NULL != getenv("SBX_D")); | 178 g_suid_sandbox_active = (NULL != getenv("SBX_D")); |
129 | 179 |
130 if (CommandLine::ForCurrentProcess()->HasSwitch(kNaClHelperAtZero)) { | 180 if (CommandLine::ForCurrentProcess()->HasSwitch(kNaClHelperAtZero)) { |
131 g_nacl_prereserved_sandbox_addr = (void *) (uintptr_t) 0x10000; | 181 g_nacl_prereserved_sandbox_addr = (void *) (uintptr_t) 0x10000; |
132 } | 182 } |
133 | 183 |
134 // Send the zygote a message to let it know we are ready to help | 184 // Send the zygote a message to let it know we are ready to help |
135 if (!UnixDomainSocket::SendMsg(kNaClZygoteDescriptor, | 185 if (!UnixDomainSocket::SendMsg(kNaClZygoteDescriptor, |
136 kNaClHelperStartupAck, | 186 kNaClHelperStartupAck, |
137 sizeof(kNaClHelperStartupAck), empty)) { | 187 sizeof(kNaClHelperStartupAck), empty)) { |
(...skipping 27 matching lines...) Expand all Loading... | |
165 } | 215 } |
166 } | 216 } |
167 // if fork fails, send PID=-1 to zygote | 217 // if fork fails, send PID=-1 to zygote |
168 if (!UnixDomainSocket::SendMsg(kNaClZygoteDescriptor, &badpid, | 218 if (!UnixDomainSocket::SendMsg(kNaClZygoteDescriptor, &badpid, |
169 sizeof(badpid), empty)) { | 219 sizeof(badpid), empty)) { |
170 LOG(ERROR) << "*** send() to zygote failed"; | 220 LOG(ERROR) << "*** send() to zygote failed"; |
171 } | 221 } |
172 } | 222 } |
173 CHECK(false); // This routine must not return | 223 CHECK(false); // This routine must not return |
174 } | 224 } |
OLD | NEW |