• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: MIT */
2 /*
3  * Description: test if personalities work
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 
13 #include "liburing.h"
14 
15 #define FNAME	"/tmp/.tmp.access"
16 #define USE_UID	1000
17 
18 static int no_personality;
19 
open_file(struct io_uring * ring,int cred_id,int with_link)20 static int open_file(struct io_uring *ring, int cred_id, int with_link)
21 {
22 	struct io_uring_cqe *cqe;
23 	struct io_uring_sqe *sqe;
24 	int ret, i, to_submit = 1;
25 
26 	if (with_link) {
27 		sqe = io_uring_get_sqe(ring);
28 		io_uring_prep_nop(sqe);
29 		sqe->flags |= IOSQE_IO_LINK;
30 		sqe->user_data = 1;
31 		to_submit++;
32 	}
33 
34 	sqe = io_uring_get_sqe(ring);
35 	io_uring_prep_openat(sqe, -1, FNAME, O_RDONLY, 0);
36 	sqe->user_data = 2;
37 
38 	if (cred_id != -1)
39 		sqe->personality = cred_id;
40 
41 	ret = io_uring_submit(ring);
42 	if (ret != to_submit) {
43 		fprintf(stderr, "submit got: %d\n", ret);
44 		goto err;
45 	}
46 
47 	for (i = 0; i < to_submit; i++) {
48 		ret = io_uring_wait_cqe(ring, &cqe);
49 		if (ret < 0) {
50 			fprintf(stderr, "wait completion %d\n", ret);
51 			goto err;
52 		}
53 
54 		ret = cqe->res;
55 		io_uring_cqe_seen(ring, cqe);
56 	}
57 err:
58 	return ret;
59 }
60 
test_personality(struct io_uring * ring)61 static int test_personality(struct io_uring *ring)
62 {
63 	int ret, cred_id;
64 
65 	ret = io_uring_register_personality(ring);
66 	if (ret < 0) {
67 		if (ret == -EINVAL) {
68 			fprintf(stdout, "Personalities not supported, skipping\n");
69 			no_personality = 1;
70 			goto out;
71 		}
72 		fprintf(stderr, "register_personality: %d\n", ret);
73 		goto err;
74 	}
75 	cred_id = ret;
76 
77 	/* create file only owner can open */
78 	ret = open(FNAME, O_RDONLY | O_CREAT, 0600);
79 	if (ret < 0) {
80 		perror("open");
81 		goto err;
82 	}
83 	close(ret);
84 
85 	/* verify we can open it */
86 	ret = open_file(ring, -1, 0);
87 	if (ret < 0) {
88 		fprintf(stderr, "current open got: %d\n", ret);
89 		goto err;
90 	}
91 
92 	if (seteuid(USE_UID) < 0) {
93 		fprintf(stdout, "Can't switch to UID %u, skipping\n", USE_UID);
94 		goto out;
95 	}
96 
97 	/* verify we can't open it with current credentials */
98 	ret = open_file(ring, -1, 0);
99 	if (ret != -EACCES) {
100 		fprintf(stderr, "open got: %d\n", ret);
101 		goto err;
102 	}
103 
104 	/* verify we can open with registered credentials */
105 	ret = open_file(ring, cred_id, 0);
106 	if (ret < 0) {
107 		fprintf(stderr, "credential open: %d\n", ret);
108 		goto err;
109 	}
110 	close(ret);
111 
112 	/* verify we can open with registered credentials and as a link */
113 	ret = open_file(ring, cred_id, 1);
114 	if (ret < 0) {
115 		fprintf(stderr, "credential open: %d\n", ret);
116 		goto err;
117 	}
118 
119 	if (seteuid(0))
120 		perror("seteuid");
121 
122 	ret = io_uring_unregister_personality(ring, cred_id);
123 	if (ret) {
124 		fprintf(stderr, "register_personality: %d\n", ret);
125 		goto err;
126 	}
127 
128 out:
129 	unlink(FNAME);
130 	return 0;
131 err:
132 	unlink(FNAME);
133 	return 1;
134 }
135 
test_invalid_personality(struct io_uring * ring)136 static int test_invalid_personality(struct io_uring *ring)
137 {
138 	int ret;
139 
140 	ret = open_file(ring, 2, 0);
141 	if (ret != -EINVAL) {
142 		fprintf(stderr, "invalid personality got: %d\n", ret);
143 		goto err;
144 	}
145 	return 0;
146 err:
147 	return 1;
148 }
149 
test_invalid_unregister(struct io_uring * ring)150 static int test_invalid_unregister(struct io_uring *ring)
151 {
152 	int ret;
153 
154 	ret = io_uring_unregister_personality(ring, 2);
155 	if (ret != -EINVAL) {
156 		fprintf(stderr, "invalid personality unregister got: %d\n", ret);
157 		goto err;
158 	}
159 	return 0;
160 err:
161 	return 1;
162 }
163 
main(int argc,char * argv[])164 int main(int argc, char *argv[])
165 {
166 	struct io_uring ring;
167 	int ret;
168 
169 	if (argc > 1)
170 		return 0;
171 
172 	if (geteuid()) {
173 		fprintf(stderr, "Not root, skipping\n");
174 		return 0;
175 	}
176 
177 	ret = io_uring_queue_init(8, &ring, 0);
178 	if (ret) {
179 		fprintf(stderr, "ring setup failed: %d\n", ret);
180 		return 1;
181 	}
182 
183 	ret = test_personality(&ring);
184 	if (ret) {
185 		fprintf(stderr, "test_personality failed\n");
186 		return ret;
187 	}
188 	if (no_personality)
189 		return 0;
190 
191 	ret = test_invalid_personality(&ring);
192 	if (ret) {
193 		fprintf(stderr, "test_invalid_personality failed\n");
194 		return ret;
195 	}
196 
197 	ret = test_invalid_unregister(&ring);
198 	if (ret) {
199 		fprintf(stderr, "test_invalid_unregister failed\n");
200 		return ret;
201 	}
202 
203 	return 0;
204 }
205