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