1 /*
2  * Copyright (c) 2020, Google Inc. All rights reserved
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files
6  * (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge,
8  * publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 
24 #define LOCAL_TRACE 0
25 
26 #include <err.h>
27 #include <interface/apploader/apploader.h>
28 #include <interface/apploader/apploader_secure.h>
29 #include <inttypes.h>
30 #include <kernel/thread.h>
31 #include <kernel/vm.h>
32 #include <lib/ktipc/ktipc.h>
33 #include <lib/trusty/handle_set.h>
34 #include <lib/trusty/ipc.h>
35 #include <lib/trusty/ipc_msg.h>
36 #include <lib/trusty/memref.h>
37 #include <lk/err_ptr.h>
38 #include <lk/init.h>
39 #include <lk/trace.h>
40 #include <string.h>
41 #include <uapi/mm.h>
42 
43 struct apploader_channel_ctx {
44     struct vmm_obj_slice vmm_obj_slice;
45 };
46 
47 /* UUID: {081ba88f-f1ee-452e-b5e8-a7e9ef173a97} */
48 static const struct uuid apploader_user_uuid = {
49         0x081ba88f,
50         0xf1ee,
51         0x452e,
52         {0xb5, 0xe8, 0xa7, 0xe9, 0xef, 0x17, 0x3a, 0x97},
53 };
54 
55 #if TEST_BUILD
56 /* UUID: {c549cb7c-f8dc-4063-8661-ef34fb3be6fc} */
57 static const struct uuid apploader_unittest_uuid = {
58         0xc549cb7c,
59         0xf8dc,
60         0x4063,
61         {0x86, 0x61, 0xef, 0x34, 0xfb, 0x3b, 0xe6, 0xfc},
62 };
63 #endif
64 
65 const static struct uuid* apploader_service_uuids[] = {
66         &apploader_user_uuid,
67 #if TEST_BUILD
68         &apploader_unittest_uuid,
69 #endif
70 };
71 
72 struct apploader_secure_req {
73     struct apploader_secure_header hdr;
74     union {
75         struct apploader_secure_get_memory_req get_memory_req;
76         struct apploader_secure_load_app_req load_app_req;
77     };
78 } __PACKED;
79 
80 /*
81  * Common structure covering all possible apploader messages, only used to
82  * determine the maximum message size
83  */
84 union apploader_longest_secure_msg {
85     struct apploader_secure_req req;
86     struct apploader_secure_resp resp;
87 } __PACKED;
88 
apploader_service_translate_error(status_t rc)89 static int apploader_service_translate_error(status_t rc) {
90     switch (rc) {
91     case ERR_NO_MEMORY:
92         return APPLOADER_ERR_NO_MEMORY;
93     case ERR_ALREADY_EXISTS:
94         return APPLOADER_ERR_ALREADY_EXISTS;
95     default:
96         TRACEF("%s: unrecognized error (%d)\n", __func__, rc);
97         return APPLOADER_ERR_INTERNAL;
98     }
99 }
100 
apploader_service_send_response(struct handle * chan,uint32_t cmd,uint32_t error,struct handle ** handles,uint32_t num_handles)101 static int apploader_service_send_response(struct handle* chan,
102                                            uint32_t cmd,
103                                            uint32_t error,
104                                            struct handle** handles,
105                                            uint32_t num_handles) {
106     struct apploader_secure_resp resp = {
107             .hdr =
108                     {
109                             .cmd = cmd | APPLOADER_SECURE_RESP_BIT,
110                     },
111             .error = error,
112     };
113 
114     int rc =
115             ktipc_send_handles(chan, handles, num_handles, &resp, sizeof(resp));
116     if (rc != (int)sizeof(resp)) {
117         return ERR_BAD_LEN;
118     }
119 
120     return NO_ERROR;
121 }
122 
apploader_service_handle_cmd_get_memory(struct handle * chan,struct apploader_channel_ctx * channel_ctx,struct apploader_secure_get_memory_req * req)123 static int apploader_service_handle_cmd_get_memory(
124         struct handle* chan,
125         struct apploader_channel_ctx* channel_ctx,
126         struct apploader_secure_get_memory_req* req) {
127     int rc;
128     uint32_t resp_error;
129 
130     if (channel_ctx->vmm_obj_slice.obj) {
131         TRACEF("%s: client already holds a memref\n", __func__);
132         resp_error = APPLOADER_ERR_INVALID_CMD;
133         goto err_chan_has_memref;
134     }
135 
136     if (!req->package_size) {
137         TRACEF("%s: 0-sized GET_MEMORY request\n", __func__);
138         resp_error = APPLOADER_ERR_INVALID_CMD;
139         goto err_zero_size;
140     }
141 
142     uint64_t aligned_size = round_up(req->package_size, PAGE_SIZE);
143     LTRACEF("Handling GET_MEMORY command, package size %" PRIu64
144             " bytes, %" PRIu64 " aligned\n",
145             req->package_size, aligned_size);
146 
147     struct vmm_obj* vmm_obj;
148     struct obj_ref vmm_obj_ref = OBJ_REF_INITIAL_VALUE(vmm_obj_ref);
149     rc = pmm_alloc(&vmm_obj, &vmm_obj_ref, aligned_size / PAGE_SIZE, 0, 0);
150     if (rc != NO_ERROR) {
151         TRACEF("%s: error (%d) allocating memory\n", __func__, rc);
152         resp_error = apploader_service_translate_error(rc);
153         goto err_alloc;
154     }
155 
156     struct handle* memref_handle;
157     uint32_t prot_flags = MMAP_FLAG_PROT_READ | MMAP_FLAG_PROT_WRITE;
158     rc = memref_create_from_vmm_obj(vmm_obj, 0, aligned_size, prot_flags,
159                                     &memref_handle);
160     if (rc != NO_ERROR) {
161         TRACEF("%s: error (%d) creating memref\n", __func__, rc);
162         resp_error = apploader_service_translate_error(rc);
163         goto err_memref_create;
164     }
165 
166     rc = apploader_service_send_response(chan, APPLOADER_SECURE_CMD_GET_MEMORY,
167                                          APPLOADER_NO_ERROR, &memref_handle, 1);
168     if (rc < 0) {
169         TRACEF("%s: error (%d) sending response\n", __func__, rc);
170     } else {
171         vmm_obj_slice_bind(&channel_ctx->vmm_obj_slice, vmm_obj, 0,
172                            aligned_size);
173     }
174 
175     handle_decref(memref_handle);
176     vmm_obj_del_ref(vmm_obj, &vmm_obj_ref);
177 
178     return rc;
179 
180 err_memref_create:
181     vmm_obj_del_ref(vmm_obj, &vmm_obj_ref);
182 err_alloc:
183 err_zero_size:
184 err_chan_has_memref:
185     return apploader_service_send_response(
186             chan, APPLOADER_SECURE_CMD_GET_MEMORY, resp_error, NULL, 0);
187 }
188 
apploader_service_handle_cmd_load_application(struct handle * chan,struct apploader_channel_ctx * channel_ctx,struct apploader_secure_load_app_req * req)189 static int apploader_service_handle_cmd_load_application(
190         struct handle* chan,
191         struct apploader_channel_ctx* channel_ctx,
192         struct apploader_secure_load_app_req* req) {
193     int rc;
194     uint32_t resp_error;
195 
196     if (!channel_ctx->vmm_obj_slice.obj) {
197         TRACEF("%s: invalid handle\n", __func__);
198         resp_error = APPLOADER_ERR_INVALID_CMD;
199         goto err_invalid_handle;
200     }
201 
202     if (!vmm_obj_has_only_ref(channel_ctx->vmm_obj_slice.obj,
203                               &channel_ctx->vmm_obj_slice.obj_ref)) {
204         TRACEF("%s: service not holding single reference to memref\n",
205                __func__);
206         resp_error = APPLOADER_ERR_INVALID_CMD;
207         goto err_invalid_refcount;
208     }
209 
210     if (req->manifest_start >= req->manifest_end ||
211         req->manifest_end > channel_ctx->vmm_obj_slice.size) {
212         TRACEF("%s: received invalid manifest offsets: 0x%" PRIx64 "-0x%" PRIx64
213                "\n",
214                __func__, req->manifest_start, req->manifest_end);
215         resp_error = APPLOADER_ERR_INVALID_CMD;
216         goto err_invalid_manifest_offsets;
217     }
218 
219     if (req->img_start >= req->img_end ||
220         req->img_end > channel_ctx->vmm_obj_slice.size) {
221         TRACEF("%s: received invalid image offsets: 0x%" PRIx64 "-0x%" PRIx64
222                "\n",
223                __func__, req->img_start, req->img_end);
224         resp_error = APPLOADER_ERR_INVALID_CMD;
225         goto err_invalid_image_offsets;
226     }
227 
228     LTRACEF("Handling LOAD_APPLICATION command, package size %zd bytes\n",
229             channel_ctx->vmm_obj_slice.size);
230 
231     void* va;
232     rc = vmm_alloc_obj(vmm_get_kernel_aspace(), "app package",
233                        channel_ctx->vmm_obj_slice.obj, 0,
234                        channel_ctx->vmm_obj_slice.size, &va, 0, 0,
235                        ARCH_MMU_FLAG_PERM_NO_EXECUTE | ARCH_MMU_FLAG_PERM_RO);
236     if (rc != NO_ERROR) {
237         TRACEF("%s: error (%d) allocation memory for vmm object\n", __func__,
238                rc);
239         resp_error = apploader_service_translate_error(rc);
240         goto err_alloc_app;
241     }
242 
243     struct trusty_app_img* app_img = calloc(1, sizeof(struct trusty_app_img));
244     if (!app_img) {
245         TRACEF("%s: error (%d) allocating struct trusty_app_img\n", __func__,
246                rc);
247         resp_error = APPLOADER_ERR_NO_MEMORY;
248         goto err_alloc_app_img;
249     }
250 
251     if (__builtin_add_overflow((uintptr_t)va, req->manifest_start,
252                                &app_img->manifest_start) ||
253         __builtin_add_overflow((uintptr_t)va, req->manifest_end,
254                                &app_img->manifest_end) ||
255         __builtin_add_overflow((uintptr_t)va, req->img_start,
256                                &app_img->img_start) ||
257         __builtin_add_overflow((uintptr_t)va, req->img_end,
258                                &app_img->img_end)) {
259         TRACEF("%s: overflow when computing trusty_app pointers\n", __func__);
260         resp_error = APPLOADER_ERR_LOADING_FAILED;
261         goto err_trusty_app_overflow;
262     }
263 
264     rc = trusty_app_create_and_start(app_img, APP_FLAGS_LOADABLE);
265     if (rc < 0) {
266         TRACEF("%s: error (%d) creating Trusty app\n", __func__, rc);
267         if (rc == ERR_NOT_VALID) {
268             resp_error = APPLOADER_ERR_LOADING_FAILED;
269         } else {
270             resp_error = apploader_service_translate_error(rc);
271         }
272         goto err_create_app;
273     }
274 
275     /* Release the slice to prevent clients from loading the app twice */
276     vmm_obj_slice_release(&channel_ctx->vmm_obj_slice);
277 
278     return apploader_service_send_response(
279             chan, APPLOADER_SECURE_CMD_LOAD_APPLICATION, APPLOADER_NO_ERROR,
280             NULL, 0);
281 
282 err_create_app:
283 err_trusty_app_overflow:
284     free(app_img);
285 err_alloc_app_img:
286     vmm_free_region(vmm_get_kernel_aspace(), (vaddr_t)va);
287 err_alloc_app:
288 err_invalid_image_offsets:
289 err_invalid_manifest_offsets:
290 err_invalid_refcount:
291     vmm_obj_slice_release(&channel_ctx->vmm_obj_slice);
292 err_invalid_handle:
293     return apploader_service_send_response(
294             chan, APPLOADER_SECURE_CMD_LOAD_APPLICATION, resp_error, NULL, 0);
295 }
296 
apploader_service_handle_msg(const struct ktipc_port * port,struct handle * chan,void * ctx)297 static int apploader_service_handle_msg(const struct ktipc_port* port,
298                                         struct handle* chan,
299                                         void* ctx) {
300     struct apploader_channel_ctx* channel_ctx = ctx;
301     int rc;
302     struct apploader_secure_req req;
303     rc = ktipc_recv(chan, sizeof(req.hdr), &req, sizeof(req));
304     if (rc < 0) {
305         TRACEF("%s: failed (%d) to read apploader request\n", __func__, rc);
306         return rc;
307     }
308 
309     size_t cmd_len;
310     switch (req.hdr.cmd) {
311     case APPLOADER_SECURE_CMD_GET_MEMORY:
312         /* Check the message length */
313         cmd_len = sizeof(req.hdr) + sizeof(req.get_memory_req);
314         if (rc != (int)cmd_len) {
315             TRACEF("%s: expected to read %zu bytes, got %d\n", __func__,
316                    cmd_len, rc);
317             rc = apploader_service_send_response(
318                     chan, req.hdr.cmd, APPLOADER_ERR_INVALID_CMD, NULL, 0);
319             break;
320         }
321 
322         rc = apploader_service_handle_cmd_get_memory(chan, channel_ctx,
323                                                      &req.get_memory_req);
324         break;
325 
326     case APPLOADER_SECURE_CMD_LOAD_APPLICATION:
327         /* Check the message length */
328         cmd_len = sizeof(req.hdr) + sizeof(req.load_app_req);
329         if (rc != (int)cmd_len) {
330             TRACEF("%s: expected to read %zu bytes, got %d\n", __func__,
331                    cmd_len, rc);
332             rc = apploader_service_send_response(
333                     chan, req.hdr.cmd, APPLOADER_ERR_INVALID_CMD, NULL, 0);
334             break;
335         }
336 
337         rc = apploader_service_handle_cmd_load_application(chan, channel_ctx,
338                                                            &req.load_app_req);
339         break;
340 
341     default:
342         TRACEF("%s: received unknown apploader service command: %" PRIu32 "\n",
343                __func__, req.hdr.cmd);
344         rc = apploader_service_send_response(
345                 chan, req.hdr.cmd, APPLOADER_ERR_UNKNOWN_CMD, NULL, 0);
346         break;
347     }
348 
349     if (rc < 0) {
350         TRACEF("%s: failed to run command (%d)\n", __func__, rc);
351     }
352 
353     return rc;
354 }
355 
apploader_service_handle_connect(const struct ktipc_port * port,struct handle * chan,const struct uuid * peer,void ** ctx_p)356 static int apploader_service_handle_connect(const struct ktipc_port* port,
357                                             struct handle* chan,
358                                             const struct uuid* peer,
359                                             void** ctx_p) {
360     struct apploader_channel_ctx* channel_ctx = calloc(1, sizeof(*channel_ctx));
361     if (!channel_ctx) {
362         TRACEF("%s: failed to allocate apploader_channel_ctx\n", __func__);
363         return ERR_NO_MEMORY;
364     }
365 
366     vmm_obj_slice_init(&channel_ctx->vmm_obj_slice);
367 
368     *ctx_p = channel_ctx;
369 
370     return NO_ERROR;
371 }
372 
apploader_service_handle_channel_cleanup(void * ctx)373 static void apploader_service_handle_channel_cleanup(void* ctx) {
374     struct apploader_channel_ctx* channel_ctx = ctx;
375 
376     vmm_obj_slice_release(&channel_ctx->vmm_obj_slice);
377     free(channel_ctx);
378 }
379 
380 const static struct ktipc_srv_ops apploader_service_ops = {
381         .on_connect = apploader_service_handle_connect,
382         .on_message = apploader_service_handle_msg,
383         .on_channel_cleanup = apploader_service_handle_channel_cleanup,
384 };
385 
386 const static struct ktipc_port_acl apploader_service_port_acl = {
387         .flags = IPC_PORT_ALLOW_TA_CONNECT,
388         .uuids = apploader_service_uuids,
389         .uuid_num = countof(apploader_service_uuids),
390         .extra_data = NULL,
391 };
392 
393 const static struct ktipc_port apploader_service_port = {
394         .name = APPLOADER_SECURE_PORT,
395         .uuid = &kernel_uuid,
396         .msg_max_size = sizeof(union apploader_longest_secure_msg),
397         .msg_queue_len = 1,
398         .acl = &apploader_service_port_acl,
399         .priv = NULL,
400 };
401 
402 static struct ktipc_server apploader_ktipc_server =
403         KTIPC_SERVER_INITIAL_VALUE(apploader_ktipc_server,
404                                    "apploader_ktipc_server");
405 
apploader_service_init(uint level)406 static void apploader_service_init(uint level) {
407     int rc;
408 
409     rc = ktipc_server_start(&apploader_ktipc_server);
410     if (rc < 0) {
411         panic("Failed (%d) to start apploader server\n", rc);
412     }
413 
414     rc = ktipc_server_add_port(&apploader_ktipc_server, &apploader_service_port,
415                                &apploader_service_ops);
416     if (rc < 0) {
417         panic("Failed (%d) to create apploader port\n", rc);
418     }
419 }
420 
421 LK_INIT_HOOK(apploader, apploader_service_init, LK_INIT_LEVEL_APPS + 1);
422