xref: /aosp_15_r20/external/liburing/test/register-restrictions.c (revision 25da2bea747f3a93b4c30fd9708b0618ef55a0e6)
1 /* SPDX-License-Identifier: MIT */
2 /*
3  * Description: test restrictions
4  *
5  */
6 #include <errno.h>
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <fcntl.h>
12 #include <poll.h>
13 #include <sys/eventfd.h>
14 
15 #include "liburing.h"
16 
17 enum {
18 	TEST_OK,
19 	TEST_SKIPPED,
20 	TEST_FAILED
21 };
22 
test_restrictions_sqe_op(void)23 static int test_restrictions_sqe_op(void)
24 {
25 	struct io_uring_restriction res[2];
26 	struct io_uring_sqe *sqe;
27 	struct io_uring_cqe *cqe;
28 	struct io_uring ring;
29 	int ret, pipe1[2];
30 
31 	uint64_t ptr;
32 	struct iovec vec = {
33 		.iov_base = &ptr,
34 		.iov_len = sizeof(ptr)
35 	};
36 
37 	if (pipe(pipe1) != 0) {
38 		perror("pipe");
39 		return TEST_FAILED;
40 	}
41 
42 	ret = io_uring_queue_init(8, &ring, IORING_SETUP_R_DISABLED);
43 	if (ret) {
44 		if (ret == -EINVAL)
45 			return TEST_SKIPPED;
46 		fprintf(stderr, "ring setup failed: %d\n", ret);
47 		return TEST_FAILED;
48 	}
49 
50 	res[0].opcode = IORING_RESTRICTION_SQE_OP;
51 	res[0].sqe_op = IORING_OP_WRITEV;
52 
53 	res[1].opcode = IORING_RESTRICTION_SQE_OP;
54 	res[1].sqe_op = IORING_OP_WRITE;
55 
56 	ret = io_uring_register_restrictions(&ring, res, 2);
57 	if (ret) {
58 		if (ret == -EINVAL)
59 			return TEST_SKIPPED;
60 
61 		fprintf(stderr, "failed to register restrictions: %d\n", ret);
62 		return TEST_FAILED;
63 	}
64 
65 	ret = io_uring_enable_rings(&ring);
66 	if (ret) {
67 		fprintf(stderr, "ring enabling failed: %d\n", ret);
68 		return TEST_FAILED;
69 	}
70 
71 	sqe = io_uring_get_sqe(&ring);
72 	io_uring_prep_writev(sqe, pipe1[1], &vec, 1, 0);
73 	sqe->user_data = 1;
74 
75 	sqe = io_uring_get_sqe(&ring);
76 	io_uring_prep_readv(sqe, pipe1[0], &vec, 1, 0);
77 	sqe->user_data = 2;
78 
79 	ret = io_uring_submit(&ring);
80 	if (ret != 2) {
81 		fprintf(stderr, "submit: %d\n", ret);
82 		return TEST_FAILED;
83 	}
84 
85 	for (int i = 0; i < 2; i++) {
86 		ret = io_uring_wait_cqe(&ring, &cqe);
87 		if (ret) {
88 			fprintf(stderr, "wait: %d\n", ret);
89 			return TEST_FAILED;
90 		}
91 
92 		switch (cqe->user_data) {
93 		case 1: /* writev */
94 			if (cqe->res != sizeof(ptr)) {
95 				fprintf(stderr, "write res: %d\n", cqe->res);
96 				return TEST_FAILED;
97 			}
98 
99 			break;
100 		case 2: /* readv should be denied */
101 			if (cqe->res != -EACCES) {
102 				fprintf(stderr, "read res: %d\n", cqe->res);
103 				return TEST_FAILED;
104 			}
105 			break;
106 		}
107 		io_uring_cqe_seen(&ring, cqe);
108 	}
109 
110 	io_uring_queue_exit(&ring);
111 	return TEST_OK;
112 }
113 
test_restrictions_register_op(void)114 static int test_restrictions_register_op(void)
115 {
116 	struct io_uring_restriction res[1];
117 	struct io_uring ring;
118 	int ret, pipe1[2];
119 
120 	uint64_t ptr;
121 	struct iovec vec = {
122 		.iov_base = &ptr,
123 		.iov_len = sizeof(ptr)
124 	};
125 
126 	if (pipe(pipe1) != 0) {
127 		perror("pipe");
128 		return TEST_FAILED;
129 	}
130 
131 	ret = io_uring_queue_init(8, &ring, IORING_SETUP_R_DISABLED);
132 	if (ret) {
133 		fprintf(stderr, "ring setup failed: %d\n", ret);
134 		return TEST_FAILED;
135 	}
136 
137 	res[0].opcode = IORING_RESTRICTION_REGISTER_OP;
138 	res[0].register_op = IORING_REGISTER_BUFFERS;
139 
140 	ret = io_uring_register_restrictions(&ring, res, 1);
141 	if (ret) {
142 		if (ret == -EINVAL)
143 			return TEST_SKIPPED;
144 
145 		fprintf(stderr, "failed to register restrictions: %d\n", ret);
146 		return TEST_FAILED;
147 	}
148 
149 	ret = io_uring_enable_rings(&ring);
150 	if (ret) {
151 		fprintf(stderr, "ring enabling failed: %d\n", ret);
152 		return TEST_FAILED;
153 	}
154 
155 	ret = io_uring_register_buffers(&ring, &vec, 1);
156 	if (ret) {
157 		fprintf(stderr, "io_uring_register_buffers failed: %d\n", ret);
158 		return TEST_FAILED;
159 	}
160 
161 	ret = io_uring_register_files(&ring, pipe1, 2);
162 	if (ret != -EACCES) {
163 		fprintf(stderr, "io_uring_register_files ret: %d\n", ret);
164 		return TEST_FAILED;
165 	}
166 
167 	io_uring_queue_exit(&ring);
168 	return TEST_OK;
169 }
170 
test_restrictions_fixed_file(void)171 static int test_restrictions_fixed_file(void)
172 {
173 	struct io_uring_restriction res[4];
174 	struct io_uring_sqe *sqe;
175 	struct io_uring_cqe *cqe;
176 	struct io_uring ring;
177 	int ret, pipe1[2];
178 
179 	uint64_t ptr;
180 	struct iovec vec = {
181 		.iov_base = &ptr,
182 		.iov_len = sizeof(ptr)
183 	};
184 
185 	if (pipe(pipe1) != 0) {
186 		perror("pipe");
187 		return TEST_FAILED;
188 	}
189 
190 	ret = io_uring_queue_init(8, &ring, IORING_SETUP_R_DISABLED);
191 	if (ret) {
192 		fprintf(stderr, "ring setup failed: %d\n", ret);
193 		return TEST_FAILED;
194 	}
195 
196 	res[0].opcode = IORING_RESTRICTION_SQE_OP;
197 	res[0].sqe_op = IORING_OP_WRITEV;
198 
199 	res[1].opcode = IORING_RESTRICTION_SQE_OP;
200 	res[1].sqe_op = IORING_OP_READV;
201 
202 	res[2].opcode = IORING_RESTRICTION_SQE_FLAGS_REQUIRED;
203 	res[2].sqe_flags = IOSQE_FIXED_FILE;
204 
205 	res[3].opcode = IORING_RESTRICTION_REGISTER_OP;
206 	res[3].register_op = IORING_REGISTER_FILES;
207 
208 	ret = io_uring_register_restrictions(&ring, res, 4);
209 	if (ret) {
210 		if (ret == -EINVAL)
211 			return TEST_SKIPPED;
212 
213 		fprintf(stderr, "failed to register restrictions: %d\n", ret);
214 		return TEST_FAILED;
215 	}
216 
217 	ret = io_uring_enable_rings(&ring);
218 	if (ret) {
219 		fprintf(stderr, "ring enabling failed: %d\n", ret);
220 		return TEST_FAILED;
221 	}
222 
223 	ret = io_uring_register_files(&ring, pipe1, 2);
224 	if (ret) {
225 		fprintf(stderr, "io_uring_register_files ret: %d\n", ret);
226 		return TEST_FAILED;
227 	}
228 
229 	sqe = io_uring_get_sqe(&ring);
230 	io_uring_prep_writev(sqe, 1, &vec, 1, 0);
231 	io_uring_sqe_set_flags(sqe, IOSQE_FIXED_FILE);
232 	sqe->user_data = 1;
233 
234 	sqe = io_uring_get_sqe(&ring);
235 	io_uring_prep_readv(sqe, 0, &vec, 1, 0);
236 	io_uring_sqe_set_flags(sqe, IOSQE_FIXED_FILE);
237 	sqe->user_data = 2;
238 
239 	sqe = io_uring_get_sqe(&ring);
240 	io_uring_prep_writev(sqe, pipe1[1], &vec, 1, 0);
241 	sqe->user_data = 3;
242 
243 	ret = io_uring_submit(&ring);
244 	if (ret != 3) {
245 		fprintf(stderr, "submit: %d\n", ret);
246 		return TEST_FAILED;
247 	}
248 
249 	for (int i = 0; i < 3; i++) {
250 		ret = io_uring_wait_cqe(&ring, &cqe);
251 		if (ret) {
252 			fprintf(stderr, "wait: %d\n", ret);
253 			return TEST_FAILED;
254 		}
255 
256 		switch (cqe->user_data) {
257 		case 1: /* writev */
258 			if (cqe->res != sizeof(ptr)) {
259 				fprintf(stderr, "write res: %d\n", cqe->res);
260 				return TEST_FAILED;
261 			}
262 
263 			break;
264 		case 2: /* readv */
265 			if (cqe->res != sizeof(ptr)) {
266 				fprintf(stderr, "read res: %d\n", cqe->res);
267 				return TEST_FAILED;
268 			}
269 			break;
270 		case 3: /* writev without fixed_file should be denied */
271 			if (cqe->res != -EACCES) {
272 				fprintf(stderr, "write res: %d\n", cqe->res);
273 				return TEST_FAILED;
274 			}
275 			break;
276 		}
277 		io_uring_cqe_seen(&ring, cqe);
278 	}
279 
280 	io_uring_queue_exit(&ring);
281 	return TEST_OK;
282 }
283 
test_restrictions_flags(void)284 static int test_restrictions_flags(void)
285 {
286 	struct io_uring_restriction res[3];
287 	struct io_uring_sqe *sqe;
288 	struct io_uring_cqe *cqe;
289 	struct io_uring ring;
290 	int ret, pipe1[2];
291 
292 	uint64_t ptr;
293 	struct iovec vec = {
294 		.iov_base = &ptr,
295 		.iov_len = sizeof(ptr)
296 	};
297 
298 	if (pipe(pipe1) != 0) {
299 		perror("pipe");
300 		return TEST_FAILED;
301 	}
302 
303 	ret = io_uring_queue_init(8, &ring, IORING_SETUP_R_DISABLED);
304 	if (ret) {
305 		fprintf(stderr, "ring setup failed: %d\n", ret);
306 		return TEST_FAILED;
307 	}
308 
309 	res[0].opcode = IORING_RESTRICTION_SQE_OP;
310 	res[0].sqe_op = IORING_OP_WRITEV;
311 
312 	res[1].opcode = IORING_RESTRICTION_SQE_FLAGS_ALLOWED;
313 	res[1].sqe_flags = IOSQE_ASYNC | IOSQE_IO_LINK;
314 
315 	res[2].opcode = IORING_RESTRICTION_SQE_FLAGS_REQUIRED;
316 	res[2].sqe_flags = IOSQE_FIXED_FILE;
317 
318 	ret = io_uring_register_restrictions(&ring, res, 3);
319 	if (ret) {
320 		if (ret == -EINVAL)
321 			return TEST_SKIPPED;
322 
323 		fprintf(stderr, "failed to register restrictions: %d\n", ret);
324 		return TEST_FAILED;
325 	}
326 
327 	ret = io_uring_register_files(&ring, pipe1, 2);
328 	if (ret) {
329 		fprintf(stderr, "io_uring_register_files ret: %d\n", ret);
330 		return TEST_FAILED;
331 	}
332 
333 	ret = io_uring_enable_rings(&ring);
334 	if (ret) {
335 		fprintf(stderr, "ring enabling failed: %d\n", ret);
336 		return TEST_FAILED;
337 	}
338 
339 	sqe = io_uring_get_sqe(&ring);
340 	io_uring_prep_writev(sqe, 1, &vec, 1, 0);
341 	io_uring_sqe_set_flags(sqe, IOSQE_FIXED_FILE);
342 	sqe->user_data = 1;
343 
344 	sqe = io_uring_get_sqe(&ring);
345 	io_uring_prep_writev(sqe, 1, &vec, 1, 0);
346 	io_uring_sqe_set_flags(sqe, IOSQE_FIXED_FILE | IOSQE_ASYNC);
347 	sqe->user_data = 2;
348 
349 	sqe = io_uring_get_sqe(&ring);
350 	io_uring_prep_writev(sqe, 1, &vec, 1, 0);
351 	io_uring_sqe_set_flags(sqe, IOSQE_FIXED_FILE | IOSQE_IO_LINK);
352 	sqe->user_data = 3;
353 
354 	ret = io_uring_submit(&ring);
355 	if (ret != 3) {
356 		fprintf(stderr, "submit: %d\n", ret);
357 		return TEST_FAILED;
358 	}
359 
360 	sqe = io_uring_get_sqe(&ring);
361 	io_uring_prep_writev(sqe, 1, &vec, 1, 0);
362 	io_uring_sqe_set_flags(sqe, IOSQE_FIXED_FILE | IOSQE_IO_DRAIN);
363 	sqe->user_data = 4;
364 
365 	ret = io_uring_submit(&ring);
366 	if (ret != 1) {
367 		fprintf(stderr, "submit: %d\n", ret);
368 		return TEST_FAILED;
369 	}
370 
371 	sqe = io_uring_get_sqe(&ring);
372 	io_uring_prep_writev(sqe, pipe1[1], &vec, 1, 0);
373 	io_uring_sqe_set_flags(sqe, IOSQE_IO_DRAIN);
374 	sqe->user_data = 5;
375 
376 	ret = io_uring_submit(&ring);
377 	if (ret != 1) {
378 		fprintf(stderr, "submit: %d\n", ret);
379 		return TEST_FAILED;
380 	}
381 
382 	sqe = io_uring_get_sqe(&ring);
383 	io_uring_prep_writev(sqe, pipe1[1], &vec, 1, 0);
384 	io_uring_sqe_set_flags(sqe, IOSQE_ASYNC);
385 	sqe->user_data = 6;
386 
387 	ret = io_uring_submit(&ring);
388 	if (ret != 1) {
389 		fprintf(stderr, "submit: %d\n", ret);
390 		return TEST_FAILED;
391 	}
392 
393 	sqe = io_uring_get_sqe(&ring);
394 	io_uring_prep_writev(sqe, pipe1[1], &vec, 1, 0);
395 	sqe->user_data = 7;
396 
397 	ret = io_uring_submit(&ring);
398 	if (ret != 1) {
399 		fprintf(stderr, "submit: %d\n", ret);
400 		return TEST_FAILED;
401 	}
402 
403 	for (int i = 0; i < 7; i++) {
404 		ret = io_uring_wait_cqe(&ring, &cqe);
405 		if (ret) {
406 			fprintf(stderr, "wait: %d\n", ret);
407 			return TEST_FAILED;
408 		}
409 
410 		switch (cqe->user_data) {
411 		case 1: /* writev - flags = IOSQE_FIXED_FILE */
412 		case 2: /* writev - flags = IOSQE_FIXED_FILE | IOSQE_ASYNC */
413 		case 3: /* writev - flags = IOSQE_FIXED_FILE | IOSQE_IO_LINK */
414 			if (cqe->res != sizeof(ptr)) {
415 				fprintf(stderr, "write res: %d user_data %" PRIu64 "\n",
416 					cqe->res, (uint64_t) cqe->user_data);
417 				return TEST_FAILED;
418 			}
419 
420 			break;
421 		case 4: /* writev - flags = IOSQE_FIXED_FILE | IOSQE_IO_DRAIN */
422 		case 5: /* writev - flags = IOSQE_IO_DRAIN */
423 		case 6: /* writev - flags = IOSQE_ASYNC */
424 		case 7: /* writev - flags = 0 */
425 			if (cqe->res != -EACCES) {
426 				fprintf(stderr, "write res: %d user_data %" PRIu64 "\n",
427 					cqe->res, (uint64_t) cqe->user_data);
428 				return TEST_FAILED;
429 			}
430 			break;
431 		}
432 		io_uring_cqe_seen(&ring, cqe);
433 	}
434 
435 	io_uring_queue_exit(&ring);
436 	return TEST_OK;
437 }
438 
test_restrictions_empty(void)439 static int test_restrictions_empty(void)
440 {
441 	struct io_uring_restriction res[0];
442 	struct io_uring_sqe *sqe;
443 	struct io_uring_cqe *cqe;
444 	struct io_uring ring;
445 	int ret, pipe1[2];
446 
447 	uint64_t ptr;
448 	struct iovec vec = {
449 		.iov_base = &ptr,
450 		.iov_len = sizeof(ptr)
451 	};
452 
453 	if (pipe(pipe1) != 0) {
454 		perror("pipe");
455 		return TEST_FAILED;
456 	}
457 
458 	ret = io_uring_queue_init(8, &ring, IORING_SETUP_R_DISABLED);
459 	if (ret) {
460 		fprintf(stderr, "ring setup failed: %d\n", ret);
461 		return TEST_FAILED;
462 	}
463 
464 	ret = io_uring_register_restrictions(&ring, res, 0);
465 	if (ret) {
466 		if (ret == -EINVAL)
467 			return TEST_SKIPPED;
468 
469 		fprintf(stderr, "failed to register restrictions: %d\n", ret);
470 		return TEST_FAILED;
471 	}
472 
473 	ret = io_uring_enable_rings(&ring);
474 	if (ret) {
475 		fprintf(stderr, "ring enabling failed: %d\n", ret);
476 		return TEST_FAILED;
477 	}
478 
479 	ret = io_uring_register_buffers(&ring, &vec, 1);
480 	if (ret != -EACCES) {
481 		fprintf(stderr, "io_uring_register_buffers ret: %d\n", ret);
482 		return TEST_FAILED;
483 	}
484 
485 	ret = io_uring_register_files(&ring, pipe1, 2);
486 	if (ret != -EACCES) {
487 		fprintf(stderr, "io_uring_register_files ret: %d\n", ret);
488 		return TEST_FAILED;
489 	}
490 
491 	sqe = io_uring_get_sqe(&ring);
492 	io_uring_prep_writev(sqe, pipe1[1], &vec, 1, 0);
493 
494 	ret = io_uring_submit(&ring);
495 	if (ret != 1) {
496 		fprintf(stderr, "submit: %d\n", ret);
497 		return TEST_FAILED;
498 	}
499 
500 	ret = io_uring_wait_cqe(&ring, &cqe);
501 	if (ret) {
502 		fprintf(stderr, "wait: %d\n", ret);
503 		return TEST_FAILED;
504 	}
505 
506 	if (cqe->res != -EACCES) {
507 		fprintf(stderr, "write res: %d\n", cqe->res);
508 		return TEST_FAILED;
509 	}
510 
511 	io_uring_cqe_seen(&ring, cqe);
512 
513 	io_uring_queue_exit(&ring);
514 	return TEST_OK;
515 }
516 
test_restrictions_rings_not_disabled(void)517 static int test_restrictions_rings_not_disabled(void)
518 {
519 	struct io_uring_restriction res[1];
520 	struct io_uring ring;
521 	int ret;
522 
523 	ret = io_uring_queue_init(8, &ring, 0);
524 	if (ret) {
525 		fprintf(stderr, "ring setup failed: %d\n", ret);
526 		return TEST_FAILED;
527 	}
528 
529 	res[0].opcode = IORING_RESTRICTION_SQE_OP;
530 	res[0].sqe_op = IORING_OP_WRITEV;
531 
532 	ret = io_uring_register_restrictions(&ring, res, 1);
533 	if (ret != -EBADFD) {
534 		fprintf(stderr, "io_uring_register_restrictions ret: %d\n",
535 			ret);
536 		return TEST_FAILED;
537 	}
538 
539 	io_uring_queue_exit(&ring);
540 	return TEST_OK;
541 }
542 
test_restrictions_rings_disabled(void)543 static int test_restrictions_rings_disabled(void)
544 {
545 	struct io_uring_sqe *sqe;
546 	struct io_uring ring;
547 	int ret;
548 
549 	ret = io_uring_queue_init(8, &ring, IORING_SETUP_R_DISABLED);
550 	if (ret) {
551 		fprintf(stderr, "ring setup failed: %d\n", ret);
552 		return TEST_FAILED;
553 	}
554 
555 	sqe = io_uring_get_sqe(&ring);
556 	io_uring_prep_nop(sqe);
557 
558 	ret = io_uring_submit(&ring);
559 	if (ret != -EBADFD) {
560 		fprintf(stderr, "submit: %d\n", ret);
561 		return TEST_FAILED;
562 	}
563 
564 	io_uring_queue_exit(&ring);
565 	return TEST_OK;
566 }
567 
main(int argc,char * argv[])568 int main(int argc, char *argv[])
569 {
570 	int ret;
571 
572 	if (argc > 1)
573 		return 0;
574 
575 	ret = test_restrictions_sqe_op();
576 	if (ret == TEST_SKIPPED) {
577 		printf("test_restrictions_sqe_op: skipped\n");
578 		return 0;
579 	} else if (ret == TEST_FAILED) {
580 		fprintf(stderr, "test_restrictions_sqe_op failed\n");
581 		return ret;
582 	}
583 
584 	ret = test_restrictions_register_op();
585 	if (ret == TEST_SKIPPED) {
586 		printf("test_restrictions_register_op: skipped\n");
587 	} else if (ret == TEST_FAILED) {
588 		fprintf(stderr, "test_restrictions_register_op failed\n");
589 		return ret;
590 	}
591 
592 	ret = test_restrictions_fixed_file();
593 	if (ret == TEST_SKIPPED) {
594 		printf("test_restrictions_fixed_file: skipped\n");
595 	} else if (ret == TEST_FAILED) {
596 		fprintf(stderr, "test_restrictions_fixed_file failed\n");
597 		return ret;
598 	}
599 
600 	ret = test_restrictions_flags();
601 	if (ret == TEST_SKIPPED) {
602 		printf("test_restrictions_flags: skipped\n");
603 	} else if (ret == TEST_FAILED) {
604 		fprintf(stderr, "test_restrictions_flags failed\n");
605 		return ret;
606 	}
607 
608 	ret = test_restrictions_empty();
609 	if (ret == TEST_SKIPPED) {
610 		printf("test_restrictions_empty: skipped\n");
611 	} else if (ret == TEST_FAILED) {
612 		fprintf(stderr, "test_restrictions_empty failed\n");
613 		return ret;
614 	}
615 
616 	ret = test_restrictions_rings_not_disabled();
617 	if (ret == TEST_SKIPPED) {
618 		printf("test_restrictions_rings_not_disabled: skipped\n");
619 	} else if (ret == TEST_FAILED) {
620 		fprintf(stderr, "test_restrictions_rings_not_disabled failed\n");
621 		return ret;
622 	}
623 
624 	ret = test_restrictions_rings_disabled();
625 	if (ret == TEST_SKIPPED) {
626 		printf("test_restrictions_rings_disabled: skipped\n");
627 	} else if (ret == TEST_FAILED) {
628 		fprintf(stderr, "test_restrictions_rings_disabled failed\n");
629 		return ret;
630 	}
631 
632 	return 0;
633 }
634