1 /*
2 * Copyright (C) 2020 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 <uapi/err.h>
18
19 #include <lib/tipc/tipc.h>
20 #include <lib/unittest/unittest.h>
21
22 #include <trusty/time.h>
23 #include <trusty_unittest.h>
24
25 #include <crasher.h>
26 #include <crasher_consts.h>
27
28 #define TLOG_TAG "crash-test"
29
30 #define US2NS(us) ((us) * (1000LL))
31 #define MS2NS(ms) (US2NS(ms) * 1000LL)
32 #define S2NS(s) (MS2NS(s) * 1000LL)
33
crasher_connect(handle_t * chan)34 static int crasher_connect(handle_t* chan) {
35 return tipc_connect(chan, CRASHER_PORT);
36 }
37
crasher_command(handle_t chan,enum crasher_command cmd)38 static int crasher_command(handle_t chan, enum crasher_command cmd) {
39 int ret;
40 struct uevent evt;
41 struct crasher_msg msg = {
42 .cmd = cmd,
43 };
44
45 ret = tipc_send1(chan, &msg, sizeof(msg));
46 ASSERT_GE(ret, 0);
47 ASSERT_EQ(ret, sizeof(msg));
48
49 ret = wait(chan, &evt, INFINITE_TIME);
50 if (ret) {
51 EXPECT_EQ(ret, ERR_CHANNEL_CLOSED);
52 return ret;
53 }
54 if (!(evt.event & IPC_HANDLE_POLL_MSG)) {
55 EXPECT_EQ(evt.event, IPC_HANDLE_POLL_HUP);
56 if (evt.event & IPC_HANDLE_POLL_HUP) {
57 return ERR_CHANNEL_CLOSED;
58 }
59 return ERR_IO;
60 }
61
62 ret = tipc_recv1(chan, sizeof(msg), &msg, sizeof(msg));
63 if (ret < 0) {
64 EXPECT_EQ(ret, ERR_CHANNEL_CLOSED);
65 return ret;
66 }
67 ASSERT_EQ(ret, sizeof(msg));
68
69 return 0;
70
71 test_abort:
72 return ret < 0 ? ret : ERR_IO;
73 }
74
TEST(crash,connect)75 TEST(crash, connect) {
76 handle_t chan = INVALID_IPC_HANDLE;
77 ASSERT_EQ(crasher_connect(&chan), 0);
78 ASSERT_EQ(crasher_command(chan, CRASHER_NOP), 0);
79
80 test_abort:
81 close(chan);
82 }
83
TEST(crash,exit_success)84 TEST(crash, exit_success) {
85 handle_t chan1 = INVALID_IPC_HANDLE;
86 handle_t chan2 = INVALID_IPC_HANDLE;
87 int64_t t1, t2;
88
89 ASSERT_EQ(crasher_connect(&chan1), 0);
90 trusty_gettime(0, &t1);
91 ASSERT_EQ(crasher_command(chan1, CRASHER_EXIT_SUCCESS), ERR_CHANNEL_CLOSED);
92 ASSERT_EQ(crasher_connect(&chan2), 0);
93 trusty_gettime(0, &t2);
94 ASSERT_EQ(crasher_command(chan2, CRASHER_EXIT_SUCCESS), ERR_CHANNEL_CLOSED);
95 ASSERT_LT(t2 - t1, S2NS(1));
96
97 test_abort:
98 close(chan1);
99 close(chan2);
100 }
101
TEST(crash,exit_failure)102 TEST(crash, exit_failure) {
103 handle_t chan1 = INVALID_IPC_HANDLE;
104 handle_t chan2 = INVALID_IPC_HANDLE;
105 int64_t t1, t2;
106
107 ASSERT_EQ(crasher_connect(&chan1), 0);
108 trusty_gettime(0, &t1);
109 ASSERT_EQ(crasher_command(chan1, CRASHER_EXIT_FAILURE), ERR_CHANNEL_CLOSED);
110 ASSERT_EQ(crasher_connect(&chan2), 0);
111 trusty_gettime(0, &t2);
112 ASSERT_EQ(crasher_command(chan2, CRASHER_EXIT_FAILURE), ERR_CHANNEL_CLOSED);
113 ASSERT_GT(t2 - t1, S2NS(1));
114
115 test_abort:
116 close(chan1);
117 close(chan2);
118 }
119
TEST(crash,read_null_ptr)120 TEST(crash, read_null_ptr) {
121 handle_t chan = INVALID_IPC_HANDLE;
122 ASSERT_EQ(crasher_connect(&chan), 0);
123 ASSERT_EQ(crasher_command(chan, CRASHER_READ_NULL_PTR), ERR_CHANNEL_CLOSED);
124
125 test_abort:
126 close(chan);
127 }
128
129 #if __aarch64__
TEST(crash,brk_instruction)130 TEST(crash, brk_instruction) {
131 handle_t chan = INVALID_IPC_HANDLE;
132 ASSERT_EQ(crasher_connect(&chan), 0);
133 ASSERT_EQ(crasher_command(chan, CRASHER_BRK), ERR_CHANNEL_CLOSED);
134
135 test_abort:
136 close(chan);
137 }
138 #endif
139
TEST(crash,read_bad_ptr)140 TEST(crash, read_bad_ptr) {
141 handle_t chan = INVALID_IPC_HANDLE;
142 ASSERT_EQ(crasher_connect(&chan), 0);
143 ASSERT_EQ(crasher_command(chan, CRASHER_READ_BAD_PTR), ERR_CHANNEL_CLOSED);
144
145 test_abort:
146 close(chan);
147 }
148
TEST(crash,write_bad_ptr)149 TEST(crash, write_bad_ptr) {
150 handle_t chan = INVALID_IPC_HANDLE;
151 ASSERT_EQ(crasher_connect(&chan), 0);
152 ASSERT_EQ(crasher_command(chan, CRASHER_WRITE_BAD_PTR), ERR_CHANNEL_CLOSED);
153
154 test_abort:
155 close(chan);
156 }
157
TEST(crash,write_ro_ptr)158 TEST(crash, write_ro_ptr) {
159 handle_t chan = INVALID_IPC_HANDLE;
160 ASSERT_EQ(crasher_connect(&chan), 0);
161 ASSERT_EQ(crasher_command(chan, CRASHER_WRITE_RO_PTR), ERR_CHANNEL_CLOSED);
162
163 test_abort:
164 close(chan);
165 }
166
TEST(crash,exec_rodata)167 TEST(crash, exec_rodata) {
168 handle_t chan = INVALID_IPC_HANDLE;
169 ASSERT_EQ(crasher_connect(&chan), 0);
170 ASSERT_EQ(crasher_command(chan, CRASHER_EXEC_RODATA), ERR_CHANNEL_CLOSED);
171
172 test_abort:
173 close(chan);
174 }
175
TEST(crash,exec_data)176 TEST(crash, exec_data) {
177 handle_t chan = INVALID_IPC_HANDLE;
178 ASSERT_EQ(crasher_connect(&chan), 0);
179 ASSERT_EQ(crasher_command(chan, CRASHER_EXEC_DATA), ERR_CHANNEL_CLOSED);
180
181 test_abort:
182 close(chan);
183 }
184
185 PORT_TEST(crash, "com.android.trusty.crashtest")
186