1 /*
2 * Copyright (c) 2020-2022 The strace developers.
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
8 #include "tests.h"
9
10 #include <fcntl.h>
11 #include <stdio.h>
12 #include <string.h>
13
14 #include <linux/tee.h>
15
16 #include <sys/ioctl.h>
17 #include <sys/stat.h>
18 #include <sys/types.h>
19
20 #include "xlat.h"
21
22 #define NUM_PARAMS 8
23 #define RVAL_EBADF " = -1 EBADF (%m)\n"
24
25 #define UUID_SIZE 16
26
27 #ifndef TEE_IOCTL_SHM_MAPPED
28 # define TEE_IOCTL_SHM_MAPPED 0x1
29 #endif
30 #ifndef TEE_IOCTL_SHM_DMA_BUF
31 # define TEE_IOCTL_SHM_DMA_BUF 0x2
32 #endif
33
34 /* Not in mainline. */
35 struct tee_ioctl_shm_register_fd_data {
36 __s64 fd;
37 __u64 size;
38 __u32 flags;
39 __u8 _pad1[4];
40 __u32 id;
41 __u8 _pad2[4];
42 } ATTRIBUTE_ALIGNED(8);
43
44 #define TEE_IOC_SHM_REGISTER_FD _IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 8, \
45 struct tee_ioctl_shm_register_fd_data)
46
47 typedef struct {
48 uint8_t b[UUID_SIZE];
49 } uuid_t;
50
51 #define UUID_INIT(a_, b_, c_, d0, d1, d2, d3, d4, d5, d6, d7) \
52 { .b = {((a_) >> 24) & 0xff, ((a_) >> 16) & 0xff, \
53 ((a_) >> 8) & 0xff, (a_) & 0xff, \
54 ((b_) >> 8) & 0xff, (b_) & 0xff, \
55 ((c_) >> 8) & 0xff, (c_) & 0xff, \
56 (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7)} }
57
58 #define CHK_NULL(ioctl_) \
59 do { \
60 ioctl(-1, ioctl_, NULL); \
61 printf("ioctl(-1, " #ioctl_ ", NULL)" RVAL_EBADF); \
62 } while (0)
63
64 #define CHK_BUF(ioctl_) \
65 do { \
66 ioctl(-1, ioctl_, &buf_data); \
67 printf("ioctl(-1, " #ioctl_ \
68 ", {buf_len=%llu, buf_ptr=%#llx})" RVAL_EBADF, \
69 (unsigned long long) buf_data.buf_len, \
70 (unsigned long long) buf_data.buf_ptr); \
71 } while (0)
72
73 #define DEFINE_BUF_W_PARAMS(type_, shorthand_) \
74 union { \
75 type_ shorthand_; \
76 struct { \
77 uint8_t type_buf[sizeof(type_)]; \
78 struct tee_ioctl_param params[NUM_PARAMS]; \
79 } data; \
80 } shorthand_ ## _buf
81
82 static const unsigned long one_beef = (unsigned long) 0xcafef00ddeadbeefULL;
83 static const unsigned long two_beef = (unsigned long) 0xbadc0dedbadc0dedULL;
84 static const unsigned long red_beef = (unsigned long) 0xdefacedbeef0beefULL;
85 static const unsigned long blu_beef = (unsigned long) 0xfacefeedcafef00dULL;
86
87 static const uuid_t uuid_beef = UUID_INIT(0xdeadbeef, 0xcafe, 0xc0de,
88 0xba, 0xdc, 0x0d, 0xed,
89 0xfa, 0xce, 0xfe, 0xed);
90
91 static void
92 fill_params(struct tee_ioctl_param *params)
93 {
94 for (unsigned i = 0; i < NUM_PARAMS; i++) {
95 params[i].a = two_beef;
96 params[i].b = red_beef;
97 params[i].c = blu_beef;
98 }
99 params[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
100 params[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
101 params[2].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT;
102 params[3].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT;
103 params[4].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
104 params[5].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
105 params[6].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT;
106 params[7].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT |
107 TEE_IOCTL_PARAM_ATTR_META;
108 }
109
110 static void
111 print_params(struct tee_ioctl_param *params)
112 {
113 printf("{attr=TEE_IOCTL_PARAM_ATTR_TYPE_NONE}, "
114 "{attr=TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT, a=%#llx, b=%#llx, c=%#llx}, "
115 "{attr=TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT, a=%#llx, b=%#llx, c=%#llx}, "
116 "{attr=TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT, a=%#llx, b=%#llx, c=%#llx}, "
117 "{attr=TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT, shm_offs=%#llx, size=%#llx, shm_id=%llu}, "
118 "{attr=TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT, shm_offs=%#llx, size=%#llx, shm_id=%llu}, "
119 "{attr=TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT, shm_offs=%#llx, size=%#llx, shm_id=%llu}, "
120 "{attr=TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT|TEE_IOCTL_PARAM_ATTR_META, a=%#llx, b=%#llx, c=%#llx}",
121 (unsigned long long) two_beef, (unsigned long long) red_beef,
122 (unsigned long long) blu_beef, (unsigned long long) two_beef,
123 (unsigned long long) red_beef, (unsigned long long) blu_beef,
124 (unsigned long long) two_beef, (unsigned long long) red_beef,
125 (unsigned long long) blu_beef, (unsigned long long) two_beef,
126 (unsigned long long) red_beef, (unsigned long long) blu_beef,
127 (unsigned long long) two_beef, (unsigned long long) red_beef,
128 (unsigned long long) blu_beef, (unsigned long long) two_beef,
129 (unsigned long long) red_beef, (unsigned long long) blu_beef,
130 (unsigned long long) two_beef, (unsigned long long) red_beef,
131 (unsigned long long) blu_beef
132 );
133 }
134
135 int
136 main(void)
137 {
138 gid_t gid;
139
140 struct tee_ioctl_cancel_arg cancel;
141 struct tee_ioctl_shm_alloc_data shm_alloc;
142 struct tee_ioctl_shm_register_data shm_register;
143 struct tee_ioctl_close_session_arg close_session;
144 struct tee_ioctl_shm_register_fd_data shm_register_fd;
145
146 struct tee_ioctl_buf_data buf_data;
147
148 DEFINE_BUF_W_PARAMS(struct tee_ioctl_invoke_arg, invoke);
149 DEFINE_BUF_W_PARAMS(struct tee_iocl_supp_recv_arg, supp_recv);
150 DEFINE_BUF_W_PARAMS(struct tee_iocl_supp_send_arg, supp_send);
151 DEFINE_BUF_W_PARAMS(struct tee_ioctl_open_session_arg, open_session);
152
153 static const char null_path[] = "/dev/null";
154 int fd = open(null_path, O_RDONLY);
155
156 /* NULL as arg */
157 CHK_NULL(TEE_IOC_CANCEL);
158 CHK_NULL(TEE_IOC_INVOKE);
159 CHK_NULL(TEE_IOC_VERSION);
160 CHK_NULL(TEE_IOC_SHM_ALLOC);
161 CHK_NULL(TEE_IOC_SUPPL_RECV);
162 CHK_NULL(TEE_IOC_SUPPL_SEND);
163 CHK_NULL(TEE_IOC_OPEN_SESSION);
164 CHK_NULL(TEE_IOC_SHM_REGISTER);
165 CHK_NULL(TEE_IOC_CLOSE_SESSION);
166
167 /* Valid parameterless calls */
168 ioctl(-1, TEE_IOC_SHM_REGISTER_FD, NULL);
169 printf("ioctl(-1, _IOC(_IOC_READ|_IOC_WRITE, 0xa4, 0x8, 0x20), NULL)"
170 RVAL_EBADF);
171 ioctl(-1, _IOC(_IOC_NONE, 0xa4, 0xa, 0), NULL);
172 printf("ioctl(-1, _IOC(_IOC_NONE, 0xa4, 0xa, 0), 0)" RVAL_EBADF);
173
174 cancel.cancel_id = (uint32_t) one_beef;
175 cancel.session = (uint32_t) two_beef;
176 ioctl(-1, TEE_IOC_CANCEL, &cancel);
177 printf("ioctl(-1, TEE_IOC_CANCEL, {cancel_id=%u, session=%#x})" RVAL_EBADF,
178 (uint32_t) one_beef, (uint32_t) two_beef);
179
180 close_session.session = (uint32_t) red_beef;
181 ioctl(-1, TEE_IOC_CLOSE_SESSION, &close_session);
182 printf("ioctl(-1, TEE_IOC_CLOSE_SESSION, {session=%#x})" RVAL_EBADF,
183 (uint32_t) red_beef);
184
185 shm_alloc.size = one_beef;
186 shm_alloc.flags = TEE_IOCTL_SHM_MAPPED | TEE_IOCTL_SHM_DMA_BUF | 0x80;
187 ioctl(-1, TEE_IOC_SHM_ALLOC, &shm_alloc);
188 printf("ioctl(-1, TEE_IOC_SHM_ALLOC, {size=%#llx, "
189 "flags=TEE_IOCTL_SHM_MAPPED|TEE_IOCTL_SHM_DMA_BUF|0x80})" RVAL_EBADF,
190 (unsigned long long) one_beef);
191
192 shm_register.addr = red_beef;
193 shm_register.length = blu_beef;
194 shm_register.flags = TEE_IOCTL_SHM_MAPPED | 0x80;
195 ioctl(-1, TEE_IOC_SHM_REGISTER, &shm_register);
196 printf("ioctl(-1, TEE_IOC_SHM_REGISTER, {addr=%#llx, length=%#llx, "
197 "flags=TEE_IOCTL_SHM_MAPPED|0x80})" RVAL_EBADF,
198 (unsigned long long) red_beef,
199 (unsigned long long) blu_beef);
200
201 if (fd >= 0) {
202 shm_register_fd.fd = fd;
203 shm_register_fd.flags = TEE_IOCTL_SHM_DMA_BUF;
204 ioctl(-1, TEE_IOC_SHM_REGISTER_FD, &shm_register_fd);
205 printf("ioctl(-1, _IOC(_IOC_READ|_IOC_WRITE, 0xa4, 0x8, 0x20), "
206 "{fd=%d, flags=TEE_IOCTL_SHM_DMA_BUF})" RVAL_EBADF, fd);
207 }
208
209 /* Beef in buf_data */
210 buf_data.buf_ptr = one_beef;
211 buf_data.buf_len = two_beef;
212 CHK_BUF(TEE_IOC_INVOKE);
213 CHK_BUF(TEE_IOC_OPEN_SESSION);
214 CHK_BUF(TEE_IOC_SUPPL_RECV);
215 CHK_BUF(TEE_IOC_SUPPL_SEND);
216
217 /* Valid calls with parameters */
218 invoke_buf.invoke.func = (uint32_t) one_beef;
219 invoke_buf.invoke.session = (uint32_t) two_beef;
220 invoke_buf.invoke.cancel_id = (uint32_t) red_beef;
221 invoke_buf.invoke.num_params = NUM_PARAMS;
222 fill_params(invoke_buf.data.params);
223 buf_data.buf_ptr = (uintptr_t) &invoke_buf;
224 buf_data.buf_len = sizeof(invoke_buf);
225 ioctl(-1, TEE_IOC_INVOKE, &buf_data);
226 printf("ioctl(-1, TEE_IOC_INVOKE, {buf_len=%llu, "
227 "buf_ptr={func=%u, session=%#x, cancel_id=%u, "
228 "num_params=%u, params=[",
229 (unsigned long long) buf_data.buf_len,
230 (uint32_t) one_beef, (uint32_t) two_beef,
231 (uint32_t) red_beef, NUM_PARAMS);
232 print_params(invoke_buf.data.params);
233 printf("]}})" RVAL_EBADF);
234
235 open_session_buf.open_session.clnt_login = TEE_IOCTL_LOGIN_PUBLIC;
236 gid = (gid_t) blu_beef;
237 memcpy(&open_session_buf.open_session.clnt_uuid, &gid, sizeof(gid_t));
238 memcpy(&open_session_buf.open_session.uuid, &uuid_beef, UUID_SIZE);
239 open_session_buf.open_session.cancel_id = (uint32_t) red_beef;
240 open_session_buf.open_session.num_params = NUM_PARAMS;
241 fill_params(open_session_buf.data.params);
242 buf_data.buf_ptr = (uintptr_t) &open_session_buf;
243 buf_data.buf_len = sizeof(open_session_buf);
244 ioctl(-1, TEE_IOC_OPEN_SESSION, &buf_data);
245 printf("ioctl(-1, TEE_IOC_OPEN_SESSION, {buf_len=%llu, "
246 "buf_ptr={uuid=deadbeef-cafe-c0de-badc-0dedfacefeed, "
247 "clnt_login=TEE_IOCTL_LOGIN_PUBLIC, "
248 "cancel_id=%u, "
249 "num_params=%u, params=[",
250 (unsigned long long) buf_data.buf_len,
251 (uint32_t) red_beef, NUM_PARAMS);
252 print_params(open_session_buf.data.params);
253 printf("]}})" RVAL_EBADF);
254
255 /* All the login types */
256 open_session_buf.open_session.clnt_login = TEE_IOCTL_LOGIN_USER;
257 ioctl(-1, TEE_IOC_OPEN_SESSION, &buf_data);
258 printf("ioctl(-1, TEE_IOC_OPEN_SESSION, {buf_len=%llu, "
259 "buf_ptr={uuid=deadbeef-cafe-c0de-badc-0dedfacefeed, "
260 "clnt_login=TEE_IOCTL_LOGIN_USER, "
261 "cancel_id=%u, "
262 "num_params=%u, params=[",
263 (unsigned long long) buf_data.buf_len,
264 (uint32_t) red_beef, NUM_PARAMS);
265 print_params(open_session_buf.data.params);
266 printf("]}})" RVAL_EBADF);
267
268 open_session_buf.open_session.clnt_login = TEE_IOCTL_LOGIN_GROUP;
269 ioctl(-1, TEE_IOC_OPEN_SESSION, &buf_data);
270 printf("ioctl(-1, TEE_IOC_OPEN_SESSION, {buf_len=%llu, "
271 "buf_ptr={uuid=deadbeef-cafe-c0de-badc-0dedfacefeed, "
272 "clnt_login=TEE_IOCTL_LOGIN_GROUP, "
273 "clnt_uuid=%u, cancel_id=%u, "
274 "num_params=%u, params=[",
275 (unsigned long long) buf_data.buf_len,
276 gid, (uint32_t) red_beef, NUM_PARAMS);
277 print_params(open_session_buf.data.params);
278 printf("]}})" RVAL_EBADF);
279
280 open_session_buf.open_session.clnt_login = TEE_IOCTL_LOGIN_APPLICATION;
281 ioctl(-1, TEE_IOC_OPEN_SESSION, &buf_data);
282 printf("ioctl(-1, TEE_IOC_OPEN_SESSION, {buf_len=%llu, "
283 "buf_ptr={uuid=deadbeef-cafe-c0de-badc-0dedfacefeed, "
284 "clnt_login=TEE_IOCTL_LOGIN_APPLICATION, "
285 "cancel_id=%u, "
286 "num_params=%u, params=[",
287 (unsigned long long) buf_data.buf_len,
288 (uint32_t) red_beef, NUM_PARAMS);
289 print_params(open_session_buf.data.params);
290 printf("]}})" RVAL_EBADF);
291
292 open_session_buf.open_session.clnt_login = TEE_IOCTL_LOGIN_USER_APPLICATION;
293 ioctl(-1, TEE_IOC_OPEN_SESSION, &buf_data);
294 printf("ioctl(-1, TEE_IOC_OPEN_SESSION, {buf_len=%llu, "
295 "buf_ptr={uuid=deadbeef-cafe-c0de-badc-0dedfacefeed, "
296 "clnt_login=TEE_IOCTL_LOGIN_USER_APPLICATION, "
297 "cancel_id=%u, "
298 "num_params=%u, params=[",
299 (unsigned long long) buf_data.buf_len,
300 (uint32_t) red_beef, NUM_PARAMS);
301 print_params(open_session_buf.data.params);
302 printf("]}})" RVAL_EBADF);
303
304 open_session_buf.open_session.clnt_login = TEE_IOCTL_LOGIN_GROUP_APPLICATION;
305 ioctl(-1, TEE_IOC_OPEN_SESSION, &buf_data);
306 printf("ioctl(-1, TEE_IOC_OPEN_SESSION, {buf_len=%llu, "
307 "buf_ptr={uuid=deadbeef-cafe-c0de-badc-0dedfacefeed, "
308 "clnt_login=TEE_IOCTL_LOGIN_GROUP_APPLICATION, "
309 "clnt_uuid=%u, cancel_id=%u, "
310 "num_params=%u, params=[",
311 (unsigned long long) buf_data.buf_len,
312 gid, (uint32_t) red_beef, NUM_PARAMS);
313 print_params(open_session_buf.data.params);
314 printf("]}})" RVAL_EBADF);
315
316 open_session_buf.open_session.clnt_login = 0xff;
317 ioctl(-1, TEE_IOC_OPEN_SESSION, &buf_data);
318 printf("ioctl(-1, TEE_IOC_OPEN_SESSION, {buf_len=%llu, "
319 "buf_ptr={uuid=deadbeef-cafe-c0de-badc-0dedfacefeed, "
320 "clnt_login=%#x /* TEE_IOCTL_LOGIN_??? */, "
321 "clnt_uuid=[", (unsigned long long) buf_data.buf_len,
322 open_session_buf.open_session.clnt_login);
323 for (unsigned i = 0; i < UUID_SIZE; i++) {
324 if (i > 0)
325 printf(", ");
326 printf("%#x", open_session_buf.open_session.clnt_uuid[i]);
327 }
328 printf("], cancel_id=%u, "
329 "num_params=%u, params=[",
330 (uint32_t) red_beef, NUM_PARAMS);
331 print_params(open_session_buf.data.params);
332 printf("]}})" RVAL_EBADF);
333
334 supp_recv_buf.supp_recv.func = (uint32_t) blu_beef;
335 supp_recv_buf.supp_recv.num_params = NUM_PARAMS;
336 fill_params(supp_recv_buf.data.params);
337 buf_data.buf_ptr = (uintptr_t) &supp_recv_buf;
338 buf_data.buf_len = sizeof(supp_recv_buf);
339 ioctl(-1, TEE_IOC_SUPPL_RECV, &buf_data);
340 printf("ioctl(-1, TEE_IOC_SUPPL_RECV, {buf_len=%llu, "
341 "buf_ptr={func=%u, "
342 "num_params=%u, params=[",
343 (unsigned long long) buf_data.buf_len,
344 (uint32_t) blu_beef, NUM_PARAMS);
345 print_params(supp_recv_buf.data.params);
346 printf("]}})" RVAL_EBADF);
347
348 supp_send_buf.supp_send.num_params = NUM_PARAMS;
349 fill_params(supp_send_buf.data.params);
350 buf_data.buf_ptr = (uintptr_t) &supp_send_buf;
351 buf_data.buf_len = sizeof(supp_send_buf);
352 ioctl(-1, TEE_IOC_SUPPL_SEND, &buf_data);
353 printf("ioctl(-1, TEE_IOC_SUPPL_SEND, {buf_len=%llu, "
354 "buf_ptr={num_params=%u, params=[",
355 (unsigned long long) buf_data.buf_len,
356 NUM_PARAMS);
357 print_params(supp_send_buf.data.params);
358 printf("]}})" RVAL_EBADF);
359
360 /* Valid buf, but unmatching num_params */
361 invoke_buf.invoke.num_params = 0;
362 supp_recv_buf.supp_recv.num_params = 0;
363 supp_send_buf.supp_send.num_params = 0;
364 open_session_buf.open_session.num_params = 0;
365
366 buf_data.buf_ptr = (uintptr_t) &invoke_buf;
367 buf_data.buf_len = sizeof(invoke_buf);
368 CHK_BUF(TEE_IOC_INVOKE);
369 buf_data.buf_ptr = (uintptr_t) &open_session_buf;
370 buf_data.buf_len = sizeof(open_session_buf);
371 CHK_BUF(TEE_IOC_OPEN_SESSION);
372 buf_data.buf_ptr = (uintptr_t) &supp_recv_buf;
373 buf_data.buf_len = sizeof(supp_recv_buf);
374 CHK_BUF(TEE_IOC_SUPPL_RECV);
375 buf_data.buf_ptr = (uintptr_t) &supp_send_buf;
376 buf_data.buf_len = sizeof(supp_send_buf);
377 CHK_BUF(TEE_IOC_SUPPL_SEND);
378
379 invoke_buf.invoke.num_params = NUM_PARAMS;
380 supp_recv_buf.supp_recv.num_params = NUM_PARAMS;
381 supp_send_buf.supp_send.num_params = NUM_PARAMS;
382 open_session_buf.open_session.num_params = NUM_PARAMS;
383
384 /* Invalid buf_len */
385 buf_data.buf_len = 0;
386 CHK_BUF(TEE_IOC_INVOKE);
387 CHK_BUF(TEE_IOC_OPEN_SESSION);
388 CHK_BUF(TEE_IOC_SUPPL_RECV);
389 CHK_BUF(TEE_IOC_SUPPL_SEND);
390
391 buf_data.buf_len = (unsigned long long) -1;
392 CHK_BUF(TEE_IOC_INVOKE);
393 CHK_BUF(TEE_IOC_OPEN_SESSION);
394 CHK_BUF(TEE_IOC_SUPPL_RECV);
395 CHK_BUF(TEE_IOC_SUPPL_SEND);
396
397 /* Valid buf_len, invalid buf_ptr */
398 buf_data.buf_ptr = one_beef;
399 buf_data.buf_len = sizeof(invoke_buf);
400 CHK_BUF(TEE_IOC_INVOKE);
401 buf_data.buf_len = sizeof(open_session_buf);
402 CHK_BUF(TEE_IOC_OPEN_SESSION);
403 buf_data.buf_len = sizeof(supp_recv_buf);
404 CHK_BUF(TEE_IOC_SUPPL_RECV);
405 buf_data.buf_len = sizeof(supp_send_buf);
406 CHK_BUF(TEE_IOC_SUPPL_SEND);
407
408 puts("+++ exited with 0 +++");
409 return 0;
410 }