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