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 
8 #include <zircon/process.h>
9 #include <zircon/processargs.h>
10 #include <zircon/syscalls.h>
11 #include <lib/fdio/io.h>
12 #include <lib/fdio/namespace.h>
13 #include <lib/fdio/util.h>
14 
15 #include <stdlib.h>
16 #include <unistd.h>
17 
add_fdio(launchpad_t * lp,zx_handle_t handles[FDIO_MAX_HANDLES],uint32_t types[FDIO_MAX_HANDLES],zx_status_t status)18 static zx_status_t add_fdio(launchpad_t* lp,
19                             zx_handle_t handles[FDIO_MAX_HANDLES],
20                             uint32_t types[FDIO_MAX_HANDLES],
21                             zx_status_t status) {
22     if (status == ZX_ERR_BAD_HANDLE)
23         return ZX_OK;
24     if (status == ZX_ERR_NOT_SUPPORTED)
25         return ZX_OK;
26     if (status > 0) {
27         return launchpad_add_handles(lp, status, handles, types);
28     } else {
29         launchpad_abort(lp, status, "add_fdio: failed");
30         return status;
31     }
32 }
33 
launchpad_clone(launchpad_t * lp,uint32_t what)34 zx_status_t launchpad_clone(launchpad_t* lp, uint32_t what) {
35     zx_handle_t handles[FDIO_MAX_HANDLES];
36     uint32_t types[FDIO_MAX_HANDLES];
37     zx_status_t status;
38 
39     if (what & LP_CLONE_FDIO_NAMESPACE) {
40         fdio_flat_namespace_t* flat;
41         status = fdio_ns_export_root(&flat);
42         if (status == ZX_OK) {
43             launchpad_set_nametable(lp, flat->count, flat->path);
44             launchpad_add_handles(lp, flat->count, flat->handle, flat->type);
45             free(flat);
46         } else if (status != ZX_ERR_NOT_FOUND) {
47             launchpad_abort(lp, status, "clone: error cloning namespace");
48             return status;
49         }
50     }
51     if (what & LP_CLONE_FDIO_STDIO) {
52         for (int fd = 0; fd < 3; fd++) {
53             add_fdio(lp, handles, types, fdio_clone_fd(fd, fd, handles, types));
54         }
55     }
56     if (what & LP_CLONE_ENVIRON) {
57         launchpad_set_environ(lp, (const char* const*)environ);
58     }
59     if (what & LP_CLONE_DEFAULT_JOB) {
60         zx_handle_t job;
61         if (zx_handle_duplicate(zx_job_default(), ZX_RIGHT_SAME_RIGHTS, &job) == ZX_OK) {
62             launchpad_add_handle(lp, job, PA_HND(PA_JOB_DEFAULT, 0));
63         }
64     }
65     return launchpad_get_status(lp);
66 }
67 
launchpad_clone_fd(launchpad_t * lp,int fd,int target_fd)68 zx_status_t launchpad_clone_fd(launchpad_t* lp, int fd, int target_fd) {
69     zx_handle_t handles[FDIO_MAX_HANDLES];
70     uint32_t types[FDIO_MAX_HANDLES];
71     return add_fdio(lp, handles, types,
72                     fdio_clone_fd(fd, target_fd, handles, types));
73 }
74 
launchpad_transfer_fd(launchpad_t * lp,int fd,int target_fd)75 zx_status_t launchpad_transfer_fd(launchpad_t* lp, int fd, int target_fd) {
76     zx_handle_t handles[FDIO_MAX_HANDLES];
77     uint32_t types[FDIO_MAX_HANDLES];
78     return add_fdio(lp, handles, types,
79                     fdio_transfer_fd(fd, target_fd, handles, types));
80 }
81