1 // Copyright 2016 The Fuchsia 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 <launchpad/launchpad.h>
6 #include <launchpad/vmo.h>
7 #include "elf.h"
8
9 #include <zircon/assert.h>
10 #include <zircon/dlfcn.h>
11 #include <zircon/process.h>
12 #include <zircon/processargs.h>
13 #include <zircon/stack.h>
14 #include <zircon/syscalls.h>
15 #include <ldmsg/ldmsg.h>
16 #include <lib/fdio/io.h>
17 #include <assert.h>
18 #include <stdatomic.h>
19 #include <stdbool.h>
20 #include <stddef.h>
21 #include <stdint.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/param.h>
25 #include <threads.h>
26
27 enum special_handles {
28 HND_LDSVC_LOADER,
29 HND_EXEC_VMO,
30 HND_SEGMENTS_VMAR,
31 HND_SPECIAL_COUNT
32 };
33
34 struct launchpad {
35 uint32_t argc;
36 uint32_t envc;
37 uint32_t namec;
38 char* args;
39 size_t args_len;
40 char* env;
41 size_t env_len;
42 char* names;
43 size_t names_len;
44
45 size_t num_script_args;
46 char* script_args;
47 size_t script_args_len;
48
49 zx_handle_t* handles;
50 uint32_t* handles_info;
51 size_t handle_count;
52 size_t handle_alloc;
53
54 const char* errmsg;
55 zx_status_t error;
56
57 zx_vaddr_t entry;
58 zx_vaddr_t base;
59 zx_vaddr_t vdso_base;
60
61 size_t stack_size;
62 bool set_stack_size;
63
64 zx_handle_t special_handles[HND_SPECIAL_COUNT];
65 bool loader_message;
66
67 zx_handle_t reserve_vmar;
68 bool fresh_process;
69 };
70
71 // Returned when calloc() fails on create, so callers
72 // can still call all the various add handles functions
73 // which will discard the handles, etc, etc.
74 static launchpad_t invalid_launchpad = {
75 .errmsg = "create: could not allocate launchpad_t",
76 .error = ZX_ERR_NO_MEMORY,
77 };
78
lp_error(launchpad_t * lp,zx_status_t error,const char * msg)79 static zx_status_t lp_error(launchpad_t* lp, zx_status_t error, const char* msg) {
80 if (lp->error == ZX_OK) {
81 lp->error = error;
82 lp->errmsg = msg;
83 }
84 return lp->error;
85 }
86
launchpad_get_status(launchpad_t * lp)87 zx_status_t launchpad_get_status(launchpad_t* lp) {
88 return lp->error;
89 }
90
launchpad_abort(launchpad_t * lp,zx_status_t error,const char * msg)91 void launchpad_abort(launchpad_t* lp, zx_status_t error, const char* msg) {
92 lp_error(lp, (error < 0) ? error : ZX_ERR_INTERNAL, msg);
93 }
94
launchpad_error_message(launchpad_t * lp)95 const char* launchpad_error_message(launchpad_t* lp) {
96 return lp->errmsg;
97 }
98
99 #define HND_LOADER_COUNT 3
100 // We always install the process handle as the first in the message.
101 #define lp_proc(lp) ((lp)->handles[0])
102 // We always install the vmar handle as the second in the message.
103 #define lp_vmar(lp) ((lp)->handles[1])
104
launchpad_destroy(launchpad_t * lp)105 void launchpad_destroy(launchpad_t* lp) {
106 if (lp == &invalid_launchpad)
107 return;
108 zx_handle_close(lp->reserve_vmar);
109 zx_handle_close_many(lp->special_handles, HND_SPECIAL_COUNT);
110 zx_handle_close_many(lp->handles, lp->handle_count);
111 free(lp->handles);
112 free(lp->handles_info);
113 free(lp->script_args);
114 free(lp->args);
115 free(lp->env);
116 free(lp);
117 }
118
launchpad_create_with_process(zx_handle_t proc,zx_handle_t vmar,launchpad_t ** result)119 zx_status_t launchpad_create_with_process(zx_handle_t proc,
120 zx_handle_t vmar,
121 launchpad_t** result) {
122 launchpad_t* lp = calloc(1, sizeof(*lp));
123 if (lp == NULL) {
124 lp = &invalid_launchpad;
125 } else {
126 lp->errmsg = "no error";
127 }
128
129 if (launchpad_add_handle(lp, proc, PA_PROC_SELF) == ZX_OK) {
130 // If the process has an existing vDSO mapping, record it for
131 // use by launchpad_start_extra.
132 zx_status_t status = zx_object_get_property(
133 proc, ZX_PROP_PROCESS_VDSO_BASE_ADDRESS,
134 &lp->vdso_base, sizeof(lp->vdso_base));
135 if (status != ZX_OK)
136 lp_error(lp, status,
137 "create: cannot get ZX_PROP_PROCESS_VDSO_BASE_ADDRESS");
138 }
139 launchpad_add_handle(lp, vmar, PA_VMAR_ROOT);
140
141 *result = lp;
142 return lp->error;
143 }
144
145 // Create a new process and a launchpad that will set it up.
launchpad_create_with_jobs(zx_handle_t creation_job,zx_handle_t transferred_job,const char * name,launchpad_t ** result)146 zx_status_t launchpad_create_with_jobs(zx_handle_t creation_job, zx_handle_t transferred_job,
147 const char* name, launchpad_t** result) {
148 uint32_t name_len = strlen(name);
149
150 zx_handle_t proc = ZX_HANDLE_INVALID;
151 zx_handle_t vmar = ZX_HANDLE_INVALID;
152 zx_status_t status = zx_process_create(creation_job, name, name_len, 0, &proc, &vmar);
153
154 launchpad_t* lp;
155 if (launchpad_create_with_process(proc, vmar, &lp) == ZX_OK)
156 lp->fresh_process = true;
157
158 if (status < 0)
159 lp_error(lp, status, "create: zx_process_create() failed");
160
161 if (transferred_job != ZX_HANDLE_INVALID) {
162 launchpad_add_handle(lp, transferred_job, PA_JOB_DEFAULT);
163 }
164
165 *result = lp;
166 return lp->error;
167 }
168
launchpad_create(zx_handle_t job,const char * name,launchpad_t ** result)169 zx_status_t launchpad_create(zx_handle_t job,
170 const char* name, launchpad_t** result) {
171 if (job == ZX_HANDLE_INVALID)
172 job = zx_job_default();
173 zx_handle_t xjob = ZX_HANDLE_INVALID;
174 zx_handle_duplicate(job, ZX_RIGHT_SAME_RIGHTS, &xjob);
175 return launchpad_create_with_jobs(job, xjob, name, result);
176 }
177
launchpad_get_process_handle(launchpad_t * lp)178 zx_handle_t launchpad_get_process_handle(launchpad_t* lp) {
179 return lp_proc(lp);
180 }
181
launchpad_get_root_vmar_handle(launchpad_t * lp)182 zx_handle_t launchpad_get_root_vmar_handle(launchpad_t* lp) {
183 return lp_vmar(lp);
184 }
185
build_stringtable(launchpad_t * lp,int count,const char * const * item,size_t * total_out,char ** out)186 static zx_status_t build_stringtable(launchpad_t* lp,
187 int count, const char* const* item,
188 size_t* total_out, char** out) {
189 if (lp->error)
190 return lp->error;
191 if (count < 0)
192 return lp_error(lp, ZX_ERR_INVALID_ARGS, "negative string array count");
193
194 size_t total = 0;
195 for (int i = 0; i < count; ++i)
196 total += strlen(item[i]) + 1;
197
198 char* buffer = NULL;
199 if (total > 0) {
200 buffer = malloc(total);
201 if (buffer == NULL)
202 return lp_error(lp, ZX_ERR_NO_MEMORY, "out of memory for string array");
203
204 char* p = buffer;
205 for (int i = 0; i < count; ++i)
206 p = stpcpy(p, item[i]) + 1;
207
208 if ((size_t) (p - buffer) != total) {
209 // The strings changed in parallel. Not kosher!
210 free(buffer);
211 return lp_error(lp, ZX_ERR_INVALID_ARGS, "string array modified during use");
212 }
213 }
214
215 *total_out = total;
216 *out = buffer;
217 return ZX_OK;
218 }
219
launchpad_set_args(launchpad_t * lp,int argc,const char * const * argv)220 zx_status_t launchpad_set_args(launchpad_t* lp,
221 int argc, const char* const* argv) {
222 size_t total;
223 char* buffer;
224 zx_status_t r = build_stringtable(lp, argc, argv, &total, &buffer);
225 if (r < 0)
226 return r;
227
228 free(lp->args);
229 lp->argc = argc;
230 lp->args = buffer;
231 lp->args_len = total;
232 return ZX_OK;
233 }
234
launchpad_set_nametable(launchpad_t * lp,size_t count,const char * const * names)235 zx_status_t launchpad_set_nametable(launchpad_t* lp,
236 size_t count, const char* const* names) {
237 size_t total;
238 char* buffer;
239 zx_status_t r = build_stringtable(lp, count, names, &total, &buffer);
240 if (r < 0)
241 return r;
242
243 free(lp->names);
244 lp->namec = count;
245 lp->names = buffer;
246 lp->names_len = total;
247 return ZX_OK;
248 }
249
launchpad_set_environ(launchpad_t * lp,const char * const * envp)250 zx_status_t launchpad_set_environ(launchpad_t* lp, const char* const* envp) {
251 uint32_t count = 0;
252 if (envp != NULL) {
253 for (const char* const* ep = envp; *ep != NULL; ++ep) {
254 ++count;
255 }
256 }
257
258 size_t total;
259 char* buffer;
260 zx_status_t r = build_stringtable(lp, count, envp, &total, &buffer);
261 if (r < 0)
262 return r;
263
264 free(lp->env);
265 lp->envc = count;
266 lp->env = buffer;
267 lp->env_len = total;
268 return ZX_OK;
269 }
270
more_handles(launchpad_t * lp,size_t n)271 static zx_status_t more_handles(launchpad_t* lp, size_t n) {
272 if (lp->error)
273 return lp->error;
274
275 if (ZX_CHANNEL_MAX_MSG_HANDLES - lp->handle_count < n)
276 return lp_error(lp, ZX_ERR_NO_MEMORY, "too many handles for handle table");
277
278 if (lp->handle_alloc - lp->handle_count < n) {
279 size_t alloc = lp->handle_alloc == 0 ? 8 : lp->handle_alloc * 2;
280 while (alloc - lp->handle_count < n)
281 alloc <<= 1;
282 zx_handle_t* handles = realloc(lp->handles,
283 alloc * sizeof(handles[0]));
284 if (handles == NULL)
285 return lp_error(lp, ZX_ERR_NO_MEMORY, "out of memory for handle table");
286 lp->handles = handles;
287 uint32_t* info = realloc(lp->handles_info, alloc * sizeof(info[0]));
288 if (info == NULL)
289 return lp_error(lp, ZX_ERR_NO_MEMORY, "out of memory for handle table");
290 lp->handles_info = info;
291 lp->handle_alloc = alloc;
292 }
293 return ZX_OK;
294 }
295
launchpad_add_handle(launchpad_t * lp,zx_handle_t h,uint32_t id)296 zx_status_t launchpad_add_handle(launchpad_t* lp, zx_handle_t h, uint32_t id) {
297 if (h == ZX_HANDLE_INVALID)
298 return lp_error(lp, ZX_ERR_BAD_HANDLE, "added invalid handle");
299 zx_status_t status = more_handles(lp, 1);
300 if (status == ZX_OK) {
301 lp->handles[lp->handle_count] = h;
302 lp->handles_info[lp->handle_count] = id;
303 ++lp->handle_count;
304 } else {
305 zx_handle_close(h);
306 }
307 return status;
308 }
309
launchpad_add_handles(launchpad_t * lp,size_t n,const zx_handle_t h[],const uint32_t id[])310 zx_status_t launchpad_add_handles(launchpad_t* lp, size_t n,
311 const zx_handle_t h[],
312 const uint32_t id[]) {
313 zx_status_t status = more_handles(lp, n);
314 if (status == ZX_OK) {
315 memcpy(&lp->handles[lp->handle_count], h, n * sizeof(h[0]));
316 memcpy(&lp->handles_info[lp->handle_count], id, n * sizeof(id[0]));
317 lp->handle_count += n;
318 for (size_t i = 0; i < n; i++) {
319 if (h[i] == ZX_HANDLE_INVALID) {
320 return lp_error(lp, ZX_ERR_BAD_HANDLE, "added invalid handle");
321 }
322 }
323 } else {
324 for (size_t i = 0; i < n; i++) {
325 zx_handle_close(h[i]);
326 }
327 }
328 return status;
329 }
330
331 //TODO: use transfer_fd here and eliminate fdio_pipe_half()
launchpad_add_pipe(launchpad_t * lp,int * fd_out,int target_fd)332 zx_status_t launchpad_add_pipe(launchpad_t* lp, int* fd_out, int target_fd) {
333 zx_handle_t handle;
334 uint32_t id;
335 int fd;
336
337 if (lp->error)
338 return lp->error;
339 if ((target_fd < 0) || (target_fd >= FDIO_MAX_FD)) {
340 return lp_error(lp, ZX_ERR_INVALID_ARGS, "add_pipe: invalid target fd");
341 }
342 zx_status_t status;
343 if ((status = fdio_pipe_half(&handle, &id)) < 0) {
344 return lp_error(lp, status, "add_pipe: failed to create pipe");
345 }
346 fd = status;
347 if ((status = launchpad_add_handle(lp, handle, PA_HND(PA_HND_TYPE(id), target_fd))) < 0) {
348 close(fd);
349 zx_handle_close(handle);
350 return status;
351 }
352 *fd_out = fd;
353 return ZX_OK;
354 }
355
check_elf_stack_size(launchpad_t * lp,elf_load_info_t * elf)356 static void check_elf_stack_size(launchpad_t* lp, elf_load_info_t* elf) {
357 size_t elf_stack_size = elf_load_get_stack_size(elf);
358 if (elf_stack_size > 0)
359 launchpad_set_stack_size(lp, elf_stack_size);
360 }
361
launchpad_elf_load_basic(launchpad_t * lp,zx_handle_t vmo)362 zx_status_t launchpad_elf_load_basic(launchpad_t* lp, zx_handle_t vmo) {
363 if (vmo == ZX_HANDLE_INVALID)
364 return lp_error(lp, ZX_ERR_INVALID_ARGS, "elf_load: invalid vmo");
365 if (lp->error)
366 goto done;
367
368 elf_load_info_t* elf;
369 zx_status_t status;
370 if ((status = elf_load_start(vmo, NULL, 0, &elf)))
371 lp_error(lp, status, "elf_load: elf_load_start() failed");
372 zx_handle_t segments_vmar;
373 if ((status = elf_load_finish(lp_vmar(lp), elf, vmo,
374 &segments_vmar, &lp->base, &lp->entry)))
375 lp_error(lp, status, "elf_load: elf_load_finish() failed");
376 check_elf_stack_size(lp, elf);
377 elf_load_destroy(elf);
378
379 if (status == ZX_OK) {
380 lp->loader_message = false;
381 launchpad_add_handle(lp, segments_vmar,
382 PA_HND(PA_VMAR_LOADED, 0));
383 }
384
385 done:
386 zx_handle_close(vmo);
387 return lp->error;
388 }
389
launchpad_elf_load_extra(launchpad_t * lp,zx_handle_t vmo,zx_vaddr_t * base,zx_vaddr_t * entry)390 zx_status_t launchpad_elf_load_extra(launchpad_t* lp, zx_handle_t vmo,
391 zx_vaddr_t* base, zx_vaddr_t* entry) {
392 if (lp->error)
393 return lp->error;
394 if (vmo == ZX_HANDLE_INVALID)
395 return lp_error(lp, ZX_ERR_INVALID_ARGS, "elf_load_extra: invalid vmo");
396
397 elf_load_info_t* elf;
398 zx_status_t status;
399 if ((status = elf_load_start(vmo, NULL, 0, &elf)))
400 lp_error(lp, status, "elf_load_extra: elf_load_start() failed");
401 if ((status = elf_load_finish(lp_vmar(lp), elf, vmo, NULL, base, entry)))
402 lp_error(lp, status, "elf_load_extra: elf_load_finish() failed");
403 elf_load_destroy(elf);
404
405 return lp->error;
406 }
407
408 #define LOADER_SVC_MSG_MAX 1024
409
loader_svc_rpc(zx_handle_t loader_svc,uint32_t ordinal,const void * data,size_t len,zx_handle_t * out)410 static zx_status_t loader_svc_rpc(zx_handle_t loader_svc, uint32_t ordinal,
411 const void* data, size_t len, zx_handle_t* out) {
412 static _Atomic zx_txid_t next_txid;
413
414 ldmsg_req_t req;
415 memset(&req.header, 0, sizeof(req.header));
416 req.header.ordinal = ordinal;
417
418 size_t req_len;
419 zx_status_t status = ldmsg_req_encode(&req, &req_len, data, len);
420 if (status != ZX_OK)
421 return status;
422
423 req.header.txid = atomic_fetch_add(&next_txid, 1);
424
425 ldmsg_rsp_t rsp;
426 memset(&rsp, 0, sizeof(rsp));
427
428 zx_handle_t handle = ZX_HANDLE_INVALID;
429 const zx_channel_call_args_t call = {
430 .wr_bytes = &req,
431 .wr_num_bytes = req_len,
432 .rd_bytes = &rsp,
433 .rd_num_bytes = sizeof(rsp),
434 .rd_handles = &handle,
435 .rd_num_handles = 1,
436 };
437 uint32_t reply_size;
438 uint32_t handle_count;
439 status = zx_channel_call(loader_svc, 0, ZX_TIME_INFINITE, &call, &reply_size, &handle_count);
440 if (status != ZX_OK)
441 return status;
442
443 // Check for protocol violations.
444 if (reply_size != ldmsg_rsp_get_size(&rsp)) {
445 protocol_violation:
446 zx_handle_close(handle);
447 return ZX_ERR_BAD_STATE;
448 }
449 if (rsp.header.ordinal != ordinal)
450 goto protocol_violation;
451
452 if (rsp.rv != ZX_OK) {
453 if (handle != ZX_HANDLE_INVALID)
454 goto protocol_violation;
455 if (rsp.rv > 0)
456 goto protocol_violation;
457 *out = ZX_HANDLE_INVALID;
458 } else {
459 *out = handle_count ? handle : ZX_HANDLE_INVALID;
460 }
461 return rsp.rv;
462 }
463
setup_loader_svc(launchpad_t * lp)464 static zx_status_t setup_loader_svc(launchpad_t* lp) {
465 if (lp->special_handles[HND_LDSVC_LOADER] != ZX_HANDLE_INVALID)
466 return ZX_OK;
467
468 zx_handle_t loader_svc;
469 zx_status_t status = dl_clone_loader_service(&loader_svc);
470 if (status < 0)
471 return status;
472
473 lp->special_handles[HND_LDSVC_LOADER] = loader_svc;
474 return ZX_OK;
475 }
476
477 // Reserve roughly the low half of the address space, so the new
478 // process can use sanitizers that need to allocate shadow memory there.
479 // The reservation VMAR is kept around just long enough to make sure all
480 // the initial allocations (mapping in the initial ELF objects, and
481 // allocating the initial stack) stay out of this area, and then destroyed.
482 // The process's own allocations can then use the full address space; if
483 // it's using a sanitizer, it will set up its shadow memory first thing.
reserve_low_address_space(launchpad_t * lp)484 static zx_status_t reserve_low_address_space(launchpad_t* lp) {
485 if (lp->reserve_vmar != ZX_HANDLE_INVALID)
486 return ZX_OK;
487
488 zx_info_vmar_t info;
489 zx_status_t status = zx_object_get_info(lp_vmar(lp), ZX_INFO_VMAR,
490 &info, sizeof(info), NULL, NULL);
491 if (status != ZX_OK) {
492 return lp_error(lp, status,
493 "zx_object_get_info failed on child root VMAR handle");
494 }
495
496 uintptr_t addr;
497 size_t reserve_size =
498 (((info.base + info.len) / 2) + PAGE_SIZE - 1) & -PAGE_SIZE;
499 status = zx_vmar_allocate(lp_vmar(lp), ZX_VM_SPECIFIC, 0,
500 reserve_size - info.base,
501 &lp->reserve_vmar, &addr);
502 if (status != ZX_OK) {
503 return lp_error(
504 lp, status,
505 "zx_vmar_allocate failed for low address space reservation");
506 }
507
508 if (addr != info.base) {
509 return lp_error(lp, ZX_ERR_BAD_STATE,
510 "zx_vmar_allocate gave wrong address?!?");
511 }
512
513 return ZX_OK;
514 }
515
516 // Consumes 'vmo' on success, not on failure.
handle_interp(launchpad_t * lp,zx_handle_t vmo,const char * interp,size_t interp_len)517 static zx_status_t handle_interp(launchpad_t* lp, zx_handle_t vmo,
518 const char* interp, size_t interp_len) {
519 zx_status_t status = setup_loader_svc(lp);
520 if (status != ZX_OK)
521 return status;
522
523 zx_handle_t interp_vmo;
524 status = loader_svc_rpc(
525 lp->special_handles[HND_LDSVC_LOADER], LDMSG_OP_LOAD_OBJECT,
526 interp, interp_len, &interp_vmo);
527 if (status != ZX_OK)
528 return status;
529
530 if (lp->fresh_process) {
531 // A fresh process using PT_INTERP might be loading a libc.so that
532 // supports sanitizers, so in that case (the most common case)
533 // keep the mappings launchpad makes out of the low address region.
534 status = reserve_low_address_space(lp);
535 if (status != ZX_OK)
536 return status;
537 }
538
539 elf_load_info_t* elf;
540 zx_handle_t segments_vmar;
541 status = elf_load_start(interp_vmo, NULL, 0, &elf);
542 if (status == ZX_OK) {
543 status = elf_load_finish(lp_vmar(lp), elf, interp_vmo,
544 &segments_vmar, &lp->base, &lp->entry);
545 elf_load_destroy(elf);
546 }
547 zx_handle_close(interp_vmo);
548
549 if (status == ZX_OK) {
550 if (lp->special_handles[HND_EXEC_VMO] != ZX_HANDLE_INVALID)
551 zx_handle_close(lp->special_handles[HND_EXEC_VMO]);
552 lp->special_handles[HND_EXEC_VMO] = vmo;
553 if (lp->special_handles[HND_SEGMENTS_VMAR] != ZX_HANDLE_INVALID)
554 zx_handle_close(lp->special_handles[HND_SEGMENTS_VMAR]);
555 lp->special_handles[HND_SEGMENTS_VMAR] = segments_vmar;
556 lp->loader_message = true;
557 }
558
559 return status;
560 }
561
launchpad_elf_load_body(launchpad_t * lp,const char * hdr_buf,size_t buf_sz,zx_handle_t vmo)562 static zx_status_t launchpad_elf_load_body(launchpad_t* lp, const char* hdr_buf,
563 size_t buf_sz, zx_handle_t vmo) {
564 elf_load_info_t* elf;
565 zx_status_t status;
566
567 if (lp->error)
568 goto done;
569 if ((status = elf_load_start(vmo, hdr_buf, buf_sz, &elf)) != ZX_OK) {
570 lp_error(lp, status, "elf_load: elf_load_start() failed");
571 } else {
572 char* interp;
573 size_t interp_len;
574 status = elf_load_get_interp(elf, vmo, &interp, &interp_len);
575 if (status != ZX_OK) {
576 lp_error(lp, status, "elf_load: get_interp() failed");
577 } else {
578 if (interp == NULL) {
579 zx_handle_t segments_vmar;
580 status = elf_load_finish(lp_vmar(lp), elf, vmo, &segments_vmar,
581 &lp->base, &lp->entry);
582 if (status != ZX_OK) {
583 lp_error(lp, status, "elf_load: elf_load_finish() failed");
584 } else {
585 // With no PT_INTERP, we obey PT_GNU_STACK.p_memsz for
586 // the stack size setting. With PT_INTERP, the dynamic
587 // linker is responsible for that.
588 check_elf_stack_size(lp, elf);
589 lp->loader_message = false;
590 launchpad_add_handle(
591 lp, segments_vmar,
592 PA_HND(PA_VMAR_LOADED, 0));
593 }
594 } else {
595 if ((status = handle_interp(lp, vmo, interp, interp_len))) {
596 lp_error(lp, status, "elf_load: handle_interp failed");
597 } else {
598 // handle_interp() takes ownership of vmo on success
599 vmo = ZX_HANDLE_INVALID;
600 }
601 free(interp);
602 }
603 }
604 elf_load_destroy(elf);
605 }
606 done:
607 if (vmo)
608 zx_handle_close(vmo);
609 return lp->error;
610 }
611
612 // Find the starting point of the interpreter and the interpreter
613 // arguments in a #! script header. Note that the input buffer (line)
614 // will be modified to add a NULL after the interpreter name.
parse_interp_spec(char * line,char ** interp_start,size_t * interp_len,char ** args_start)615 static zx_status_t parse_interp_spec(char *line, char **interp_start,
616 size_t *interp_len, char **args_start)
617 {
618 *args_start = NULL;
619
620 // Skip the '#!' prefix
621 char* next_char = line + 2;
622
623 // Skip whitespace
624 next_char += strspn(next_char, " \t");
625
626 // No interpreter specified
627 if (*next_char == '\0')
628 return ZX_ERR_NOT_FOUND;
629
630 *interp_start = next_char;
631
632 // Skip the interpreter name
633 next_char += strcspn(next_char, " \t");
634 *interp_len = next_char - *interp_start;
635
636 if (*next_char == '\0')
637 return ZX_OK;
638
639 *next_char++ = '\0';
640
641 // Look for the args
642 next_char += strspn(next_char, " \t");
643
644 if (*next_char == '\0')
645 return ZX_OK;
646
647 *args_start = next_char;
648 return ZX_OK;
649 }
650
launchpad_file_load(launchpad_t * lp,zx_handle_t vmo)651 zx_status_t launchpad_file_load(launchpad_t* lp, zx_handle_t vmo) {
652 if (vmo == ZX_HANDLE_INVALID)
653 return lp_error(lp, ZX_ERR_INVALID_ARGS, "file_load: invalid vmo");
654
655 if (lp->script_args != NULL) {
656 free(lp->script_args);
657 lp->script_args = NULL;
658 }
659 lp->script_args_len = 0;
660 lp->num_script_args = 0;
661
662 size_t script_nest_level = 0;
663
664 char first_line[LP_MAX_INTERP_LINE_LEN + 1];
665 size_t to_read = sizeof(first_line);
666 size_t vmo_size;
667 zx_status_t status = zx_vmo_get_size(vmo, &vmo_size);
668 if (status != ZX_OK) {
669 return lp_error(lp, status, "file_load: zx_vmo_get_size() failed");
670 }
671 if (to_read > vmo_size) {
672 to_read = vmo_size;
673 }
674
675 while (1) {
676 // Read enough to get the interpreter specification of a script
677 status = zx_vmo_read(vmo, first_line, 0, to_read);
678
679 // This is not a script -- load as an ELF file
680 if ((status == ZX_OK)
681 && (to_read < 2 || first_line[0] != '#' || first_line[1] != '!'))
682 break;
683
684 zx_handle_close(vmo);
685
686 if (status != ZX_OK)
687 return lp_error(lp, status, "file_load: zx_vmo_read() failed");
688
689 script_nest_level++;
690
691 // No point trying to read an interpreter we're not going to consider
692 if (script_nest_level > LP_MAX_SCRIPT_NEST_LEVEL)
693 return lp_error(lp, ZX_ERR_NOT_SUPPORTED,
694 "file_load: too many levels of script indirection");
695
696 // Normalize the line so that it is NULL-terminated
697 char* newline_pos = memchr(first_line, '\n', to_read);
698 if (newline_pos)
699 *newline_pos = '\0';
700 else if (to_read == sizeof(first_line))
701 return lp_error(lp, ZX_ERR_OUT_OF_RANGE,
702 "file_load: first line of script too long");
703 else
704 first_line[to_read] = '\0';
705
706 char* interp_start;
707 size_t interp_len;
708 char* args_start;
709 status = parse_interp_spec(first_line, &interp_start, &interp_len,
710 &args_start);
711 if (status != ZX_OK)
712 return lp_error(lp, status,
713 "file_load: failed to parse interpreter spec");
714
715 size_t args_len = (args_start == NULL) ? 0 : newline_pos - args_start;
716
717 // Add interpreter and args to start of lp->script_args
718 size_t new_args_len = interp_len + 1;
719 if (args_start != NULL)
720 new_args_len += args_len + 1;
721 char *new_buf = malloc(new_args_len + lp->script_args_len);
722 if (new_buf == NULL)
723 return lp_error(lp, ZX_ERR_NO_MEMORY, "file_load: out of memory");
724
725 memcpy(new_buf, interp_start, interp_len + 1);
726 lp->num_script_args++;
727
728 if (args_start != NULL) {
729 memcpy(&new_buf[interp_len + 1], args_start, args_len + 1);
730 lp->num_script_args++;
731 }
732
733 if (lp->script_args != NULL) {
734 memcpy(&new_buf[new_args_len], lp->script_args,
735 lp->script_args_len);
736 free(lp->script_args);
737 }
738
739 lp->script_args = new_buf;
740 lp->script_args_len += new_args_len;
741
742 // Load the interpreter into memory
743 status = setup_loader_svc(lp);
744 if (status != ZX_OK)
745 return lp_error(lp, status, "file_load: setup_loader_svc() failed");
746
747 status = loader_svc_rpc(lp->special_handles[HND_LDSVC_LOADER],
748 LDMSG_OP_LOAD_SCRIPT_INTERPRETER,
749 interp_start, interp_len, &vmo);
750 if (status != ZX_OK)
751 return lp_error(lp, status, "file_load: loader_svc_rpc() failed");
752 }
753
754 // Finally, load the interpreter itself
755 status = launchpad_elf_load_body(lp, first_line, to_read, vmo);
756
757 if (status != ZX_OK)
758 lp_error(lp, status, "file_load: failed to load ELF file");
759
760 return status;
761 }
762
launchpad_elf_load(launchpad_t * lp,zx_handle_t vmo)763 zx_status_t launchpad_elf_load(launchpad_t* lp, zx_handle_t vmo) {
764 if (vmo == ZX_HANDLE_INVALID)
765 return lp_error(lp, ZX_ERR_INVALID_ARGS, "elf_load: invalid vmo");
766
767 return launchpad_elf_load_body(lp, NULL, 0, vmo);
768 }
769
770 static zx_handle_t vdso_vmo = ZX_HANDLE_INVALID;
771 static mtx_t vdso_mutex = MTX_INIT;
vdso_lock(void)772 static void vdso_lock(void) __TA_ACQUIRE(&vdso_mutex) {
773 mtx_lock(&vdso_mutex);
774 }
vdso_unlock(void)775 static void vdso_unlock(void) __TA_RELEASE(&vdso_mutex) {
776 mtx_unlock(&vdso_mutex);
777 }
vdso_get_vmo(void)778 static zx_handle_t vdso_get_vmo(void) {
779 if (vdso_vmo == ZX_HANDLE_INVALID)
780 vdso_vmo = zx_take_startup_handle(PA_HND(PA_VMO_VDSO, 0));
781 return vdso_vmo;
782 }
783
launchpad_get_vdso_vmo(zx_handle_t * out)784 zx_status_t launchpad_get_vdso_vmo(zx_handle_t* out) {
785 vdso_lock();
786 zx_status_t status = zx_handle_duplicate(vdso_get_vmo(),
787 ZX_RIGHT_SAME_RIGHTS, out);
788 vdso_unlock();
789 return status;
790 }
791
launchpad_set_vdso_vmo(zx_handle_t new_vdso_vmo)792 zx_handle_t launchpad_set_vdso_vmo(zx_handle_t new_vdso_vmo) {
793 vdso_lock();
794 zx_handle_t old = vdso_vmo;
795 vdso_vmo = new_vdso_vmo;
796 vdso_unlock();
797 return old;
798 }
799
launchpad_add_vdso_vmo(launchpad_t * lp)800 zx_status_t launchpad_add_vdso_vmo(launchpad_t* lp) {
801 if (lp->error)
802 return lp->error;
803 zx_handle_t vdso;
804 zx_status_t status;
805 if ((status = launchpad_get_vdso_vmo(&vdso)) != ZX_OK)
806 return lp_error(lp, status, "add_vdso_vmo: get_vdso_vmo failed");
807 // Takes ownership of 'vdso'.
808 return launchpad_add_handle(lp, vdso, PA_HND(PA_VMO_VDSO, 0));
809 }
810
launchpad_load_vdso(launchpad_t * lp,zx_handle_t vmo)811 zx_status_t launchpad_load_vdso(launchpad_t* lp, zx_handle_t vmo) {
812 if (vmo != ZX_HANDLE_INVALID)
813 return launchpad_elf_load_extra(lp, vmo, &lp->vdso_base, NULL);
814 vdso_lock();
815 vmo = vdso_get_vmo();
816 zx_status_t status = launchpad_elf_load_extra(lp, vmo,
817 &lp->vdso_base, NULL);
818 vdso_unlock();
819 return status;
820 }
821
launchpad_get_entry_address(launchpad_t * lp,zx_vaddr_t * entry)822 zx_status_t launchpad_get_entry_address(launchpad_t* lp, zx_vaddr_t* entry) {
823 if (lp->entry == 0)
824 return ZX_ERR_BAD_STATE;
825 *entry = lp->entry;
826 return ZX_OK;
827 }
828
launchpad_get_base_address(launchpad_t * lp,zx_vaddr_t * base)829 zx_status_t launchpad_get_base_address(launchpad_t* lp, zx_vaddr_t* base) {
830 if (lp->base == 0)
831 return ZX_ERR_BAD_STATE;
832 *base = lp->base;
833 return ZX_OK;
834 }
835
launchpad_send_loader_message(launchpad_t * lp,bool do_send)836 bool launchpad_send_loader_message(launchpad_t* lp, bool do_send) {
837 bool result = lp->loader_message;
838 if (!lp->error)
839 lp->loader_message = do_send;
840 return result;
841 }
842
launchpad_use_loader_service(launchpad_t * lp,zx_handle_t svc)843 zx_handle_t launchpad_use_loader_service(launchpad_t* lp, zx_handle_t svc) {
844 zx_handle_t result = lp->special_handles[HND_LDSVC_LOADER];
845 lp->special_handles[HND_LDSVC_LOADER] = svc;
846 return result;
847 }
848
849 // Construct a load message. Fill in the header, args, and environment
850 // fields, and leave space for the handles, which should be filled in
851 // by the caller.
852 // TODO(mcgrathr): One day we'll have a gather variant of message_write
853 // and then we can send this without copying into a temporary buffer.
build_message(launchpad_t * lp,size_t num_handles,void ** msg_buf,size_t * buf_size,bool with_names)854 static zx_status_t build_message(launchpad_t* lp, size_t num_handles,
855 void** msg_buf, size_t* buf_size,
856 bool with_names) {
857
858 size_t msg_size = sizeof(zx_proc_args_t);
859 static_assert(sizeof(zx_proc_args_t) % sizeof(uint32_t) == 0,
860 "handles misaligned in load message");
861 msg_size += sizeof(uint32_t) * num_handles;
862 msg_size += lp->script_args_len;
863 msg_size += lp->args_len;
864 msg_size += lp->env_len;
865 msg_size += lp->names_len;
866 void* msg = malloc(msg_size);
867 if (msg == NULL)
868 return ZX_ERR_NO_MEMORY;
869
870 zx_proc_args_t* header = msg;
871
872 memset(header, 0, sizeof(*header));
873 header->protocol = ZX_PROCARGS_PROTOCOL;
874 header->version = ZX_PROCARGS_VERSION;
875 header->handle_info_off = sizeof(*header);
876
877 // Include the argument strings so the dynamic linker can use argv[0]
878 // in messages it prints.
879 header->args_off = header->handle_info_off +
880 sizeof(uint32_t) * num_handles;
881 header->args_num = lp->num_script_args + lp->argc;
882 if (header->args_num > 0) {
883 uint8_t* script_args_start = (uint8_t*)msg + header->args_off;
884 memcpy(script_args_start, lp->script_args, lp->script_args_len);
885 uint8_t* args_start = script_args_start + lp->script_args_len;
886 memcpy(args_start, lp->args, lp->args_len);
887 }
888 size_t total_args_len = lp->script_args_len + lp->args_len;
889
890 // Include the environment strings so the dynamic linker can
891 // see options like LD_DEBUG or whatnot.
892 if (lp->envc > 0) {
893 header->environ_off = header->args_off + total_args_len;
894 header->environ_num = lp->envc;
895 uint8_t* env_start = (uint8_t*)msg + header->environ_off;
896 memcpy(env_start, lp->env, lp->env_len);
897 }
898
899 if (with_names && (lp->namec > 0)) {
900 header->names_off = header->args_off + total_args_len + lp->env_len;
901 header->names_num = lp->namec;
902 uint8_t* names_start = (uint8_t*)msg + header->names_off;
903 memcpy(names_start, lp->names, lp->names_len);
904 }
905
906 *msg_buf = msg;
907 *buf_size = msg_size;
908 return ZX_OK;
909 }
910
send_loader_message(launchpad_t * lp,zx_handle_t first_thread,zx_handle_t tochannel)911 static zx_status_t send_loader_message(launchpad_t* lp,
912 zx_handle_t first_thread,
913 zx_handle_t tochannel) {
914 void* msg;
915 size_t msg_size;
916 size_t num_handles = HND_SPECIAL_COUNT + HND_LOADER_COUNT;
917
918 zx_status_t status = build_message(lp, num_handles, &msg, &msg_size, false);
919 if (status != ZX_OK)
920 return status;
921
922 zx_proc_args_t* header = msg;
923 uint32_t* msg_handle_info;
924 msg_handle_info = (uint32_t*) ((uint8_t*)msg + header->handle_info_off);
925
926 // This loop should be completely unrolled. But using a switch here
927 // gives us compiler warnings if we forget to handle any of the special
928 // types listed in the enum.
929 zx_handle_t handles[HND_SPECIAL_COUNT + HND_LOADER_COUNT];
930 size_t nhandles = 0;
931 for (enum special_handles i = 0; i <= HND_SPECIAL_COUNT; ++i) {
932 uint32_t id = 0; // -Wall
933 switch (i) {
934 case HND_SPECIAL_COUNT:;
935 // Duplicate the handles for the loader so we can send them in the
936 // loader message and still have them later.
937 zx_handle_t proc;
938 status = zx_handle_duplicate(lp_proc(lp), ZX_RIGHT_SAME_RIGHTS, &proc);
939 if (status != ZX_OK) {
940 free(msg);
941 return status;
942 }
943 zx_handle_t vmar;
944 status = zx_handle_duplicate(lp_vmar(lp), ZX_RIGHT_SAME_RIGHTS, &vmar);
945 if (status != ZX_OK) {
946 zx_handle_close(proc);
947 free(msg);
948 return status;
949 }
950 zx_handle_t thread;
951 status = zx_handle_duplicate(first_thread, ZX_RIGHT_SAME_RIGHTS, &thread);
952 if (status != ZX_OK) {
953 zx_handle_close(proc);
954 zx_handle_close(vmar);
955 free(msg);
956 return status;
957 }
958 handles[nhandles] = proc;
959 msg_handle_info[nhandles] = PA_PROC_SELF;
960 handles[nhandles + 1] = vmar;
961 msg_handle_info[nhandles + 1] = PA_VMAR_ROOT;
962 handles[nhandles + 2] = thread;
963 msg_handle_info[nhandles + 2] = PA_THREAD_SELF;
964 nhandles += HND_LOADER_COUNT;
965 continue;
966
967 case HND_LDSVC_LOADER:
968 id = PA_LDSVC_LOADER;
969 break;
970
971 case HND_EXEC_VMO:
972 id = PA_VMO_EXECUTABLE;
973 break;
974
975 case HND_SEGMENTS_VMAR:
976 id = PA_VMAR_LOADED;
977 break;
978 }
979 if (lp->special_handles[i] != ZX_HANDLE_INVALID) {
980 handles[nhandles] = lp->special_handles[i];
981 msg_handle_info[nhandles] = id;
982 ++nhandles;
983 }
984 }
985
986 status = zx_channel_write(tochannel, 0, msg, msg_size, handles, nhandles);
987 if (status == ZX_OK)
988 lp->loader_message = false;
989
990 // message_write consumed all those handles.
991 for (enum special_handles i = 0; i < HND_SPECIAL_COUNT; ++i)
992 lp->special_handles[i] = ZX_HANDLE_INVALID;
993
994 free(msg);
995 return status;
996 }
997
launchpad_set_stack_size(launchpad_t * lp,size_t new_size)998 size_t launchpad_set_stack_size(launchpad_t* lp, size_t new_size) {
999 size_t old_size = lp->stack_size;
1000 if (new_size >= (SIZE_MAX & -PAGE_SIZE)) {
1001 // Ridiculously large size won't actually work at allocation time,
1002 // but at least page rounding won't wrap it around to zero.
1003 new_size = SIZE_MAX & -PAGE_SIZE;
1004 } else if (new_size > 0) {
1005 // Round up to page size.
1006 new_size = (new_size + PAGE_SIZE - 1) & -PAGE_SIZE;
1007 }
1008 if (lp->error == ZX_OK) {
1009 lp->stack_size = new_size;
1010 lp->set_stack_size = true;
1011 }
1012 return old_size;
1013 }
1014
prepare_start(launchpad_t * lp,launchpad_start_data_t * result)1015 static zx_status_t prepare_start(launchpad_t* lp, launchpad_start_data_t* result) {
1016 if (lp->entry == 0)
1017 return lp_error(lp, ZX_ERR_BAD_STATE, "prepare start bad state");
1018
1019 zx_status_t status = ZX_OK;
1020 zx_handle_t to_child = ZX_HANDLE_INVALID;
1021 zx_handle_t bootstrap = ZX_HANDLE_INVALID;
1022 zx_handle_t process = ZX_HANDLE_INVALID;
1023 zx_handle_t root_vmar = ZX_HANDLE_INVALID;
1024 zx_handle_t thread = ZX_HANDLE_INVALID;
1025 void *msg = NULL;
1026
1027 status = zx_channel_create(0, &to_child, &bootstrap);
1028 if (status != ZX_OK)
1029 return lp_error(lp, status, "start: cannot create channel");
1030
1031 const char* thread_name = "initial-thread";
1032 status = zx_thread_create(lp_proc(lp), thread_name, strlen(thread_name), 0, &thread);
1033 if (status != ZX_OK) {
1034 lp_error(lp, status, "cannot create initial thread");
1035 goto cleanup;
1036 }
1037
1038 // Pass the thread handle down to the child. The handle we pass
1039 // will be consumed by message_write. So we need a duplicate to
1040 // pass to zx_process_start later.
1041 zx_handle_t thread_copy;
1042 status = zx_handle_duplicate(thread, ZX_RIGHT_SAME_RIGHTS, &thread_copy);
1043 if (status != ZX_OK) {
1044 lp_error(lp, status, "cannot duplicate thread handle");
1045 goto cleanup;
1046 }
1047
1048 status = launchpad_add_handle(lp, thread_copy, PA_THREAD_SELF);
1049 if (status != ZX_OK) {
1050 lp_error(lp, status, "cannot add thread self handle");
1051 goto cleanup;
1052 }
1053
1054 bool sent_loader_message = lp->loader_message;
1055 if (lp->loader_message) {
1056 status = send_loader_message(lp, thread, to_child);
1057 if (status != ZX_OK) {
1058 lp_error(lp, status, "failed to send loader message");
1059 goto cleanup;
1060 }
1061 }
1062
1063 bool allocate_stack = !lp->set_stack_size || lp->stack_size > 0;
1064
1065 size_t size;
1066 if (build_message(lp, lp->handle_count + (allocate_stack ? 1 : 0),
1067 &msg, &size, true) != ZX_OK) {
1068 lp_error(lp, ZX_ERR_NO_MEMORY,
1069 "out of memory assembling procargs message");
1070 goto cleanup;
1071 }
1072 zx_proc_args_t* header = msg;
1073 uint32_t* next_handle = mempcpy((uint8_t*)msg + header->handle_info_off,
1074 lp->handles_info,
1075 lp->handle_count * sizeof(lp->handles_info[0]));
1076 if (allocate_stack)
1077 *next_handle = PA_VMO_STACK;
1078
1079 // Figure out how big an initial thread to allocate.
1080 char stack_vmo_name[ZX_MAX_NAME_LEN];
1081 size_t stack_size;
1082 if (sent_loader_message && !lp->set_stack_size) {
1083 // The initial stack will be used just for startup work and to
1084 // contain the bootstrap message. Make it only as big as needed:
1085 // the message itself and its array of handles, plus some slop.
1086 stack_size = size + (lp->handle_count * sizeof(zx_handle_t));
1087
1088 // This constant is defined by the C library in <limits.h>. It's
1089 // tuned to be enough to cover the dynamic linker and C library
1090 // startup code's stack usage (up until the point it switches to
1091 // its own stack in __libc_start_main), but leave a little space so
1092 // for small bootstrap message sizes the stack needs only one page.
1093 stack_size += PTHREAD_STACK_MIN;
1094 stack_size = (stack_size + PAGE_SIZE - 1) & -PAGE_SIZE;
1095
1096 snprintf(stack_vmo_name, sizeof(stack_vmo_name),
1097 "stack: msg of %#zx", size);
1098 } else {
1099 // Use the requested or default size.
1100 stack_size =
1101 lp->set_stack_size ? lp->stack_size : ZIRCON_DEFAULT_STACK_SIZE;
1102 snprintf(stack_vmo_name, sizeof(stack_vmo_name), "stack: %s %#zx",
1103 lp->set_stack_size ? "explicit" : "default", stack_size);
1104
1105 // Assume the process will read the bootstrap message onto its
1106 // initial thread's stack. If it would need more than half its
1107 // stack just to read the message, consider that an unreasonably
1108 // large size for the message (presumably arguments and
1109 // environment strings that are unreasonably large).
1110 if (stack_size > 0 && size > stack_size / 2) {
1111 lp_error(lp, ZX_ERR_BUFFER_TOO_SMALL,
1112 "procargs message is too large");
1113 goto cleanup;
1114 }
1115 }
1116
1117 zx_vaddr_t sp = 0;
1118 if (stack_size > 0) {
1119 // Allocate the initial thread's stack.
1120 zx_handle_t stack_vmo;
1121 zx_status_t status = zx_vmo_create(stack_size, 0, &stack_vmo);
1122 if (status != ZX_OK) {
1123 lp_error(lp, status, "cannot create stack vmo");
1124 goto cleanup;
1125 }
1126 zx_object_set_property(stack_vmo, ZX_PROP_NAME,
1127 stack_vmo_name, strlen(stack_vmo_name));
1128 zx_vaddr_t stack_base;
1129 status = zx_vmar_map(lp_vmar(lp),
1130 ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
1131 0, stack_vmo, 0, stack_size, &stack_base);
1132 if (status == ZX_OK) {
1133 ZX_DEBUG_ASSERT(stack_size % PAGE_SIZE == 0);
1134 sp = compute_initial_stack_pointer(stack_base, stack_size);
1135 // Pass the stack VMO to the process. Our protocol with the
1136 // new process is that we warrant that this is the VMO from
1137 // which the initial stack is mapped and that we've exactly
1138 // mapped the entire thing, so vm_object_get_size on this in
1139 // concert with the initial SP value tells it the exact bounds
1140 // of its stack.
1141 //
1142 // Note this expands the handle list after we've already
1143 // built the bootstrap message. We shoved an extra info
1144 // slot with PA_VMO_STACK into the message, so now this new
1145 // final handle will correspond to that slot.
1146 status = launchpad_add_handle(lp, stack_vmo, PA_VMO_STACK);
1147 }
1148 if (status != ZX_OK) {
1149 zx_handle_close(stack_vmo);
1150 lp_error(lp, status, "cannot map stack vmo");
1151 goto cleanup;
1152 }
1153 }
1154
1155 if (lp->reserve_vmar != ZX_HANDLE_INVALID) {
1156 // We're done doing mappings, so clear out the reservation VMAR.
1157 status = zx_vmar_destroy(lp->reserve_vmar);
1158 if (status != ZX_OK) {
1159 lp_error(lp, status, "\
1160 zx_vmar_destroy failed on low address space reservation VMAR");
1161 goto cleanup;
1162 }
1163 status = zx_handle_close(lp->reserve_vmar);
1164 if (status != ZX_OK) {
1165 lp_error(lp, status, "\
1166 zx_handle_close failed on low address space reservation VMAR");
1167 goto cleanup;
1168 }
1169 lp->reserve_vmar = ZX_HANDLE_INVALID;
1170 }
1171
1172 // The process handle in lp->handles[0] will be consumed by message_write.
1173 // So we'll need a duplicate to do process operations later.
1174 status = zx_handle_duplicate(lp_proc(lp), ZX_RIGHT_SAME_RIGHTS, &process);
1175 if (status != ZX_OK) {
1176 lp_error(lp, status, "cannot duplicate process handle");
1177 goto cleanup;
1178 }
1179
1180 // The root_vmar handle in lp->handles[0] will be consumed by message_write.
1181 // So we'll need a duplicate to do process operations later.
1182 status = zx_handle_duplicate(lp_vmar(lp), ZX_RIGHT_SAME_RIGHTS, &root_vmar);
1183 if (status != ZX_OK) {
1184 lp_error(lp, status, "cannot duplicate root vmar handle");
1185 goto cleanup;
1186 }
1187
1188 status = zx_channel_write(to_child, 0, msg, size, lp->handles, lp->handle_count);
1189
1190 // message_write consumed all the handles.
1191 for (size_t i = 0; i < lp->handle_count; ++i)
1192 lp->handles[i] = ZX_HANDLE_INVALID;
1193 lp->handle_count = 0;
1194
1195 if (status != ZX_OK) {
1196 lp_error(lp, status, "failed to write procargs message");
1197 goto cleanup;
1198 }
1199
1200 zx_handle_close(to_child);
1201 free(msg);
1202
1203 result->process = process;
1204 result->root_vmar = root_vmar;
1205 result->thread = thread;
1206 result->entry = lp->entry;
1207 result->sp = sp;
1208 result->bootstrap = bootstrap;
1209 result->vdso_base = lp->vdso_base;
1210 result->base = lp->base;
1211 return ZX_OK;
1212
1213 cleanup:
1214 if (to_child != ZX_HANDLE_INVALID)
1215 zx_handle_close(to_child);
1216 if (bootstrap != ZX_HANDLE_INVALID)
1217 zx_handle_close(bootstrap);
1218 if (process != ZX_HANDLE_INVALID)
1219 zx_handle_close(process);
1220 if (root_vmar != ZX_HANDLE_INVALID)
1221 zx_handle_close(root_vmar);
1222 if (thread != ZX_HANDLE_INVALID)
1223 zx_handle_close(thread);
1224 free(msg);
1225 return lp->error;
1226 }
1227
1228 // Start the process running. If the send_loader_message flag is
1229 // set and this succeeds in sending the initial bootstrap message,
1230 // it clears the loader-service handle. If this succeeds in sending
1231 // the main bootstrap message, it clears the list of handles to
1232 // transfer (after they've been transferred) as well as the process
1233 // handle.
1234 //
1235 // Returns the process handle via |process_out| on success, giving
1236 // ownership to the caller. On failure, the return value doesn't
1237 // distinguish failure to send the first or second message from
1238 // failure to start the process, so on failure the loader-service
1239 // handle might or might not have been cleared and the handles to
1240 // transfer might or might not have been cleared.
launchpad_start(launchpad_t * lp,zx_handle_t * process_out)1241 static zx_status_t launchpad_start(launchpad_t* lp, zx_handle_t* process_out) {
1242 if (lp->error)
1243 return lp->error;
1244
1245 launchpad_start_data_t data;
1246 zx_status_t status = prepare_start(lp, &data);
1247 if (status != ZX_OK)
1248 return status;
1249
1250 status = zx_process_start(data.process, data.thread, data.entry, data.sp,
1251 data.bootstrap, data.vdso_base);
1252
1253 zx_handle_close(data.thread);
1254 zx_handle_close(data.root_vmar);
1255
1256 if (status != ZX_OK) {
1257 zx_handle_close(data.process);
1258 return lp_error(lp, status, "zx_process_start() failed");
1259 }
1260
1261 *process_out = data.process;
1262 return ZX_OK;
1263 }
1264
launchpad_go(launchpad_t * lp,zx_handle_t * proc,const char ** errmsg)1265 zx_status_t launchpad_go(launchpad_t* lp, zx_handle_t* proc, const char** errmsg) {
1266 zx_handle_t h = ZX_HANDLE_INVALID;
1267 zx_status_t status = launchpad_start(lp, &h);
1268 if (errmsg)
1269 *errmsg = lp->errmsg;
1270 if (status == ZX_OK) {
1271 if (proc) {
1272 *proc = h;
1273 } else {
1274 zx_handle_close(h);
1275 }
1276 }
1277 launchpad_destroy(lp);
1278 return status;
1279 }
1280
launchpad_ready_set(launchpad_t * lp,launchpad_start_data_t * data,const char ** errmsg)1281 zx_status_t launchpad_ready_set(launchpad_t* lp,
1282 launchpad_start_data_t* data,
1283 const char** errmsg) {
1284 zx_status_t status = prepare_start(lp, data);
1285 if (errmsg)
1286 *errmsg = lp->errmsg;
1287 launchpad_destroy(lp);
1288 return status;
1289 }
1290
launchpad_file_load_with_vdso(launchpad_t * lp,zx_handle_t vmo)1291 static zx_status_t launchpad_file_load_with_vdso(launchpad_t* lp, zx_handle_t vmo) {
1292 launchpad_file_load(lp, vmo);
1293 launchpad_load_vdso(lp, ZX_HANDLE_INVALID);
1294 return launchpad_add_vdso_vmo(lp);
1295 }
1296
launchpad_load_from_file(launchpad_t * lp,const char * path)1297 zx_status_t launchpad_load_from_file(launchpad_t* lp, const char* path) {
1298 zx_handle_t vmo;
1299 zx_status_t status = launchpad_vmo_from_file(path, &vmo);
1300 if (status == ZX_OK) {
1301 return launchpad_file_load_with_vdso(lp, vmo);
1302 } else {
1303 return lp_error(lp, status, "launchpad_vmo_from_file failure");
1304 }
1305 }
1306
launchpad_load_from_fd(launchpad_t * lp,int fd)1307 zx_status_t launchpad_load_from_fd(launchpad_t* lp, int fd) {
1308 zx_handle_t vmo;
1309 zx_status_t status = fdio_get_vmo_clone(fd, &vmo);
1310 if (status == ZX_OK) {
1311 return launchpad_file_load_with_vdso(lp, vmo);
1312 } else {
1313 return status;
1314 }
1315 }
1316
launchpad_load_from_vmo(launchpad_t * lp,zx_handle_t vmo)1317 zx_status_t launchpad_load_from_vmo(launchpad_t* lp, zx_handle_t vmo) {
1318 return launchpad_file_load_with_vdso(lp, vmo);
1319 }
1320