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