1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <app_mgmt_port_consts.h>
18 #include <app_mgmt_test.h>
19 #include <assert.h>
20 #include <interface/apploader/apploader.h>
21 #include <lib/system_state/system_state.h>
22 #include <lib/tipc/tipc.h>
23 #include <lib/unittest/unittest.h>
24 #include <stddef.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <sys/auxv.h>
28 #include <sys/mman.h>
29 #include <trusty/memref.h>
30 #include <trusty/time.h>
31 #include <trusty_ipc.h>
32 #include <trusty_unittest.h>
33 #include <uapi/err.h>
34
35 #define TLOG_TAG "app-mgmt-test-client"
36 #define PORT_BASE "com.android.appmgmt-unittest.appmngr"
37
38 /*
39 * These are expected to occur/elapse in passing test cases and as such there is
40 * a trade off between the degree of confidence provided by the tests and the
41 * runtime of the tests.
42 */
43 #define EXPECTED_TIMEOUT_MS 500
44 #define UNEXPECTED_TIMEOUT_MS 60000
45 #define WAIT_FOR_APP_SLEEP_NS 500000000
46
47 /*
48 * These tests makes use of one client TA (this file), 7 test server TAs, and
49 * one malformed (unsigned) TA.
50 *
51 * boot-start-srv:
52 * - Starts at boot
53 * - Creates BOOT_START_PORT
54 * - Never exits
55 * - Does not restart at exit
56 *
57 * dev-only-srv:
58 * - Starts at boot
59 * - Tests that this app is only loadable if the unlocked system state flag is
60 * set and that attempts to load it fails verification otherwise.
61 * - Does not restart at exit
62 *
63 * never-start-srv:
64 * - Should never be started
65 * - Creates NEVER_START_PORT (if ever started i.e. failure case)
66 * - Exits after receiving a connection
67 * - Restarts after exiting
68 *
69 * restart-srv:
70 * - Starts at boot
71 * - Creates RESTART_PORT
72 * - Exits after receiving a connection
73 * - Restarts after exiting
74 *
75 * port-start-srv:
76 * - Doesn't start at boot
77 * - Starts on connections to START_PORT
78 * - Creates START_PORT, CTRL_PORT and SHUTDOWN_PORT
79 * - Exits after receiving a CMD_EXIT command on START_PORT or a connection on
80 * SHUTDOWN_PORT
81 * - Does not restart at exit
82 *
83 * port-start-fail-srv:
84 * - Doesn't start at boot
85 * - Fails to start because it requests almost 4GB heap and stack
86 * - Never runs and thus never exits
87 *
88 * port-waiter-srv:
89 * - Starts at boot
90 * - Waits on the port of another loadable app that has yet to load
91 * - Starts the second app
92 * - Never exists
93 * - Does not restart at exit
94 *
95 * unsigned:
96 * - Tests that loading of malformed app leads to verification failure
97 */
98
port_start_srv_running(void)99 static bool port_start_srv_running(void) {
100 int rc;
101
102 trusty_nanosleep(0, 0, WAIT_FOR_APP_SLEEP_NS);
103 rc = connect(CTRL_PORT, IPC_CONNECT_ASYNC);
104 close((handle_t)rc);
105 return rc >= 0;
106 }
107
chan_send_cmd(handle_t chan,uint8_t cmd)108 static void chan_send_cmd(handle_t chan, uint8_t cmd) {
109 uint8_t rsp;
110 uevent_t uevt;
111
112 if (HasFailure())
113 return;
114
115 ASSERT_EQ(sizeof(cmd), tipc_send1(chan, &cmd, sizeof(cmd)));
116 ASSERT_EQ(NO_ERROR, wait(chan, &uevt, INFINITE_TIME));
117 ASSERT_NE(0, uevt.event & IPC_HANDLE_POLL_MSG);
118 ASSERT_EQ(sizeof(rsp), tipc_recv1(chan, sizeof(rsp), &rsp, sizeof(rsp)));
119 ASSERT_EQ(RSP_OK, rsp);
120
121 test_abort:
122 return;
123 }
124
125 typedef enum {
126 /* Accepted on connect and served by port-start-srv */
127 MAIN_CHAN,
128
129 /* Not accepted on connect. Put on pending list when established */
130 PEND_CHAN,
131
132 /* Not accepted on connect. Put on waiting list when established */
133 WAIT_CHAN,
134
135 CHAN_COUNT,
136 } chan_idx_t;
137
138 typedef struct {
139 handle_t chans[CHAN_COUNT];
140 } AppMgrPortStart_t;
141
send_cmd(AppMgrPortStart_t * state,chan_idx_t idx,uint8_t cmd)142 static void send_cmd(AppMgrPortStart_t* state, chan_idx_t idx, uint8_t cmd) {
143 assert(idx < CHAN_COUNT);
144
145 if (HasFailure())
146 return;
147
148 chan_send_cmd(state->chans[idx], cmd);
149
150 test_abort:
151 return;
152 }
153
establish_unhandled_channel(AppMgrPortStart_t * state,chan_idx_t idx)154 static void establish_unhandled_channel(AppMgrPortStart_t* state,
155 chan_idx_t idx) {
156 int rc;
157 uevent_t uevt;
158 handle_t chan = INVALID_IPC_HANDLE;
159
160 assert(idx < CHAN_COUNT);
161
162 if (HasFailure())
163 return;
164
165 rc = connect(START_PORT, IPC_CONNECT_ASYNC);
166 ASSERT_GE(rc, 0);
167 chan = (handle_t)rc;
168
169 /* Make sure port-start-srv does not accept the connection */
170 ASSERT_EQ(ERR_TIMED_OUT, wait(chan, &uevt, EXPECTED_TIMEOUT_MS));
171
172 state->chans[idx] = chan;
173
174 test_abort:
175 return;
176 }
177
close_channel(AppMgrPortStart_t * state,chan_idx_t idx)178 static void close_channel(AppMgrPortStart_t* state, chan_idx_t idx) {
179 assert(idx < CHAN_COUNT);
180
181 if (HasFailure())
182 return;
183
184 close(state->chans[idx]);
185 state->chans[idx] = INVALID_IPC_HANDLE;
186 }
187
send_exit(AppMgrPortStart_t * state,chan_idx_t idx)188 static void send_exit(AppMgrPortStart_t* state, chan_idx_t idx) {
189 assert(idx < CHAN_COUNT);
190
191 if (HasFailure())
192 return;
193
194 send_cmd(state, idx, CMD_EXIT);
195 close_channel(state, idx);
196 }
197
wait_and_exit(AppMgrPortStart_t * state,chan_idx_t idx)198 static void wait_and_exit(AppMgrPortStart_t* state, chan_idx_t idx) {
199 uevent_t uevt;
200
201 assert(idx < CHAN_COUNT);
202
203 if (HasFailure())
204 return;
205
206 ASSERT_EQ(NO_ERROR, wait(state->chans[idx], &uevt, INFINITE_TIME));
207 ASSERT_NE(0, IPC_HANDLE_POLL_READY & uevt.event);
208
209 send_exit(state, idx);
210
211 test_abort:
212 return;
213 }
214
send_apploader_request(handle_t channel,uint32_t cmd,void * req,size_t req_size,handle_t handle)215 static void send_apploader_request(handle_t channel,
216 uint32_t cmd,
217 void* req,
218 size_t req_size,
219 handle_t handle) {
220 if (HasFailure())
221 return;
222
223 struct apploader_header hdr = {
224 .cmd = cmd,
225 };
226 struct iovec iov[2] = {{&hdr, sizeof(hdr)}, {req, req_size}};
227 ipc_msg_t msg = {
228 .iov = iov,
229 .num_iov = (req && req_size) ? 2 : 1,
230 .handles = &handle,
231 .num_handles = (handle != INVALID_IPC_HANDLE) ? 1 : 0,
232 };
233
234 int rc;
235 rc = send_msg(channel, &msg);
236 ASSERT_EQ(rc, (ssize_t)sizeof(hdr) + (ssize_t)req_size);
237
238 test_abort:;
239 }
240
read_apploader_response(handle_t channel,uint32_t cmd,handle_t * handles,size_t num_handles,ipc_msg_info_t * msg_inf)241 static uint32_t read_apploader_response(handle_t channel,
242 uint32_t cmd,
243 handle_t* handles,
244 size_t num_handles,
245 ipc_msg_info_t* msg_inf) {
246 int rc;
247 struct apploader_resp resp;
248 ASSERT_EQ(msg_inf->len, sizeof(resp));
249
250 struct iovec iov = {
251 .iov_base = (void*)&resp,
252 .iov_len = sizeof(resp),
253 };
254 ipc_msg_t msg = {
255 .iov = &iov,
256 .num_iov = 1,
257 .handles = handles,
258 .num_handles = num_handles,
259 };
260 rc = read_msg(channel, msg_inf->id, 0, &msg);
261 ASSERT_EQ(rc, (ssize_t)sizeof(resp));
262 ASSERT_EQ(resp.hdr.cmd, cmd | APPLOADER_RESP_BIT);
263
264 return resp.error;
265
266 test_abort:
267 return 0;
268 }
269
recv_apploader_response(handle_t channel,uint32_t cmd,handle_t * handles,size_t num_handles)270 static uint32_t recv_apploader_response(handle_t channel,
271 uint32_t cmd,
272 handle_t* handles,
273 size_t num_handles) {
274 int rc;
275 struct uevent event;
276 ipc_msg_info_t msg_inf;
277
278 if (HasFailure())
279 return 0;
280
281 rc = wait(channel, &event, INFINITE_TIME);
282 ASSERT_EQ(rc, NO_ERROR);
283 ASSERT_NE(event.event & IPC_HANDLE_POLL_MSG, 0);
284
285 rc = get_msg(channel, &msg_inf);
286 ASSERT_EQ(rc, NO_ERROR);
287
288 rc = read_apploader_response(channel, cmd, handles, num_handles, &msg_inf);
289 put_msg(channel, msg_inf.id);
290 return rc;
291
292 test_abort:
293 return 0;
294 }
295
load_app(char * app_begin,char * app_end)296 static uint32_t load_app(char* app_begin, char* app_end) {
297 int rc;
298 handle_t chan = INVALID_IPC_HANDLE;
299 handle_t handle = INVALID_IPC_HANDLE;
300
301 rc = connect(APPLOADER_PORT, IPC_CONNECT_WAIT_FOR_PORT);
302 ASSERT_GT(rc, 0);
303 chan = (handle_t)rc;
304
305 uint64_t page_size = getauxval(AT_PAGESZ);
306 ptrdiff_t app_size = app_end - app_begin;
307 size_t aligned_app_size = round_up(app_size, page_size);
308
309 handle = memref_create(app_begin, aligned_app_size, MMAP_FLAG_PROT_READ);
310 ASSERT_GT(handle, 0);
311
312 struct apploader_load_app_req req = {
313 .package_size = app_size,
314 };
315 send_apploader_request(chan, APPLOADER_CMD_LOAD_APPLICATION, &req,
316 sizeof(req), handle);
317 ASSERT_EQ(false, HasFailure());
318
319 uint32_t error;
320 error = recv_apploader_response(chan, APPLOADER_CMD_LOAD_APPLICATION, NULL,
321 0);
322 ASSERT_EQ(false, HasFailure());
323
324 /* Wait for a bit for the app to start properly */
325 if (error == APPLOADER_NO_ERROR) {
326 trusty_nanosleep(0, 0, WAIT_FOR_APP_SLEEP_NS);
327 }
328
329 close(handle);
330 close(chan);
331
332 return error;
333
334 test_abort:
335 if (handle > 0) {
336 close(handle);
337 }
338 close(chan);
339 return 0;
340 }
341
342 extern char boot_start_app_begin[], boot_start_app_end[];
343 extern char never_start_app_begin[], never_start_app_end[];
344 extern char port_start_app_begin[], port_start_app_end[];
345 extern char port_start_fail_app_begin[], port_start_fail_app_end[];
346 extern char restart_app_begin[], restart_app_end[];
347 extern char port_waiter_app_begin[], port_waiter_app_end[];
348 extern char unsigned_app_begin[], unsigned_app_end[];
349 extern char dev_only_app_begin[], dev_only_app_end[];
350
351 /*
352 * Loading an application the a second time should return
353 * APPLOADER_ERR_ALREADY_EXISTS. This test should be the first
354 * in the file to load boot-start-srv so we test both proper
355 * application loading and the second load attempt.
356 */
TEST(AppMgrBoot,DoubleLoad)357 TEST(AppMgrBoot, DoubleLoad) {
358 uint32_t error;
359
360 error = load_app(boot_start_app_begin, boot_start_app_end);
361 ASSERT_EQ(false, HasFailure());
362 ASSERT_EQ(true, error == APPLOADER_NO_ERROR ||
363 error == APPLOADER_ERR_ALREADY_EXISTS);
364 if (error == APPLOADER_ERR_ALREADY_EXISTS) {
365 trusty_unittest_printf("[ WARNING ] boot-start-srv already loaded\n");
366 }
367
368 error = load_app(boot_start_app_begin, boot_start_app_end);
369 ASSERT_EQ(false, HasFailure());
370 ASSERT_EQ(error, APPLOADER_ERR_ALREADY_EXISTS);
371
372 test_abort:;
373 }
374
375 /*
376 * Start an app that waits on the port of another loadable app that has not
377 * been loaded yet, then start the second app. The kernel should correctly wake
378 * up the first app after loading the second.
379 */
TEST(AppMgrWaitForPort,WaitConnectForPort)380 TEST(AppMgrWaitForPort, WaitConnectForPort) {
381 int rc;
382 handle_t chan = INVALID_IPC_HANDLE;
383 struct uevent uevt;
384 uint8_t rsp;
385
386 /*
387 * port-start-srv should not be running
388 * TODO: unload it ourselves when app unloading is supported; until then,
389 * we only allow this test to be run once per boot, and it needs to be the
390 * first one in the file.
391 */
392 static bool skip = false;
393 if (skip) {
394 trusty_unittest_printf(
395 "[ SKIPPED ] Can't run second time without unloading.\n");
396 return;
397 }
398 skip = true;
399 ASSERT_EQ(false, port_start_srv_running());
400
401 /* Load port-waiter-srv */
402 uint32_t load_error = load_app(port_waiter_app_begin, port_waiter_app_end);
403 ASSERT_EQ(false, HasFailure());
404 ASSERT_EQ(true, load_error == APPLOADER_NO_ERROR ||
405 load_error == APPLOADER_ERR_ALREADY_EXISTS);
406
407 /* Load port-start-srv now, which should wake up port-waiter-srv */
408 load_error = load_app(port_start_app_begin, port_start_app_end);
409 ASSERT_EQ(false, HasFailure());
410 ASSERT_EQ(load_error, APPLOADER_NO_ERROR);
411
412 /* Connect to port-waiter-srv */
413 rc = connect(PORT_WAITER_PORT,
414 IPC_CONNECT_ASYNC | IPC_CONNECT_WAIT_FOR_PORT);
415 ASSERT_GE(rc, 0);
416 chan = (handle_t)rc;
417
418 ASSERT_EQ(NO_ERROR, wait(chan, &uevt, UNEXPECTED_TIMEOUT_MS));
419 ASSERT_NE(0, uevt.event & IPC_HANDLE_POLL_READY);
420 if (!(uevt.event & IPC_HANDLE_POLL_MSG)) {
421 ASSERT_EQ(NO_ERROR, wait(chan, &uevt, INFINITE_TIME));
422 ASSERT_NE(0, uevt.event & IPC_HANDLE_POLL_MSG);
423 }
424 ASSERT_EQ(sizeof(rsp), tipc_recv1(chan, sizeof(rsp), &rsp, sizeof(rsp)));
425 ASSERT_EQ(RSP_OK, rsp);
426
427 test_abort:
428 close(chan);
429 }
430
AppMgrPortStart_SetUp(AppMgrPortStart_t * state)431 static void AppMgrPortStart_SetUp(AppMgrPortStart_t* state) {
432 int rc;
433 uevent_t uevt;
434 handle_t chan;
435
436 uint32_t error = load_app(port_start_app_begin, port_start_app_end);
437 ASSERT_EQ(false, HasFailure());
438 ASSERT_EQ(true, error == APPLOADER_NO_ERROR ||
439 error == APPLOADER_ERR_ALREADY_EXISTS);
440
441 for (size_t i = 0; i < CHAN_COUNT; i++) {
442 state->chans[i] = INVALID_IPC_HANDLE;
443 }
444
445 /* Shutdown port-start-srv in case it is running from a previous test */
446 rc = connect(SHUTDOWN_PORT, IPC_CONNECT_ASYNC);
447 if (rc > 0) {
448 /* SHUTDOWN_PORT exists so the srv was running. Wait for it to exit */
449 chan = (handle_t)rc;
450 rc = wait(chan, &uevt, INFINITE_TIME);
451 close(chan);
452 ASSERT_GE(rc, 0);
453 ASSERT_NE(0, uevt.event & IPC_HANDLE_POLL_HUP);
454 }
455
456 /* port-start-srv should not be running */
457 ASSERT_EQ(false, port_start_srv_running());
458
459 /* Start and connect to port-start-srv */
460 rc = connect(START_PORT, 0);
461 ASSERT_GE(rc, 0);
462
463 state->chans[MAIN_CHAN] = (handle_t)rc;
464
465 test_abort:
466 return;
467 }
468
AppMgrPortStart_TearDown(AppMgrPortStart_t * state)469 static void AppMgrPortStart_TearDown(AppMgrPortStart_t* state) {
470 ASSERT_EQ(false, HasFailure());
471
472 /* port-start-srv should not be running at the end of a test */
473 ASSERT_EQ(false, port_start_srv_running());
474
475 for (size_t i = 0; i < CHAN_COUNT; i++) {
476 ASSERT_EQ(INVALID_IPC_HANDLE, state->chans[i]);
477 }
478
479 test_abort:
480 for (size_t i = 0; i < CHAN_COUNT; i++) {
481 close(state->chans[i]);
482 }
483 }
484
485 /* Apps with deferred start should not start at boot */
TEST(AppMgrBoot,BootStartNegative)486 TEST(AppMgrBoot, BootStartNegative) {
487 int rc;
488
489 uint32_t error = load_app(never_start_app_begin, never_start_app_end);
490 ASSERT_EQ(false, HasFailure());
491 ASSERT_EQ(true, error == APPLOADER_NO_ERROR ||
492 error == APPLOADER_ERR_ALREADY_EXISTS);
493
494 /* never-start-srv should not be running */
495 rc = connect(NEVER_START_PORT, IPC_CONNECT_ASYNC);
496 EXPECT_LT(rc, 0);
497 close((handle_t)rc);
498
499 test_abort:;
500 }
501
502 /* Apps without deferred should start at boot */
TEST(AppMgrBoot,BootStartPositive)503 TEST(AppMgrBoot, BootStartPositive) {
504 int rc;
505
506 uint32_t error = load_app(boot_start_app_begin, boot_start_app_end);
507 ASSERT_EQ(false, HasFailure());
508 ASSERT_EQ(true, error == APPLOADER_NO_ERROR ||
509 error == APPLOADER_ERR_ALREADY_EXISTS);
510
511 /* boot-start-srv should be running from boot */
512 rc = connect(BOOT_START_PORT, IPC_CONNECT_ASYNC);
513 EXPECT_GE(rc, 0);
514 close((handle_t)rc);
515
516 test_abort:;
517 }
518
519 /* Apps with automatic restart should restart after exiting */
TEST(AppMgrRestart,AppRestartPositive)520 TEST(AppMgrRestart, AppRestartPositive) {
521 int rc;
522 uevent_t uevt;
523 handle_t chan = INVALID_IPC_HANDLE;
524
525 uint32_t error = load_app(restart_app_begin, restart_app_end);
526 ASSERT_EQ(false, HasFailure());
527 ASSERT_EQ(true, error == APPLOADER_NO_ERROR ||
528 error == APPLOADER_ERR_ALREADY_EXISTS);
529
530 /* restart-srv should be running from boot or a previous restart */
531 rc = connect(RESTART_PORT, IPC_CONNECT_ASYNC | IPC_CONNECT_WAIT_FOR_PORT);
532 ASSERT_GE(rc, 0);
533
534 /* Wait for restart-srv to initiate shutdown */
535 chan = (handle_t)rc;
536 ASSERT_EQ(NO_ERROR, wait(chan, &uevt, INFINITE_TIME));
537 ASSERT_NE(0, IPC_HANDLE_POLL_HUP & uevt.event);
538 close(chan);
539
540 /* restart-srv should eventually restart */
541 rc = connect(RESTART_PORT, IPC_CONNECT_ASYNC | IPC_CONNECT_WAIT_FOR_PORT);
542 ASSERT_GE(rc, 0);
543 chan = (handle_t)rc;
544
545 test_abort:
546 close(chan);
547 }
548
549 /*
550 * Apps without automatic restart should not restart after exiting
551 * Start ports should start an app on connection
552 */
TEST(AppMgrRestart,AppRestartNegativePortStartPositive)553 TEST(AppMgrRestart, AppRestartNegativePortStartPositive) {
554 int rc;
555 handle_t chan = INVALID_IPC_HANDLE;
556
557 uint32_t error = load_app(port_start_app_begin, port_start_app_end);
558 ASSERT_EQ(false, HasFailure());
559 ASSERT_EQ(true, error == APPLOADER_NO_ERROR ||
560 error == APPLOADER_ERR_ALREADY_EXISTS);
561
562 /* Start and connect to port-start-srv */
563 rc = connect(START_PORT, 0);
564 ASSERT_GE(rc, 0);
565 chan = (handle_t)rc;
566
567 /* Shutdown port-start-srv */
568 chan_send_cmd(chan, CMD_EXIT);
569 ASSERT_EQ(false, HasFailure());
570
571 /* port-start-srv should not restart */
572 ASSERT_EQ(false, port_start_srv_running());
573
574 test_abort:
575 close(chan);
576 }
577
578 /* Regular ports should not start an app on connection */
TEST(AppMgrPortStartFail,PortStartFail)579 TEST(AppMgrPortStartFail, PortStartFail) {
580 /*
581 * TODO: If no unloading, on the second run port is already in 'cancelled'
582 * state, so running the test second time makes no sense, just skip it.
583 */
584 static bool skip = false;
585 if (skip) {
586 trusty_unittest_printf(
587 "[ SKIPPED ] Can't run second time without unloading.\n");
588 return;
589 }
590 skip = true;
591
592 int rc;
593 handle_t chan = INVALID_IPC_HANDLE;
594 uevent_t uevt;
595
596 uint32_t error =
597 load_app(port_start_fail_app_begin, port_start_fail_app_end);
598 ASSERT_EQ(false, HasFailure());
599 ASSERT_EQ(true, error == APPLOADER_NO_ERROR ||
600 error == APPLOADER_ERR_ALREADY_EXISTS);
601
602 /*
603 * A connection to START_FAIL_PORT should fail to start the
604 * port-start-fail-srv app, but it will first create a handle we can wait on
605 */
606 rc = connect(START_FAIL_PORT, IPC_CONNECT_ASYNC);
607 ASSERT_GE(rc, 0);
608
609 /* Wait for kernel to shut down channel after failing to start app */
610 chan = (handle_t)rc;
611 ASSERT_EQ(NO_ERROR, wait(chan, &uevt, UNEXPECTED_TIMEOUT_MS));
612 ASSERT_NE(0, IPC_HANDLE_POLL_HUP & uevt.event);
613 close(chan);
614
615 /* Try again to make sure we get ERR_CANCELLED the second time */
616 rc = connect(START_FAIL_PORT, IPC_CONNECT_ASYNC);
617 ASSERT_EQ(ERR_CANCELLED, rc);
618
619 test_abort:;
620 }
621
622 /* Regular ports should not start an app on connection */
TEST(AppMgrPortStartNegative,PortStartNegative)623 TEST(AppMgrPortStartNegative, PortStartNegative) {
624 int rc;
625
626 uint32_t error = load_app(port_start_app_begin, port_start_app_end);
627 ASSERT_EQ(false, HasFailure());
628 ASSERT_EQ(true, error == APPLOADER_NO_ERROR ||
629 error == APPLOADER_ERR_ALREADY_EXISTS);
630
631 /* A connection to CTRL_PORT should not start port-start-srv */
632 rc = connect(CTRL_PORT, IPC_CONNECT_ASYNC);
633 EXPECT_LT(rc, 0);
634 close((handle_t)rc);
635
636 test_abort:;
637 }
638
639 /* Start ports with closed pending connections should not start an app */
TEST_F(AppMgrPortStart,PortStartPendingNegative)640 TEST_F(AppMgrPortStart, PortStartPendingNegative) {
641 /* Create a pending connection */
642 establish_unhandled_channel(_state, PEND_CHAN);
643
644 /* Close the pending connection */
645 close_channel(_state, PEND_CHAN);
646
647 /* Close the main channel and shutdown port-start-srv */
648 send_exit(_state, MAIN_CHAN);
649
650 test_abort:;
651 }
652
653 /* Start ports with pending connections should start an app */
TEST_F(AppMgrPortStart,PortStartPendingPositive)654 TEST_F(AppMgrPortStart, PortStartPendingPositive) {
655 /* Create a pending connection */
656 establish_unhandled_channel(_state, PEND_CHAN);
657
658 /* Close the main channel and shutdown port-start-srv */
659 send_exit(_state, MAIN_CHAN);
660
661 /*
662 * Wait for port-start-srv to restart due to the pending connection and then
663 * shut it down
664 */
665 wait_and_exit(_state, PEND_CHAN);
666 }
667
668 /* Closed connections waiting for a start port should not start an app */
TEST_F(AppMgrPortStart,PortStartWaitingNegative)669 TEST_F(AppMgrPortStart, PortStartWaitingNegative) {
670 /* Make port-start-srv close START_PORT */
671 send_cmd(_state, MAIN_CHAN, CMD_CLOSE_PORT);
672
673 /* Create a waiting connection */
674 establish_unhandled_channel(_state, WAIT_CHAN);
675
676 /* Close the waiting connection */
677 close_channel(_state, WAIT_CHAN);
678
679 /* Close the main channel and shutdown port-start-srv */
680 send_exit(_state, MAIN_CHAN);
681 }
682
683 /* Connections waiting for a start port should start an app */
TEST_F(AppMgrPortStart,PortStartWaitingPositive)684 TEST_F(AppMgrPortStart, PortStartWaitingPositive) {
685 /* Make port-start-srv close START_PORT */
686 send_cmd(_state, MAIN_CHAN, CMD_CLOSE_PORT);
687
688 /* Create a waiting connection */
689 establish_unhandled_channel(_state, WAIT_CHAN);
690
691 /* Close the main channel and shutdown port-start-srv */
692 send_exit(_state, MAIN_CHAN);
693
694 /*
695 * Wait for port-start-srv to restart due to the waiting connection and then
696 * shut it down
697 */
698 wait_and_exit(_state, WAIT_CHAN);
699 }
700
701 /*
702 * Closed waiting connections that were pending on a start port should not start
703 * an app
704 */
TEST_F(AppMgrPortStart,PortStartPendingToWaitingNegative)705 TEST_F(AppMgrPortStart, PortStartPendingToWaitingNegative) {
706 /* Create a pending connection */
707 establish_unhandled_channel(_state, PEND_CHAN);
708
709 /*
710 * Make port-start-srv close START_PORT (the pending connection becomes
711 * waiting)
712 */
713 send_cmd(_state, MAIN_CHAN, CMD_CLOSE_PORT);
714
715 /* Close the waiting connection */
716 close_channel(_state, PEND_CHAN);
717
718 /* Close the main channel and shutdown port-start-srv */
719 send_exit(_state, MAIN_CHAN);
720 }
721
722 /*
723 * Waiting connections that were pending on a start port should start an app
724 */
TEST_F(AppMgrPortStart,PortStartPendingToWaitingPositive)725 TEST_F(AppMgrPortStart, PortStartPendingToWaitingPositive) {
726 /* Create a pending connection */
727 establish_unhandled_channel(_state, PEND_CHAN);
728
729 /*
730 * Make port-start-srv close START_PORT (the pending connection becomes
731 * waiting)
732 */
733 send_cmd(_state, MAIN_CHAN, CMD_CLOSE_PORT);
734
735 /* Close the main channel and shutdown port-start-srv */
736 send_exit(_state, MAIN_CHAN);
737
738 /*
739 * Wait for port-start-srv to restart due to the waiting connection and then
740 * shut it down
741 */
742 wait_and_exit(_state, PEND_CHAN);
743 }
744
745 /*
746 * Start ports with closed pending connections that were waiting for the port
747 * should not start an app
748 */
TEST_F(AppMgrPortStart,PortStartWaitingToPendingNegative)749 TEST_F(AppMgrPortStart, PortStartWaitingToPendingNegative) {
750 /* Make port-start-srv close START_PORT */
751 send_cmd(_state, MAIN_CHAN, CMD_CLOSE_PORT);
752
753 /* Create a waiting connection */
754 establish_unhandled_channel(_state, WAIT_CHAN);
755
756 /*
757 * Make port-start-srv open START_PORT (the waiting connection becomes
758 * pending)
759 */
760 send_cmd(_state, MAIN_CHAN, CMD_OPEN_PORT);
761
762 /* Close the pending connection */
763 close_channel(_state, WAIT_CHAN);
764
765 /* Close the main channel and shutdown port-start-srv */
766 send_exit(_state, MAIN_CHAN);
767 }
768
769 /*
770 * Start ports with pending connections that were waiting for the port should
771 * start an app
772 */
TEST_F(AppMgrPortStart,PortStartWaitingToPendingPositive)773 TEST_F(AppMgrPortStart, PortStartWaitingToPendingPositive) {
774 /* Make port-start-srv close START_PORT */
775 send_cmd(_state, MAIN_CHAN, CMD_CLOSE_PORT);
776
777 /* Create a waiting connection */
778 establish_unhandled_channel(_state, WAIT_CHAN);
779
780 /*
781 * Make port-start-srv open START_PORT (the waiting connection becomes
782 * pending)
783 */
784 send_cmd(_state, MAIN_CHAN, CMD_OPEN_PORT);
785
786 /* Close the main channel and shutdown port-start-srv */
787 send_exit(_state, MAIN_CHAN);
788
789 /*
790 * Wait for port-start-srv to restart due to the pending connection and then
791 * shut it down
792 */
793 wait_and_exit(_state, WAIT_CHAN);
794 }
795
796 /*
797 * Closed connections waiting for a start port with closed pending connections
798 * should not start an app
799 */
TEST_F(AppMgrPortStart,PortStartPendingWaitingNegative)800 TEST_F(AppMgrPortStart, PortStartPendingWaitingNegative) {
801 /* Create a pending connection */
802 establish_unhandled_channel(_state, PEND_CHAN);
803
804 /*
805 * Make port-start-srv close START_PORT (the pending connection becomes
806 * waiting)
807 */
808 send_cmd(_state, MAIN_CHAN, CMD_CLOSE_PORT);
809
810 /* Create a waiting connection */
811 establish_unhandled_channel(_state, WAIT_CHAN);
812
813 /* Close the first waiting connection */
814 close_channel(_state, PEND_CHAN);
815
816 /* Close the second waiting connection */
817 close_channel(_state, WAIT_CHAN);
818
819 /* Close the main channel and shutdown port-start-srv */
820 send_exit(_state, MAIN_CHAN);
821 }
822
823 /*
824 * Connections waiting for a start port with pending connections should start
825 * an app
826 */
TEST_F(AppMgrPortStart,PortStartPendingWaitingPositive)827 TEST_F(AppMgrPortStart, PortStartPendingWaitingPositive) {
828 /* Create a pending connection */
829 establish_unhandled_channel(_state, PEND_CHAN);
830
831 /*
832 * Make port-start-srv close START_PORT (the pending connection becomes
833 * waiting)
834 */
835 send_cmd(_state, MAIN_CHAN, CMD_CLOSE_PORT);
836
837 /* Create a waiting connection */
838 establish_unhandled_channel(_state, WAIT_CHAN);
839
840 /* Close the main channel and shutdown port-start-srv */
841 send_exit(_state, MAIN_CHAN);
842
843 /*
844 * Wait for port-start-srv to restart due to the first waiting connection
845 * and then shut it down
846 */
847 wait_and_exit(_state, PEND_CHAN);
848
849 /*
850 * wait for port-start-srv to restart due to the second waiting connection
851 * and then shut it down
852 */
853 wait_and_exit(_state, WAIT_CHAN);
854 }
855
856 /*
857 * Connections waiting for a start port with closed pending connections should
858 * start an app
859 */
TEST_F(AppMgrPortStart,PortStartPendingClosedWaitingPositive)860 TEST_F(AppMgrPortStart, PortStartPendingClosedWaitingPositive) {
861 /* Create a pending connection */
862 establish_unhandled_channel(_state, PEND_CHAN);
863
864 /*
865 * Make port-start-srv close START_PORT (the pending connection becomes
866 * waiting)
867 */
868 send_cmd(_state, MAIN_CHAN, CMD_CLOSE_PORT);
869
870 /* Create a waiting connection */
871 establish_unhandled_channel(_state, WAIT_CHAN);
872
873 /* Close the first waiting connection */
874 close_channel(_state, PEND_CHAN);
875
876 /* Close the main channel and shutdown port-start-srv */
877 send_exit(_state, MAIN_CHAN);
878
879 /*
880 * wait for port-start-srv to restart due to the second waiting connection
881 * and then shut it down
882 */
883 wait_and_exit(_state, WAIT_CHAN);
884 }
885
886 /*
887 * Start ports with pending connections and with closed connections waiting for
888 * the port should start an app
889 */
TEST_F(AppMgrPortStart,PortStartPendingWaitingClosedPositive)890 TEST_F(AppMgrPortStart, PortStartPendingWaitingClosedPositive) {
891 /* Create a pending connection */
892 establish_unhandled_channel(_state, PEND_CHAN);
893
894 /*
895 * Make port-start-srv close START_PORT (the pending connection becomes
896 * waiting)
897 */
898 send_cmd(_state, MAIN_CHAN, CMD_CLOSE_PORT);
899
900 /* Create a waiting connection */
901 establish_unhandled_channel(_state, WAIT_CHAN);
902
903 /* Close the second waiting connection */
904 close_channel(_state, WAIT_CHAN);
905
906 /* Close the main channel and shutdown port-start-srv */
907 send_exit(_state, MAIN_CHAN);
908
909 /*
910 * wait for port-start-srv to restart due to the first waiting connection
911 * and then shut it down
912 */
913 wait_and_exit(_state, PEND_CHAN);
914 }
915
916 /*
917 * Connecting to an app's start port as it terminating should always restart the
918 * app
919 */
TEST(AppMgrPortStartRacingTerminate,PortStartRacingTerminate)920 TEST(AppMgrPortStartRacingTerminate, PortStartRacingTerminate) {
921 int rc;
922 handle_t chan = INVALID_IPC_HANDLE;
923 uevent_t uevt;
924 uint32_t error = load_app(port_start_app_begin, port_start_app_end);
925 ASSERT_EQ(false, HasFailure());
926 ASSERT_EQ(true, error == APPLOADER_NO_ERROR ||
927 error == APPLOADER_ERR_ALREADY_EXISTS);
928
929 /* Connect to the start port triggering app start */
930 rc = connect(START_PORT, IPC_CONNECT_ASYNC);
931 ASSERT_GE(rc, 0);
932 chan = (handle_t)rc;
933
934 /* Make sure port-start-srv started successfully */
935 ASSERT_EQ(0, wait(chan, &uevt, UNEXPECTED_TIMEOUT_MS));
936 ASSERT_NE(0, IPC_HANDLE_POLL_READY & uevt.event);
937 ASSERT_EQ(true, port_start_srv_running());
938
939 /* Close the main channel and shutdown port-start-srv */
940 chan_send_cmd(chan, CMD_EXIT);
941 ASSERT_EQ(false, HasFailure());
942 close(chan);
943
944 /* Immediately reconnect to the start port triggering app start */
945 rc = connect(START_PORT, IPC_CONNECT_ASYNC);
946 ASSERT_GE(rc, 0);
947 chan = (handle_t)rc;
948
949 /* Make sure port-start-srv started successfully */
950 ASSERT_EQ(0, wait(chan, &uevt, UNEXPECTED_TIMEOUT_MS));
951 ASSERT_NE(0, IPC_HANDLE_POLL_READY & uevt.event);
952 ASSERT_EQ(true, port_start_srv_running());
953
954 /* Close the main channel and shutdown port-start-srv */
955 chan_send_cmd(chan, CMD_EXIT);
956 ASSERT_EQ(false, HasFailure());
957
958 test_abort:
959 close(chan);
960 }
961
962 /* Test loading an unsigned app */
TEST(AppLoader,UnsignedApp)963 TEST(AppLoader, UnsignedApp) {
964 uint32_t error = load_app(unsigned_app_begin, unsigned_app_end);
965 ASSERT_EQ(false, HasFailure());
966 ASSERT_EQ(APPLOADER_ERR_VERIFICATION_FAILED, error);
967
968 test_abort:;
969 }
970
971 /*
972 * Dev apploader keys should only be available when the system state service
973 * indicates that the system is in an unlocked state. This app is signed with
974 * apploader slot 1, which is the dev key and therefore must only load in the
975 * unlocked state.
976 */
TEST(AppMgrBoot,UnlockedDevLoad)977 TEST(AppMgrBoot, UnlockedDevLoad) {
978 uint32_t error = load_app(dev_only_app_begin, dev_only_app_end);
979 ASSERT_EQ(false, HasFailure());
980
981 if (system_state_app_loading_unlocked()) {
982 ASSERT_EQ(true, error == APPLOADER_NO_ERROR ||
983 error == APPLOADER_ERR_ALREADY_EXISTS);
984 } else {
985 EXPECT_EQ(APPLOADER_ERR_VERIFICATION_FAILED, error);
986 }
987
988 test_abort:;
989 }
990
run_appmngr_tests(struct unittest * test)991 static bool run_appmngr_tests(struct unittest* test) {
992 return RUN_ALL_TESTS();
993 }
994
run_appmngr_stress_tests(struct unittest * test)995 static bool run_appmngr_stress_tests(struct unittest* test) {
996 while (RUN_ALL_TESTS()) {
997 }
998
999 return false;
1000 }
1001
main(void)1002 int main(void) {
1003 static struct unittest appmgmt_unittests[] = {
1004 {
1005 .port_name = PORT_BASE,
1006 .run_test = run_appmngr_tests,
1007 },
1008 {
1009 .port_name = PORT_BASE ".stress",
1010 .run_test = run_appmngr_stress_tests,
1011 },
1012 };
1013 struct unittest* unittests[countof(appmgmt_unittests)];
1014
1015 for (size_t i = 0; i < countof(appmgmt_unittests); i++)
1016 unittests[i] = &appmgmt_unittests[i];
1017
1018 return unittest_main(unittests, countof(unittests));
1019 }
1020