• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: MIT */
2 #define _POSIX_C_SOURCE 200112L
3 
4 #include "lib.h"
5 #include "syscall.h"
6 #include "liburing.h"
7 #include "int_flags.h"
8 #include "liburing/compat.h"
9 #include "liburing/io_uring.h"
10 #include "liburing/sanitize.h"
11 
do_register(struct io_uring * ring,unsigned int opcode,const void * arg,unsigned int nr_args)12 static inline int do_register(struct io_uring *ring, unsigned int opcode,
13 			      const void *arg, unsigned int nr_args)
14 {
15 	int fd;
16 
17 	liburing_sanitize_address(arg);
18 
19 	if (ring->int_flags & INT_FLAG_REG_REG_RING) {
20 		opcode |= IORING_REGISTER_USE_REGISTERED_RING;
21 		fd = ring->enter_ring_fd;
22 	} else {
23 		fd = ring->ring_fd;
24 	}
25 
26 	return __sys_io_uring_register(fd, opcode, arg, nr_args);
27 }
28 
io_uring_register_buffers_update_tag(struct io_uring * ring,unsigned off,const struct iovec * iovecs,const __u64 * tags,unsigned nr)29 int io_uring_register_buffers_update_tag(struct io_uring *ring, unsigned off,
30 					 const struct iovec *iovecs,
31 					 const __u64 *tags,
32 					 unsigned nr)
33 {
34 	liburing_sanitize_iovecs(iovecs, nr);
35 
36 	struct io_uring_rsrc_update2 up = {
37 		.offset	= off,
38 		.data = (unsigned long)iovecs,
39 		.tags = (unsigned long)tags,
40 		.nr = nr,
41 	};
42 
43 	return do_register(ring, IORING_REGISTER_BUFFERS_UPDATE, &up, sizeof(up));
44 }
45 
io_uring_register_buffers_tags(struct io_uring * ring,const struct iovec * iovecs,const __u64 * tags,unsigned nr)46 int io_uring_register_buffers_tags(struct io_uring *ring,
47 				   const struct iovec *iovecs,
48 				   const __u64 *tags,
49 				   unsigned nr)
50 {
51 	liburing_sanitize_iovecs(iovecs, nr);
52 
53 	struct io_uring_rsrc_register reg = {
54 		.nr = nr,
55 		.data = (unsigned long)iovecs,
56 		.tags = (unsigned long)tags,
57 	};
58 
59 	return do_register(ring, IORING_REGISTER_BUFFERS2, &reg, sizeof(reg));
60 }
61 
io_uring_register_buffers_sparse(struct io_uring * ring,unsigned nr)62 int io_uring_register_buffers_sparse(struct io_uring *ring, unsigned nr)
63 {
64 	struct io_uring_rsrc_register reg = {
65 		.flags = IORING_RSRC_REGISTER_SPARSE,
66 		.nr = nr,
67 	};
68 
69 	return do_register(ring, IORING_REGISTER_BUFFERS2, &reg, sizeof(reg));
70 }
71 
io_uring_register_buffers(struct io_uring * ring,const struct iovec * iovecs,unsigned nr_iovecs)72 int io_uring_register_buffers(struct io_uring *ring, const struct iovec *iovecs,
73 			      unsigned nr_iovecs)
74 {
75 	liburing_sanitize_iovecs(iovecs, nr_iovecs);
76 
77 	return do_register(ring, IORING_REGISTER_BUFFERS, iovecs, nr_iovecs);
78 }
79 
io_uring_unregister_buffers(struct io_uring * ring)80 int io_uring_unregister_buffers(struct io_uring *ring)
81 {
82 	return do_register(ring, IORING_UNREGISTER_BUFFERS, NULL, 0);
83 }
84 
io_uring_register_files_update_tag(struct io_uring * ring,unsigned off,const int * files,const __u64 * tags,unsigned nr_files)85 int io_uring_register_files_update_tag(struct io_uring *ring, unsigned off,
86 					const int *files, const __u64 *tags,
87 					unsigned nr_files)
88 {
89 	liburing_sanitize_address(files);
90 	liburing_sanitize_address(tags);
91 
92 	struct io_uring_rsrc_update2 up = {
93 		.offset	= off,
94 		.data = (unsigned long)files,
95 		.tags = (unsigned long)tags,
96 		.nr = nr_files,
97 	};
98 
99 	return do_register(ring, IORING_REGISTER_FILES_UPDATE2, &up, sizeof(up));
100 }
101 
102 /*
103  * Register an update for an existing file set. The updates will start at
104  * 'off' in the original array, and 'nr_files' is the number of files we'll
105  * update.
106  *
107  * Returns number of files updated on success, -ERROR on failure.
108  */
io_uring_register_files_update(struct io_uring * ring,unsigned off,const int * files,unsigned nr_files)109 int io_uring_register_files_update(struct io_uring *ring, unsigned off,
110 				   const int *files, unsigned nr_files)
111 {
112 	liburing_sanitize_address(files);
113 
114 	struct io_uring_files_update up = {
115 		.offset	= off,
116 		.fds	= (unsigned long) files,
117 	};
118 
119 	return do_register(ring, IORING_REGISTER_FILES_UPDATE, &up, nr_files);
120 }
121 
increase_rlimit_nofile(unsigned nr)122 static int increase_rlimit_nofile(unsigned nr)
123 {
124 	int ret;
125 	struct rlimit rlim;
126 
127 	ret = __sys_getrlimit(RLIMIT_NOFILE, &rlim);
128 	if (ret < 0)
129 		return ret;
130 
131 	if (rlim.rlim_cur < nr) {
132 		rlim.rlim_cur += nr;
133 		__sys_setrlimit(RLIMIT_NOFILE, &rlim);
134 	}
135 
136 	return 0;
137 }
138 
io_uring_register_files_sparse(struct io_uring * ring,unsigned nr)139 int io_uring_register_files_sparse(struct io_uring *ring, unsigned nr)
140 {
141 	struct io_uring_rsrc_register reg = {
142 		.flags = IORING_RSRC_REGISTER_SPARSE,
143 		.nr = nr,
144 	};
145 	int ret, did_increase = 0;
146 
147 	do {
148 		ret = do_register(ring, IORING_REGISTER_FILES2, &reg, sizeof(reg));
149 		if (ret >= 0)
150 			break;
151 		if (ret == -EMFILE && !did_increase) {
152 			did_increase = 1;
153 			increase_rlimit_nofile(nr);
154 			continue;
155 		}
156 		break;
157 	} while (1);
158 
159 	return ret;
160 }
161 
io_uring_register_files_tags(struct io_uring * ring,const int * files,const __u64 * tags,unsigned nr)162 int io_uring_register_files_tags(struct io_uring *ring, const int *files,
163 				 const __u64 *tags, unsigned nr)
164 {
165 	liburing_sanitize_address(files);
166 	liburing_sanitize_address(tags);
167 
168 	struct io_uring_rsrc_register reg = {
169 		.nr = nr,
170 		.data = (unsigned long)files,
171 		.tags = (unsigned long)tags,
172 	};
173 	int ret, did_increase = 0;
174 
175 	do {
176 		ret = do_register(ring, IORING_REGISTER_FILES2, &reg, sizeof(reg));
177 		if (ret >= 0)
178 			break;
179 		if (ret == -EMFILE && !did_increase) {
180 			did_increase = 1;
181 			increase_rlimit_nofile(nr);
182 			continue;
183 		}
184 		break;
185 	} while (1);
186 
187 	return ret;
188 }
189 
io_uring_register_files(struct io_uring * ring,const int * files,unsigned nr_files)190 int io_uring_register_files(struct io_uring *ring, const int *files,
191 			    unsigned nr_files)
192 {
193 	int ret, did_increase = 0;
194 
195 	liburing_sanitize_address(files);
196 
197 	do {
198 		ret = do_register(ring, IORING_REGISTER_FILES, files, nr_files);
199 		if (ret >= 0)
200 			break;
201 		if (ret == -EMFILE && !did_increase) {
202 			did_increase = 1;
203 			increase_rlimit_nofile(nr_files);
204 			continue;
205 		}
206 		break;
207 	} while (1);
208 
209 	return ret;
210 }
211 
io_uring_unregister_files(struct io_uring * ring)212 int io_uring_unregister_files(struct io_uring *ring)
213 {
214 	return do_register(ring, IORING_UNREGISTER_FILES, NULL, 0);
215 }
216 
io_uring_register_eventfd(struct io_uring * ring,int event_fd)217 int io_uring_register_eventfd(struct io_uring *ring, int event_fd)
218 {
219 	return do_register(ring, IORING_REGISTER_EVENTFD, &event_fd, 1);
220 }
221 
io_uring_unregister_eventfd(struct io_uring * ring)222 int io_uring_unregister_eventfd(struct io_uring *ring)
223 {
224 	return do_register(ring, IORING_UNREGISTER_EVENTFD, NULL, 0);
225 }
226 
io_uring_register_eventfd_async(struct io_uring * ring,int event_fd)227 int io_uring_register_eventfd_async(struct io_uring *ring, int event_fd)
228 {
229 	return do_register(ring, IORING_REGISTER_EVENTFD_ASYNC, &event_fd, 1);
230 }
231 
io_uring_register_probe(struct io_uring * ring,struct io_uring_probe * p,unsigned int nr_ops)232 int io_uring_register_probe(struct io_uring *ring, struct io_uring_probe *p,
233 			    unsigned int nr_ops)
234 {
235 	return do_register(ring, IORING_REGISTER_PROBE, p, nr_ops);
236 }
237 
io_uring_register_personality(struct io_uring * ring)238 int io_uring_register_personality(struct io_uring *ring)
239 {
240 	return do_register(ring, IORING_REGISTER_PERSONALITY, NULL, 0);
241 }
242 
io_uring_unregister_personality(struct io_uring * ring,int id)243 int io_uring_unregister_personality(struct io_uring *ring, int id)
244 {
245 	return do_register(ring, IORING_UNREGISTER_PERSONALITY, NULL, id);
246 }
247 
io_uring_register_restrictions(struct io_uring * ring,struct io_uring_restriction * res,unsigned int nr_res)248 int io_uring_register_restrictions(struct io_uring *ring,
249 				   struct io_uring_restriction *res,
250 				   unsigned int nr_res)
251 {
252 	return do_register(ring, IORING_REGISTER_RESTRICTIONS, res, nr_res);
253 }
254 
io_uring_enable_rings(struct io_uring * ring)255 int io_uring_enable_rings(struct io_uring *ring)
256 {
257 	return do_register(ring, IORING_REGISTER_ENABLE_RINGS, NULL, 0);
258 }
259 
io_uring_register_iowq_aff(struct io_uring * ring,size_t cpusz,const cpu_set_t * mask)260 int io_uring_register_iowq_aff(struct io_uring *ring, size_t cpusz,
261 			       const cpu_set_t *mask)
262 {
263 	if (cpusz >= (1U << 31))
264 		return -EINVAL;
265 
266 	return do_register(ring, IORING_REGISTER_IOWQ_AFF, mask, (int) cpusz);
267 }
268 
io_uring_unregister_iowq_aff(struct io_uring * ring)269 int io_uring_unregister_iowq_aff(struct io_uring *ring)
270 {
271 	return do_register(ring, IORING_UNREGISTER_IOWQ_AFF, NULL, 0);
272 }
273 
io_uring_register_iowq_max_workers(struct io_uring * ring,unsigned int * val)274 int io_uring_register_iowq_max_workers(struct io_uring *ring, unsigned int *val)
275 {
276 	return do_register(ring, IORING_REGISTER_IOWQ_MAX_WORKERS, val, 2);
277 }
278 
io_uring_register_ring_fd(struct io_uring * ring)279 int io_uring_register_ring_fd(struct io_uring *ring)
280 {
281 	struct io_uring_rsrc_update up = {
282 		.data = ring->ring_fd,
283 		.offset = -1U,
284 	};
285 	int ret;
286 
287 	if (ring->int_flags & INT_FLAG_REG_RING)
288 		return -EEXIST;
289 
290 	ret = do_register(ring, IORING_REGISTER_RING_FDS, &up, 1);
291 	if (ret == 1) {
292 		ring->enter_ring_fd = up.offset;
293 		ring->int_flags |= INT_FLAG_REG_RING;
294 		if (ring->features & IORING_FEAT_REG_REG_RING) {
295 			ring->int_flags |= INT_FLAG_REG_REG_RING;
296 		}
297 	}
298 	return ret;
299 }
300 
301 
io_uring_unregister_ring_fd(struct io_uring * ring)302 int io_uring_unregister_ring_fd(struct io_uring *ring)
303 {
304 	struct io_uring_rsrc_update up = {
305 		.offset = ring->enter_ring_fd,
306 	};
307 	int ret;
308 
309 	if (!(ring->int_flags & INT_FLAG_REG_RING))
310 		return -EINVAL;
311 
312 	ret = do_register(ring, IORING_UNREGISTER_RING_FDS, &up, 1);
313 	if (ret == 1) {
314 		ring->enter_ring_fd = ring->ring_fd;
315 		ring->int_flags &= ~(INT_FLAG_REG_RING | INT_FLAG_REG_REG_RING);
316 	}
317 	return ret;
318 }
319 
io_uring_close_ring_fd(struct io_uring * ring)320 int io_uring_close_ring_fd(struct io_uring *ring)
321 {
322 	if (!(ring->features & IORING_FEAT_REG_REG_RING))
323 		return -EOPNOTSUPP;
324 	if (!(ring->int_flags & INT_FLAG_REG_RING))
325 		return -EINVAL;
326 	if (ring->ring_fd == -1)
327 		return -EBADF;
328 
329 	__sys_close(ring->ring_fd);
330 	ring->ring_fd = -1;
331 	return 1;
332 }
333 
io_uring_register_buf_ring(struct io_uring * ring,struct io_uring_buf_reg * reg,unsigned int __maybe_unused flags)334 int io_uring_register_buf_ring(struct io_uring *ring,
335 			       struct io_uring_buf_reg *reg,
336 			       unsigned int __maybe_unused flags)
337 {
338 	reg->flags |= flags;
339 	return do_register(ring, IORING_REGISTER_PBUF_RING, reg, 1);
340 }
341 
io_uring_unregister_buf_ring(struct io_uring * ring,int bgid)342 int io_uring_unregister_buf_ring(struct io_uring *ring, int bgid)
343 {
344 	struct io_uring_buf_reg reg = { .bgid = bgid };
345 
346 	return do_register(ring, IORING_UNREGISTER_PBUF_RING, &reg, 1);
347 }
348 
io_uring_buf_ring_head(struct io_uring * ring,int buf_group,uint16_t * head)349 int io_uring_buf_ring_head(struct io_uring *ring, int buf_group, uint16_t *head)
350 {
351 	liburing_sanitize_address(head);
352 
353 	struct io_uring_buf_status buf_status = {
354 		.buf_group	= buf_group,
355 	};
356 	int ret;
357 
358 	ret = do_register(ring, IORING_REGISTER_PBUF_STATUS, &buf_status, 1);
359 	if (ret)
360 		return ret;
361 	*head = buf_status.head;
362 	return 0;
363 }
364 
io_uring_register_sync_cancel(struct io_uring * ring,struct io_uring_sync_cancel_reg * reg)365 int io_uring_register_sync_cancel(struct io_uring *ring,
366 				  struct io_uring_sync_cancel_reg *reg)
367 {
368 	return do_register(ring, IORING_REGISTER_SYNC_CANCEL, reg, 1);
369 }
370 
io_uring_register_file_alloc_range(struct io_uring * ring,unsigned off,unsigned len)371 int io_uring_register_file_alloc_range(struct io_uring *ring,
372 					unsigned off, unsigned len)
373 {
374 	struct io_uring_file_index_range range = {
375 		.off = off,
376 		.len = len
377 	};
378 
379 	return do_register(ring, IORING_REGISTER_FILE_ALLOC_RANGE, &range, 0);
380 }
381 
io_uring_register_napi(struct io_uring * ring,struct io_uring_napi * napi)382 int io_uring_register_napi(struct io_uring *ring, struct io_uring_napi *napi)
383 {
384 	return do_register(ring, IORING_REGISTER_NAPI, napi, 1);
385 }
386 
io_uring_unregister_napi(struct io_uring * ring,struct io_uring_napi * napi)387 int io_uring_unregister_napi(struct io_uring *ring, struct io_uring_napi *napi)
388 {
389 	return do_register(ring, IORING_UNREGISTER_NAPI, napi, 1);
390 }
391 
io_uring_register_clock(struct io_uring * ring,struct io_uring_clock_register * arg)392 int io_uring_register_clock(struct io_uring *ring,
393 			    struct io_uring_clock_register *arg)
394 {
395 	return do_register(ring, IORING_REGISTER_CLOCK, arg, 0);
396 }
397 
io_uring_clone_buffers(struct io_uring * dst,struct io_uring * src)398 int io_uring_clone_buffers(struct io_uring *dst, struct io_uring *src)
399 {
400 	struct io_uring_clone_buffers buf = { .src_fd = src->ring_fd, };
401 
402 	if (src->int_flags & INT_FLAG_REG_REG_RING) {
403 		buf.src_fd = src->enter_ring_fd;
404 		buf.flags = IORING_REGISTER_SRC_REGISTERED;
405 	} else {
406 		buf.src_fd = src->ring_fd;
407 	}
408 
409 	return do_register(dst, IORING_REGISTER_CLONE_BUFFERS, &buf, 1);
410 }
411