1 /*
2 * Copyright (c) 2022, 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 #include <err.h>
25 #include <ktipc_test.h>
26 #include <lib/ktipc/ktipc.h>
27 #include <lib/unittest/unittest.h>
28 #include <lk/init.h>
29
30 #define TIMEOUT_MSEC 10000
31
32 #define NUM_TEST_CONNECTIONS 100
33 #define NUM_TEST_MESSAGES 50
34
35 static char test_pattern[] = "abcdefghijklmnopqrstuvwxyz!";
36
send_cmd(struct handle * chan,enum ktipc_test_cmd cmd,char * buf,size_t len)37 static void send_cmd(struct handle* chan,
38 enum ktipc_test_cmd cmd,
39 char* buf,
40 size_t len) {
41 struct ktipc_test_req req = {
42 .cmd = cmd,
43 };
44 int rc = ktipc_send(chan, &req, sizeof(req), buf, len);
45 ASSERT_GE(rc, 0);
46 ASSERT_EQ(sizeof(req) + len, (size_t)rc);
47
48 test_abort:;
49 }
50
wait_for_hup(struct handle * chan)51 static void wait_for_hup(struct handle* chan) {
52 int rc;
53 uint32_t event;
54
55 rc = handle_wait(chan, &event, TIMEOUT_MSEC);
56 ASSERT_EQ(NO_ERROR, rc);
57 ASSERT_NE(0, (event & IPC_HANDLE_POLL_READY));
58
59 if (!(event & IPC_HANDLE_POLL_HUP)) {
60 /*
61 * Service hasn't closed the channel yet, wait again.
62 * We should only get READY once, so one extra wait should do it.
63 */
64 rc = handle_wait(chan, &event, TIMEOUT_MSEC);
65 ASSERT_EQ(NO_ERROR, rc);
66 }
67
68 ASSERT_NE(0, (event & IPC_HANDLE_POLL_HUP));
69
70 test_abort:;
71 }
72
73 /*
74 * Test that the service closes the channel on its end in case on_connect()
75 * returns an error. The client should see this as a HUP.
76 */
TEST(ktipctest,connecterr)77 TEST(ktipctest, connecterr) {
78 int rc;
79 struct handle* chan = NULL;
80
81 rc = ipc_port_connect_async(&kernel_uuid, KTIPC_TEST_SRV_PORT ".connecterr",
82 IPC_PORT_PATH_MAX, IPC_CONNECT_WAIT_FOR_PORT,
83 &chan);
84 ASSERT_EQ(NO_ERROR, rc);
85
86 wait_for_hup(chan);
87 ASSERT_EQ(false, HasFailure());
88
89 test_abort:
90 if (chan) {
91 handle_decref(chan);
92 }
93 }
94
95 /* Test connections to ports blocked by UUID */
TEST(ktipctest,blockedport)96 TEST(ktipctest, blockedport) {
97 int rc;
98 struct handle* chan = NULL;
99
100 /*
101 * ipc_port_connect_async() returns NO_ERROR for rejected connections,
102 * even with IPC_CONNECT_WAIT_FOR_PORT. We check for a HUP below instead.
103 */
104 rc = ipc_port_connect_async(&kernel_uuid, KTIPC_TEST_SRV_PORT ".blocked",
105 IPC_PORT_PATH_MAX, IPC_CONNECT_WAIT_FOR_PORT,
106 &chan);
107 ASSERT_EQ(NO_ERROR, rc);
108
109 wait_for_hup(chan);
110 ASSERT_EQ(false, HasFailure());
111
112 test_abort:
113 if (chan) {
114 handle_decref(chan);
115 }
116 }
117
TEST(ktipctest,echo)118 TEST(ktipctest, echo) {
119 int rc;
120 struct handle* chan[NUM_TEST_CONNECTIONS] = {
121 [0 ...(NUM_TEST_CONNECTIONS - 1)] = NULL,
122 };
123 uint32_t event;
124
125 for (size_t i = 0; i < NUM_TEST_CONNECTIONS; i++) {
126 rc = ipc_port_connect_async(&kernel_uuid, KTIPC_TEST_SRV_PORT,
127 IPC_PORT_PATH_MAX,
128 IPC_CONNECT_WAIT_FOR_PORT, &chan[i]);
129 ASSERT_EQ(NO_ERROR, rc);
130
131 rc = handle_wait(chan[i], &event, TIMEOUT_MSEC);
132 ASSERT_EQ(NO_ERROR, rc);
133 ASSERT_NE(0, (event & IPC_HANDLE_POLL_READY));
134 }
135
136 const size_t len = countof(test_pattern);
137 for (size_t i = 0; i < NUM_TEST_CONNECTIONS; i++) {
138 for (size_t j = 0; j < NUM_TEST_MESSAGES; j++) {
139 test_pattern[i % len] = (i + j) & 0xff;
140
141 send_cmd(chan[i], KTIPC_TEST_CMD_ECHO, test_pattern, len);
142 ASSERT_EQ(false, HasFailure());
143
144 rc = handle_wait(chan[i], &event, TIMEOUT_MSEC);
145 ASSERT_EQ(NO_ERROR, rc);
146 ASSERT_NE(0, (event & IPC_HANDLE_POLL_MSG));
147
148 char buf[countof(test_pattern)];
149 rc = ktipc_recv(chan[i], len, buf, len);
150 ASSERT_EQ(len, rc);
151 ASSERT_EQ(0, memcmp(buf, test_pattern, len));
152 }
153 }
154
155 test_abort:
156 for (size_t i = 0; i < NUM_TEST_CONNECTIONS; i++) {
157 if (chan[i]) {
158 handle_decref(chan[i]);
159 }
160 }
161 }
162
163 /* Test that sends and receives 8 buffers at once */
TEST(ktipctest,echo8)164 TEST(ktipctest, echo8) {
165 int rc;
166 struct handle* chan = NULL;
167 uint32_t event;
168
169 rc = ipc_port_connect_async(&kernel_uuid, KTIPC_TEST_SRV_PORT,
170 IPC_PORT_PATH_MAX, IPC_CONNECT_WAIT_FOR_PORT,
171 &chan);
172 ASSERT_EQ(NO_ERROR, rc);
173
174 rc = handle_wait(chan, &event, TIMEOUT_MSEC);
175 ASSERT_EQ(NO_ERROR, rc);
176 ASSERT_NE(0, (event & IPC_HANDLE_POLL_READY));
177
178 /*
179 * Send different parts of the test pattern from various offsets as 8
180 * different buffers so we pass the maximum number of arguments to
181 * ktipc_send().
182 */
183 const size_t len = 4 * 7;
184 struct ktipc_test_req req = {
185 .cmd = KTIPC_TEST_CMD_ECHO,
186 };
187 rc = ktipc_send(chan, &req, sizeof(req), test_pattern, 4, test_pattern + 4,
188 4, test_pattern, 2, test_pattern + 2, 4, test_pattern + 6,
189 6, test_pattern, 6, test_pattern + 8, 2);
190 ASSERT_GE(rc, 0);
191 ASSERT_EQ(sizeof(req) + len, (size_t)rc);
192
193 rc = handle_wait(chan, &event, TIMEOUT_MSEC);
194 ASSERT_EQ(NO_ERROR, rc);
195 ASSERT_NE(0, (event & IPC_HANDLE_POLL_MSG));
196
197 /*
198 * Read the message back into different buffers that add to the same total
199 * length. We split the last 4-byte buffer into two smaller ones so that
200 * we still get 8 buffers in total, so we test ktipc_recv() with the maximum
201 * amount of allowed arguments.
202 */
203 char buf4[6][4];
204 char buf2[2][2];
205 rc = ktipc_recv(chan, len, buf4[0], 4, buf4[1], 4, buf4[2], 4, buf4[3], 4,
206 buf4[4], 4, buf4[5], 4, buf2[0], 2, buf2[1], 2);
207 ASSERT_EQ(len, rc);
208 ASSERT_EQ(0, memcmp(buf4[0], test_pattern + 0, 4));
209 ASSERT_EQ(0, memcmp(buf4[1], test_pattern + 4, 4));
210 ASSERT_EQ(0, memcmp(buf4[2], test_pattern + 0, 4));
211 ASSERT_EQ(0, memcmp(buf4[3], test_pattern + 4, 4));
212 ASSERT_EQ(0, memcmp(buf4[4], test_pattern + 8, 4));
213 ASSERT_EQ(0, memcmp(buf4[5], test_pattern + 0, 4));
214 ASSERT_EQ(0, memcmp(buf2[0], test_pattern + 4, 2));
215 ASSERT_EQ(0, memcmp(buf2[1], test_pattern + 8, 2));
216
217 test_abort:
218 if (chan) {
219 handle_decref(chan);
220 }
221 }
222
TEST(ktipctest,close)223 TEST(ktipctest, close) {
224 int rc;
225 struct handle* chan = NULL;
226 uint32_t start_close_counter, end_close_counter;
227 uint32_t event;
228
229 rc = ipc_port_connect_async(&kernel_uuid, KTIPC_TEST_SRV_PORT,
230 IPC_PORT_PATH_MAX, IPC_CONNECT_WAIT_FOR_PORT,
231 &chan);
232 ASSERT_EQ(NO_ERROR, rc);
233
234 rc = handle_wait(chan, &event, TIMEOUT_MSEC);
235 ASSERT_EQ(NO_ERROR, rc);
236 ASSERT_NE(0, (event & IPC_HANDLE_POLL_READY));
237
238 send_cmd(chan, KTIPC_TEST_CMD_READ_CLOSE_COUNTER, NULL, 0);
239 ASSERT_EQ(false, HasFailure());
240
241 rc = handle_wait(chan, &event, TIMEOUT_MSEC);
242 ASSERT_EQ(NO_ERROR, rc);
243 ASSERT_NE(0, (event & IPC_HANDLE_POLL_MSG));
244
245 rc = ktipc_recv(chan, sizeof(start_close_counter), &start_close_counter,
246 sizeof(start_close_counter));
247 ASSERT_EQ(sizeof(start_close_counter), rc);
248
249 /* Close the first channel */
250 handle_decref(chan);
251 chan = NULL;
252
253 /* Now open a new channel and ask the server to close it */
254 rc = ipc_port_connect_async(&kernel_uuid, KTIPC_TEST_SRV_PORT,
255 IPC_PORT_PATH_MAX, IPC_CONNECT_WAIT_FOR_PORT,
256 &chan);
257 ASSERT_EQ(NO_ERROR, rc);
258
259 rc = handle_wait(chan, &event, TIMEOUT_MSEC);
260 ASSERT_EQ(NO_ERROR, rc);
261 ASSERT_NE(0, (event & IPC_HANDLE_POLL_READY));
262
263 send_cmd(chan, KTIPC_TEST_CMD_CLOSE, NULL, 0);
264 ASSERT_EQ(false, HasFailure());
265
266 rc = handle_wait(chan, &event, TIMEOUT_MSEC);
267 ASSERT_EQ(NO_ERROR, rc);
268 ASSERT_NE(0, (event & IPC_HANDLE_POLL_HUP));
269
270 handle_decref(chan);
271 chan = NULL;
272
273 /* Read the close counter again; it should be 2 higher than the previous */
274 rc = ipc_port_connect_async(&kernel_uuid, KTIPC_TEST_SRV_PORT,
275 IPC_PORT_PATH_MAX, IPC_CONNECT_WAIT_FOR_PORT,
276 &chan);
277 ASSERT_EQ(NO_ERROR, rc);
278
279 rc = handle_wait(chan, &event, TIMEOUT_MSEC);
280 ASSERT_EQ(NO_ERROR, rc);
281 ASSERT_NE(0, (event & IPC_HANDLE_POLL_READY));
282
283 send_cmd(chan, KTIPC_TEST_CMD_READ_CLOSE_COUNTER, NULL, 0);
284 ASSERT_EQ(false, HasFailure());
285
286 rc = handle_wait(chan, &event, TIMEOUT_MSEC);
287 ASSERT_EQ(NO_ERROR, rc);
288 ASSERT_NE(0, (event & IPC_HANDLE_POLL_MSG));
289
290 rc = ktipc_recv(chan, sizeof(end_close_counter), &end_close_counter,
291 sizeof(end_close_counter));
292 ASSERT_EQ(sizeof(end_close_counter), rc);
293 ASSERT_EQ(start_close_counter + 2, end_close_counter);
294
295 test_abort:
296 if (chan) {
297 handle_decref(chan);
298 }
299 }
300
TEST(ktipctest,blockedsend)301 TEST(ktipctest, blockedsend) {
302 int rc;
303 struct handle* chan = NULL;
304 uint32_t event;
305
306 rc = ipc_port_connect_async(&kernel_uuid, KTIPC_TEST_SRV_PORT,
307 IPC_PORT_PATH_MAX, IPC_CONNECT_WAIT_FOR_PORT,
308 &chan);
309 ASSERT_EQ(NO_ERROR, rc);
310
311 rc = handle_wait(chan, &event, TIMEOUT_MSEC);
312 ASSERT_EQ(NO_ERROR, rc);
313 ASSERT_NE(0, (event & IPC_HANDLE_POLL_READY));
314
315 /* Send the message twice, second one should get queued */
316 const size_t len = countof(test_pattern);
317 send_cmd(chan, KTIPC_TEST_CMD_ECHO, test_pattern, len);
318 ASSERT_EQ(false, HasFailure());
319
320 rc = handle_wait(chan, &event, TIMEOUT_MSEC);
321 ASSERT_EQ(NO_ERROR, rc);
322 ASSERT_NE(0, (event & IPC_HANDLE_POLL_MSG));
323
324 /*
325 * Send the second message before reading the first reply,
326 * should force the service to queue
327 */
328 send_cmd(chan, KTIPC_TEST_CMD_ECHO, test_pattern, len);
329 ASSERT_EQ(false, HasFailure());
330
331 /* Sleep to give the service a chance to run */
332 thread_sleep(10);
333
334 char buf[countof(test_pattern)];
335 rc = ktipc_recv(chan, len, buf, len);
336 ASSERT_EQ(len, rc);
337 ASSERT_EQ(0, memcmp(buf, test_pattern, len));
338
339 rc = handle_wait(chan, &event, TIMEOUT_MSEC);
340 ASSERT_EQ(NO_ERROR, rc);
341 ASSERT_NE(0, (event & IPC_HANDLE_POLL_MSG));
342
343 rc = ktipc_recv(chan, len, buf, len);
344 ASSERT_EQ(len, rc);
345 ASSERT_EQ(0, memcmp(buf, test_pattern, len));
346
347 test_abort:
348 if (chan) {
349 handle_decref(chan);
350 }
351 }
352
353 PORT_TEST(ktipctest, "com.android.kernel.ktipc.test");
354