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 <loader-service/loader-service.h>
6 
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <lib/fdio/io.h>
10 #include <inttypes.h>
11 #include <ldmsg/ldmsg.h>
12 #include <lib/async-loop/loop.h>
13 #include <lib/async/wait.h>
14 #include <limits.h>
15 #include <stdatomic.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <sys/stat.h>
20 #include <unistd.h>
21 #include <zircon/compiler.h>
22 #include <zircon/device/vfs.h>
23 #include <zircon/status.h>
24 #include <zircon/syscalls.h>
25 #include <zircon/types.h>
26 
27 #define PREFIX_MAX 32
28 
29 // State of a loader service instance.
30 typedef struct instance_state instance_state_t;
31 struct instance_state {
32   int root_dir_fd;
33   int data_sink_dir_fd;
34   // NULL-terminated list of paths from which objects will loaded.
35   const char* const* lib_paths;
36 };
37 
38 // This represents an instance of the loader service. Each session in an
39 // instance has a session_state_t pointing to this. All sessions in
40 // the same instance behave the same.
41 struct loader_service {
42     atomic_int refcount;
43     async_dispatcher_t* dispatcher;
44 
45     const loader_service_ops_t* ops;
46     void* ctx;
47 };
48 
49 // Per-session state of a loader service instance.
50 typedef struct session_state session_state_t;
51 struct session_state {
52     async_wait_t wait; // Must be first.
53     char config_prefix[PREFIX_MAX];
54     bool config_exclusive;
55     loader_service_t* svc;
56 };
57 
loader_service_addref(loader_service_t * svc)58 static void loader_service_addref(loader_service_t* svc) {
59     atomic_fetch_add(&svc->refcount, 1);
60 }
61 
loader_service_deref(loader_service_t * svc)62 static void loader_service_deref(loader_service_t* svc) {
63     if (atomic_fetch_sub(&svc->refcount, 1) == 1) {
64         if (svc->ops->finalizer)
65             svc->ops->finalizer(svc->ctx);
66         free(svc);
67     }
68 }
69 
70 // When loading a library object, search in the locations provided in
71 // |lib_paths|, which is required to be NULL-terminated.
open_from_lib_paths(int root_dir_fd,const char * const * lib_paths,const char * fn)72 static int open_from_lib_paths(int root_dir_fd, const char* const* lib_paths,
73                                const char* fn) {
74     int fd = -1;
75     for (size_t n = 0; fd < 0 && lib_paths[n]; ++n) {
76         char path[PATH_MAX];
77         if (snprintf(path, sizeof(path), "%s/%s", lib_paths[n], fn) < 0) {
78             return -1;
79         }
80         fd = openat(root_dir_fd, path, O_RDONLY);
81     }
82     return fd;
83 }
84 
85 // Always consumes the |fd|.
vmo_from_fd(int fd,const char * fn,zx_handle_t * out)86 static zx_handle_t vmo_from_fd(int fd, const char* fn, zx_handle_t* out) {
87     zx_status_t status = fdio_get_vmo_clone(fd, out);
88     close(fd);
89     if (status == ZX_OK) {
90         zx_object_set_property(*out, ZX_PROP_NAME, fn, strlen(fn));
91     }
92     return status;
93 }
94 
fd_load_object(void * ctx,const char * name,zx_handle_t * out)95 static zx_status_t fd_load_object(void* ctx, const char* name, zx_handle_t* out) {
96     int root_dir_fd = ((instance_state_t*)ctx)->root_dir_fd;
97     const char* const* lib_paths = ((instance_state_t*)ctx)->lib_paths;
98 
99     int fd = open_from_lib_paths(root_dir_fd, lib_paths, name);
100     if (fd >= 0) {
101         return vmo_from_fd(fd, name, out);
102     }
103     return ZX_ERR_NOT_FOUND;
104 }
105 
fd_load_abspath(void * ctx,const char * path,zx_handle_t * out)106 static zx_status_t fd_load_abspath(void* ctx, const char* path, zx_handle_t* out) {
107     int root_dir_fd = ((instance_state_t*)ctx)->root_dir_fd;
108     int fd = openat(root_dir_fd, path, O_RDONLY);
109     if (fd >= 0) {
110         return vmo_from_fd(fd, path, out);
111     }
112     return ZX_ERR_NOT_FOUND;
113 }
114 
fd_publish_data_sink(void * ctx,const char * sink_name,zx_handle_t vmo)115 zx_status_t fd_publish_data_sink(void* ctx, const char* sink_name, zx_handle_t vmo) {
116     zx_handle_close(vmo);
117     return ZX_ERR_NOT_SUPPORTED;
118 }
119 
fd_finalizer(void * ctx)120 void fd_finalizer(void* ctx) {
121     instance_state_t* instance_state = (instance_state_t*)ctx;
122     int root_dir_fd = instance_state->root_dir_fd;
123     int data_sink_dir_fd = instance_state->data_sink_dir_fd;
124     close(root_dir_fd);
125     close(data_sink_dir_fd);
126     free(instance_state);
127 }
128 
129 static const loader_service_ops_t fd_ops = {
130     .load_object = fd_load_object,
131     .load_abspath = fd_load_abspath,
132     .publish_data_sink = fd_publish_data_sink,
133     .finalizer = fd_finalizer,
134 };
135 
loader_service_rpc(zx_handle_t h,session_state_t * session_state)136 static zx_status_t loader_service_rpc(zx_handle_t h, session_state_t* session_state) {
137     loader_service_t* svc = session_state->svc;
138     ldmsg_req_t req;
139     uint32_t req_len = sizeof(req);
140     zx_handle_t req_handle = ZX_HANDLE_INVALID;
141     uint32_t req_handle_len;
142     zx_status_t status =
143         zx_channel_read(h, 0, &req, &req_handle, req_len, 1, &req_len, &req_handle_len);
144     if (status != ZX_OK) {
145         // This is the normal error for the other end going away,
146         // which happens when the process dies.
147         if (status != ZX_ERR_PEER_CLOSED)
148             fprintf(stderr, "dlsvc: msg read error %d: %s\n", status, zx_status_get_string(status));
149         return status;
150     }
151 
152     const char* data = NULL;
153     size_t len = 0;
154     status = ldmsg_req_decode(&req, req_len, &data, &len);
155 
156     if (status != ZX_OK) {
157         zx_handle_close(req_handle);
158         fprintf(stderr, "dlsvc: invalid message\n");
159         return ZX_ERR_IO;
160     }
161 
162     zx_handle_t rsp_handle = ZX_HANDLE_INVALID;
163     switch (req.header.ordinal) {
164     case LDMSG_OP_CONFIG: {
165         size_t len = strlen(data);
166         if (len < 2 || len >= sizeof(session_state->config_prefix) - 1 || strchr(data, '/') != NULL) {
167             status = ZX_ERR_INVALID_ARGS;
168             break;
169         }
170         memcpy(session_state->config_prefix, data, len + 1);
171         session_state->config_exclusive = false;
172         if (session_state->config_prefix[len - 1] == '!') {
173             --len;
174             session_state->config_exclusive = true;
175         }
176         session_state->config_prefix[len] = '/';
177         session_state->config_prefix[len + 1] = '\0';
178         status = ZX_OK;
179         break;
180     }
181     case LDMSG_OP_LOAD_OBJECT:
182         // If a prefix is configured, try loading with that prefix first
183         if (session_state->config_prefix[0] != '\0') {
184             size_t maxlen = PREFIX_MAX + strlen(data) + 1;
185             char prefixed_name[maxlen];
186             snprintf(prefixed_name, maxlen, "%s%s", session_state->config_prefix, data);
187             if (((status = svc->ops->load_object(svc->ctx, prefixed_name, &rsp_handle)) == ZX_OK) ||
188                 session_state->config_exclusive) {
189                 // if loading with prefix succeeds, or loading
190                 // with prefix is configured to be exclusive of
191                 // non-prefix loading, stop here
192                 break;
193             }
194             // otherwise, if non-exclusive, try loading without the prefix
195         }
196         status = svc->ops->load_object(svc->ctx, data, &rsp_handle);
197         break;
198     case LDMSG_OP_LOAD_SCRIPT_INTERPRETER:
199     case LDMSG_OP_DEBUG_LOAD_CONFIG:
200         // When loading a script interpreter or debug configuration file,
201         // we expect an absolute path.
202         if (data[0] != '/') {
203             fprintf(stderr, "dlsvc: invalid %s '%s' is not an absolute path\n",
204                     req.header.ordinal == LDMSG_OP_LOAD_SCRIPT_INTERPRETER ? "script interpreter" : "debug config file",
205                     data);
206             status = ZX_ERR_NOT_FOUND;
207             break;
208         }
209         status = svc->ops->load_abspath(svc->ctx, data, &rsp_handle);
210         break;
211     case LDMSG_OP_DEBUG_PUBLISH_DATA_SINK:
212         status = svc->ops->publish_data_sink(svc->ctx, data, req_handle);
213         req_handle = ZX_HANDLE_INVALID;
214         break;
215     case LDMSG_OP_CLONE:
216         status = loader_service_attach(svc, req_handle);
217         req_handle = ZX_HANDLE_INVALID;
218         break;
219     case LDMSG_OP_DONE:
220         zx_handle_close(req_handle);
221         return ZX_ERR_PEER_CLOSED;
222     default:
223         // This case cannot happen because ldmsg_req_decode will return an
224         // error for invalid ordinals.
225         __builtin_trap();
226     }
227 
228     if (status == ZX_ERR_NOT_FOUND) {
229         fprintf(stderr, "dlsvc: could not open '%s'\n", data);
230     }
231 
232     if (req_handle != ZX_HANDLE_INVALID) {
233         fprintf(stderr, "dlsvc: unused handle (%#x) opcode=%#x data=\"%s\"\n",
234                 req_handle, req.header.ordinal, data);
235         zx_handle_close(req_handle);
236     }
237 
238     ldmsg_rsp_t rsp;
239     memset(&rsp, 0, sizeof(rsp));
240     rsp.header.txid = req.header.txid;
241     rsp.header.ordinal = req.header.ordinal;
242     rsp.rv = status;
243     rsp.object = rsp_handle == ZX_HANDLE_INVALID ? FIDL_HANDLE_ABSENT : FIDL_HANDLE_PRESENT;
244     if ((status = zx_channel_write(h, 0, &rsp, ldmsg_rsp_get_size(&rsp),
245                                    &rsp_handle, rsp_handle != ZX_HANDLE_INVALID ? 1 : 0)) < 0) {
246         fprintf(stderr, "dlsvc: msg write error: %d: %s\n", status, zx_status_get_string(status));
247         return status;
248     }
249     return ZX_OK;
250 }
251 
loader_service_create(async_dispatcher_t * dispatcher,const loader_service_ops_t * ops,void * ctx,loader_service_t ** out)252 zx_status_t loader_service_create(async_dispatcher_t* dispatcher,
253                                   const loader_service_ops_t* ops,
254                                   void* ctx,
255                                   loader_service_t** out) {
256     if (out == NULL || ops == NULL) {
257         return ZX_ERR_INVALID_ARGS;
258     }
259 
260     loader_service_t* svc = calloc(1, sizeof(loader_service_t));
261     if (svc == NULL) {
262         return ZX_ERR_NO_MEMORY;
263     }
264 
265     if (!dispatcher) {
266         async_loop_t* loop;
267         zx_status_t status = async_loop_create(&kAsyncLoopConfigNoAttachToThread, &loop);
268         if (status != ZX_OK) {
269             free(svc);
270             return status;
271         }
272 
273         status = async_loop_start_thread(loop, "loader-service", NULL);
274         if (status != ZX_OK) {
275             free(svc);
276             async_loop_destroy(loop);
277             return status;
278         }
279 
280         dispatcher = async_loop_get_dispatcher(loop);
281     }
282 
283     svc->dispatcher = dispatcher;
284     svc->ops = ops;
285     svc->ctx = ctx;
286 
287     // When we create the loader service, we initialize the refcount to 1, which
288     // causes the loader service to stay alive at least until someone calls
289     // |loader_service_release|, at which point the service will be destroyed
290     // once the last client goes away.
291     loader_service_addref(svc);
292 
293     *out = svc;
294     return ZX_OK;
295 }
296 
297 // Default library paths for the fd- and fs- loader service implementations.
298 static const char* const fd_lib_paths[] = {"lib", NULL};
299 static const char* const fs_lib_paths[] = {"system/lib", "boot/lib", NULL};
300 
301 // Create the default implementation of a loader service for which
302 // paths are loaded relative to |root_dir_fd| and among the array of
303 // subdirectories given by |lib_paths| (NULL-terminated), with data published
304 // in the location given by |data_sink_dir_fd|.
loader_service_create_default(async_dispatcher_t * dispatcher,int root_dir_fd,int data_sink_dir_fd,const char * const * lib_paths,loader_service_t ** out)305 zx_status_t loader_service_create_default(async_dispatcher_t* dispatcher,
306                                           int root_dir_fd,
307                                           int data_sink_dir_fd,
308                                           const char* const* lib_paths,
309                                           loader_service_t** out) {
310     instance_state_t* instance_state = calloc(1, sizeof(loader_service_t));
311     if (instance_state == NULL) {
312         return ZX_ERR_NO_MEMORY;
313     }
314     instance_state->root_dir_fd = root_dir_fd;
315     instance_state->data_sink_dir_fd = data_sink_dir_fd;
316     instance_state->lib_paths = lib_paths? lib_paths : fd_lib_paths;
317 
318     loader_service_t* svc;
319     zx_status_t status = loader_service_create(dispatcher, &fd_ops, NULL, &svc);
320     if (status == ZX_OK) {
321       svc->ctx = instance_state;
322       *out = svc;
323     } else {
324       free(instance_state);
325     }
326     return status;
327 }
328 
loader_service_create_fs(async_dispatcher_t * dispatcher,loader_service_t ** out)329 zx_status_t loader_service_create_fs(async_dispatcher_t* dispatcher, loader_service_t** out) {
330     int root_dir_fd = open("/", O_RDONLY | O_DIRECTORY);
331     if (root_dir_fd < 0){
332       return ZX_ERR_NOT_FOUND;
333     }
334     return loader_service_create_default(dispatcher, root_dir_fd, -1, fs_lib_paths,
335                                          out);
336 }
337 
loader_service_create_fd(async_dispatcher_t * dispatcher,int root_dir_fd,int data_sink_dir_fd,loader_service_t ** out)338 zx_status_t loader_service_create_fd(async_dispatcher_t* dispatcher,
339                                      int root_dir_fd,
340                                      int data_sink_dir_fd,
341                                      loader_service_t** out) {
342     return loader_service_create_default(dispatcher, root_dir_fd, data_sink_dir_fd,
343                                          fd_lib_paths, out);
344 }
345 
loader_service_release(loader_service_t * svc)346 zx_status_t loader_service_release(loader_service_t* svc) {
347     // This call to |loader_service_deref| balances the |loader_service_addref|
348     // call in |loader_service_create|. This reference prevents the loader
349     // service from being destroyed before its creator is done with it.
350     loader_service_deref(svc);
351     return ZX_OK;
352 }
353 
loader_service_handler(async_dispatcher_t * dispatcher,async_wait_t * wait,zx_status_t status,const zx_packet_signal_t * signal)354 static void loader_service_handler(async_dispatcher_t* dispatcher,
355                                    async_wait_t* wait,
356                                    zx_status_t status,
357                                    const zx_packet_signal_t* signal) {
358     session_state_t* session_state = (session_state_t*)wait;
359     if (status != ZX_OK)
360         goto stop;
361     status = loader_service_rpc(wait->object, session_state);
362     if (status != ZX_OK)
363         goto stop;
364     status = async_begin_wait(dispatcher, wait);
365     if (status != ZX_OK)
366         goto stop;
367     return;
368 stop:
369     zx_handle_close(wait->object);
370     loader_service_t* svc = session_state->svc;
371     free(session_state);
372     loader_service_deref(svc); // Balanced in |loader_service_attach|.
373 }
374 
loader_service_attach(loader_service_t * svc,zx_handle_t h)375 zx_status_t loader_service_attach(loader_service_t* svc, zx_handle_t h) {
376     zx_status_t status = ZX_OK;
377     session_state_t* session_state = NULL;
378 
379     if (svc == NULL) {
380         status = ZX_ERR_INVALID_ARGS;
381         goto done;
382     }
383 
384     session_state = calloc(1, sizeof(session_state_t));
385     if (session_state == NULL) {
386         status = ZX_ERR_NO_MEMORY;
387         goto done;
388     }
389 
390     session_state->wait.handler = loader_service_handler;
391     session_state->wait.object = h;
392     session_state->wait.trigger = ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED;
393     session_state->svc = svc;
394 
395     status = async_begin_wait(svc->dispatcher, &session_state->wait);
396 
397     if (status == ZX_OK) {
398         loader_service_addref(svc); // Balanced in |loader_service_handler|.
399     }
400 
401 done:
402     if (status != ZX_OK) {
403         zx_handle_close(h);
404         free(session_state);
405     }
406     return status;
407 }
408 
loader_service_connect(loader_service_t * svc,zx_handle_t * out)409 zx_status_t loader_service_connect(loader_service_t* svc, zx_handle_t* out) {
410     zx_handle_t h0, h1;
411     zx_status_t status;
412     if ((status = zx_channel_create(0, &h0, &h1)) != ZX_OK) {
413         return status;
414     }
415     if ((status = loader_service_attach(svc, h1)) != ZX_OK) {
416         zx_handle_close(h0);
417         return status;
418     }
419     *out = h0;
420     return ZX_OK;
421 }
422