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

Side by Side Diff: src/untrusted/init/init.cc

Issue 25147002: nacl_init Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client
Patch Set: Created 7 years, 2 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 | « src/untrusted/init/auto_lock.h ('k') | src/untrusted/init/irt_dev_process.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2013 The Native Client Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <errno.h>
6 #include <pthread.h>
7 #include <string.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10
11 #include "native_client/src/include/nacl_scoped_ptr.h"
12 #include "native_client/src/public/imc_syscalls.h"
13 #include "native_client/src/shared/srpc/nacl_srpc.h.h"
14 #include "native_client/src/untrusted/irt/irt.h"
15
16 #include "native_client/src/untrusted/init/scoped_lock.h"
17 #include "native_client/src/untrusted/init/scoped_non_ptr.h"
18
19 namespace nacl {
20
21 class Pidmap {
22 std::bitset<PID_MAX_LIMIT> pids_;
23 };
24
25 typedef std::map<int, SrpcChannel> PidMap;
26
27 class PidNamespace {
28 private:
29 PidMap pids_;
30 };
31
32 }
33
34 static void print_error(const char *message) {
35 write(2, message, strlen(message));
36 }
37
38 /* Mutex to guard kernel channel initialization. */
39 static pthread_mutex_t kernel_service_mutex = PTHREAD_MUTEX_INITIALIZER;
40 static int kernel_channel_initialized = 0;
41 static struct NaClSrpcChannel kernel_channel;
42
43 static int get_kernel_channel_locked(struct NaClSrpcChannel **result) {
44 int status;
45 int kernel;
46 int kernel_conn;
47
48 if (kernel_channel_initialized) {
49 *result = &manifest_channel;
50 return 0;
51 }
52 *result = NULL;
53
54 status = irt_nameservice_lookup("KernelService", O_RDWR, &kernel);
55 if (NACL_NAME_SERVICE_SUCCESS != status) {
56 print_error("Kernel service lookup failed\n");
57 return EIO;
58 }
59
60 if (-1 == kernel) {
61 print_error("Kernel service descriptor is invalid\n");
62 return EIO;
63 }
64 kernel_conn = imc_connect(kernel);
65 close(kernel);
66 if (-1 == kernel_conn) {
67 print_error("Error connecting to Kernel service\n");
68 return EIO;
69 }
70 if (!NaClSrpcClientCtor(&kernel_channel, kernel_conn)) {
71 print_error("Error establishing Kernel SRPC channel\n");
72 return EIO;
73 }
74 *result = &kernel_channel;
75 kernel_channel_initialized = 1;
76 return 0;
77 }
78
79 int get_kernel_channel(struct NaClSrpcChannel **result) {
80 int error;
81 pthread_mutex_lock(&kernel_service_mutex);
82 error = get_kernel_channel_locked(result);
83 pthread_mutex_unlock(&kernel_service_mutex);
84 return error;
85 }
86
87 int create_process(struct NaClSrpcChannel *kernel_channel) {
88 int status;
89
90 if (NACL_SRPC_RESULT_OK !=
91 NaClSrpcInvokeBySignature(kern_chan, NACL_KERNEL_SERVICE_CREATE_PROCESS,
92 &status, &g_sock_addr, &g_app_addr)) {
93 fprintf(stderr, "create process failed, status %d\n", status);
94 return 0;
95 }
96 assert(0 == status);
97
98 if (!NaClLdrSetupCommandChannel(g_sock_addr, &g_command_channel)) {
99 fprintf(stderr, "failed to setup command channel\n");
100 return 0;
101 }
102
103 return 1;
104 }
105
106 static int nacl_irt_posix_spawn(pid_t *pid, const char *path,
107 const posix_spawn_file_actions_t *file_actions,
108 const posix_spawnattr_t *attrp,
109 char *const argv[], char *const envp[]) {
110 int status;
111 struct NaClSrpcChannel *kernel_channel;
112 int sock_addr;
113 int app_addr;
114 int nexe_fd;
115 struct NaClSrpcChannel command_channel;
116 int app_conn;
117 struct NaClSrpcChannel app_channel;
118
119 status = get_kernel_channel(&kernel_channel);
120 if (0 != status) {
121 return status;
122 }
123
124 pthread_mutex_lock(&kernel_service_mutex);
125 if (NACL_SRPC_RESULT_OK == NaClSrpcInvokeBySignature(
126 kernel_channel, NACL_KERNEL_SERVICE_CREATE_PROCESS,
127 &status, &sock_addr, &app_addr)) {
128 status = 0;
129 }
130 pthread_mutex_unlock(&kernel_service_mutex);
131
132 if (!NaClLdrSetupCommandChannel(sock_addr, &command_channel)) {
133 print_error(stderr, "Failed to setup command channel\n");
134 return 0;
135 }
136
137 status = nacl_irt_resource_open.open_resource(path, &nexe_fd);
138 if (0 != status) {
139 print_error(stderr, "Failed to open module nexe\n");
140 goto cleanup_channel;
141 }
142
143 if (!NaClLdrLoadModule(&command_channel, nexe_fd)) {
144 print_error(stderr, "Failed to load module\n");
145 goto cleanup_channel;
146 }
147
148 if (!NaClLdrStartModule(&command_channel)) {
149 print_error(stderr, "Failed to start module\n");
150 goto cleanup_channel;
151 }
152
153 app_conn = imc_connect(app_addr);
154 close(app_addr);
155 if (-1 == app_conn) {
156 print_error("Error connecting to application\n");
157 return EIO;
158 }
159 if (!NaClSrpcClientCtor(&app_channel, app_conn)) {
160 fprintf(stderr, "Application SRPC channel ctor failed\n");
161 return 1;
162 }
163
164 cleanup_channel:
165 NaClSrpcDtor(&command_channel);
166 return status;
167 }
168
169 // Each connection can be stateful and that state is tracked by this
170 // object.
171 class SrpcHandlerState {
172 public:
173 explicit SrpcHandlerState(int desc)
174 : desc_(desc) {}
175 void Run();
176 private:
177 static void SignalHandler(struct NaClSrpcRpc *rpc,
178 struct NaClSrpcArg *args[],
179 struct NaClSrpcArg *rets[],
180 struct NaClSrpcClosure *done);
181 static void WaitHandler(struct NaClSrpcRpc *rpc,
182 struct NaClSrpcArg *args[],
183 struct NaClSrpcArg *rets[],
184 struct NaClSrpcClosure *done);
185
186 int desc_;
187
188 static struct NaClSrpcHandlerDesc const table[];
189 };
190
191 static void CreateProcess() {
192 nacl::scoped_ptr<NaClProcessLib::NameServiceClient> name_service(
193 g_name_service_factory->NameService());
194 ScopedNonPtr<int, close_desc> ks_cap(name_service->Resolve("KernelService"));
195 if (-1 == ks_cap) {
196 fprintf(stderr, "No Kernel Service!?!\n");
197 return 1;
198 }
199 nacl::KernelServiceClient kernel_service;
200 kernel_service.InitializeFromConnectionCapability(ks_cap);
201
202 int sr_cap;
203 int app_cap;
204
205 if (!kernel_service.CreateProcess(&sr_cap, &app_cap)) {
206 return 1;
207 }
208
209 nacl::scoped_ptr<nacl::ServiceRuntimeClient> service_runtime(
210 kernel_service.ServiceRuntimeClientFactory(sr_cap_));
211
212 ScopedNonPtr<int, close_desc> manifest_desc(
213 name_service->Resolve("ManifestNameService"));
214 if (-1 == manifest_desc) {
215 fprintf(stderr, "init: no manifest name service\n");
216 return 1;
217 }
218
219 NaClProcessLib::NameServiceClient manifest_service;
220 if (!manifest_service.InitializeFromConnectionCapability(manifest_desc)) {
221 fprintf(stderr, "Could not connect to manifest name service\n");
222 return 1;
223 }
224
225 ScopedNonPtr<int, close_desc> nexe_desc(manifest_service.Resolve(path));
226 if (-1 == nexe_desc) {
227 fprintf(stderr, "init: cannot resolve path '%s' in manifest name service\n",
228 path);
229 return 1;
230 }
231
232 NaClErrorCode status;
233 if (LOAD_OK != (status = service_runtime->RunNaClModule(nexe_desc))) {
234 fprintf(stderr, "init: error while loading program (%d)\n", status);
235 return 1;
236 }
237
238 nacl::SrpcClientConnection app_conn;
239 if (!app_conn.InitializeFromConnectionCapability(app_cap)) {
240 fprintf(stderr, "Could not connect to subprogram\n");
241 return 1;
242 }
243
244 close(sr_cap);
245 close(app_cap);
246 }
247
248 void SrpcHandlerState::PosixSpawnHandler(
249 struct NaClSrpcRpc *rpc,
250 struct NaClSrpcArg *in_args[],
251 struct NaClSrpcArg *out_args[],
252 struct NaClSrpcClosure *done_cls) {
253 NaClSrpcClosureRunner on_scope_exit(done_cls);
254 rpc->result = NACL_SRPC_RESULT_OK;
255
256 SerializationBuffer deserializer(
257 reinterpret_cast<uint8_t *>(in_args[0]->arrays.carr),
258 static_cast<size_t>(in_args[0]->u.count));
259
260 std::vector<nacl::string> argv;
261 if (!deserializer.Deserialize(&argv)) {
262 goto cleanup_args;
263 }
264
265 std::vector<nacl::string> envp;
266 if (!deserializer.Deserialize(&envp)) {
267 goto cleanup_args;
268 }
269
270 int pid;
271 // HandleSpawn(path, argv, envp, &pid);
272
273 return;
274
275 cleanup_args:
276 // Use 0 instead of -1 for invalid pid; we avoid having a buggy
277 // program do kill(-1, SIGKILL). By using 0, a buggy program will
278 // just kill every process in its own process group, which will
279 // (hopefully) make the bug quite apparent, without taking all of
280 // the user's processes down.
281 out_args[0]->u.ival = 0;
282 }
283
284 void SrpcHandlerState::SignalHandler(
285 struct NaClSrpcRpc *rpc,
286 struct NaClSrpcArg *args[],
287 struct NaClSrpcArg *rets[],
288 struct NaClSrpcClosure *done) {
289 NaClSrpcClosureRunner on_scope_exit(done);
290 rpc->result = NACL_SRPC_RESULT_OK;
291
292 pid_t pid = args[0]->u.ival;
293 int signal = args[1]->u.ival;
294
295 Pidmap::iterator it = pids_.find(pid);
296 if (it != pids_.end()) {
297 NaClAppClient client = it->second;
298
299 client->signal(signal);
300 }
301
302 fflush(stdout);
303 }
304
305 void SrpcHandlerState::WaitHandler(
306 struct NaClSrpcRpc *rpc,
307 struct NaClSrpcArg *args[],
308 struct NaClSrpcArg *rets[],
309 struct NaClSrpcClosure *done) {
310 NaClSrpcClosureRunner on_scope_exit(done);
311 rpc->result = NACL_SRPC_RESULT_OK;
312 }
313
314 const struct nacl_irt_dev_process nacl_irt_dev_process = {
315 nacl_irt_getpid,
316 nacl_irt_getppid,
317 nacl_irt_setpgid,
318 nacl_irt_getpgid,
319 nacl_irt_getsid,
320 nacl_irt_setsid,
321 nacl_irt_kill,
322 nacl_irt_posix_spawn,
323 nacl_irt_signal,
324 nacl_irt_sigprocmask,
325 nacl_irt_wait,
326 nacl_irt_waitpid,
327 };
328
329 struct NaClSrpcHandlerDesc const SrpcHandlerState::table[] = {
330 { "posix_spawn:sC:i", SpawnHandler, },
331 { "kill:ii:", SignalHandler, },
332 { "wait:iiii:", WaitHandler, },
333 { static_cast<char const *>(NULL), static_cast<NaClSrpcMethod>(NULL), },
334 };
335
336 void SrpcHandlerState::Run() {
337 if (!NaClSrpcServerLoop(desc_, table, NULL)) {
338 fprintf(stderr, "NaClSrpcServerLoop failed\n");
339 abort();
340 }
341 if (-1 == close(desc_)) {
342 perror("close RPC connection");
343 abort();
344 }
345 }
346
347 static void *RpcHandler(void *arg) {
348 int desc = reinterpret_cast<int>(arg);
349 SrpcHandlerState handler(desc);
350
351 handler.Run();
352 return NULL;
353 }
354
355 int main(int argc, char **argv) {
356 int d;
357
358 NaClSrpcModuleInit();
359 while ((d = imc_accept(3)) != -1) {
360 pthread_t thread;
361 if (0 != pthread_create(&thread, static_cast<pthread_attr_t *>(NULL),
362 RpcHandler, reinterpret_cast<void *>(d))) {
363 perror("pthread_create for RpcHandler");
364 abort();
365 }
366 }
367 NaClSrpcModuleFini();
368
369 return 0;
370 }
OLDNEW
« no previous file with comments | « src/untrusted/init/auto_lock.h ('k') | src/untrusted/init/irt_dev_process.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698