1  // SPDX-License-Identifier: GPL-2.0
2  #include <linux/kernel.h>
3  #include <linux/errno.h>
4  #include <linux/file.h>
5  #include <linux/mm.h>
6  #include <linux/slab.h>
7  #include <linux/nospec.h>
8  #include <linux/io_uring.h>
9  
10  #include <uapi/linux/io_uring.h>
11  
12  #include "io_uring.h"
13  #include "rsrc.h"
14  #include "filetable.h"
15  
io_file_bitmap_get(struct io_ring_ctx * ctx)16  static int io_file_bitmap_get(struct io_ring_ctx *ctx)
17  {
18  	struct io_file_table *table = &ctx->file_table;
19  	unsigned long nr = ctx->file_alloc_end;
20  	int ret;
21  
22  	if (!table->bitmap)
23  		return -ENFILE;
24  
25  	do {
26  		ret = find_next_zero_bit(table->bitmap, nr, table->alloc_hint);
27  		if (ret != nr)
28  			return ret;
29  
30  		if (table->alloc_hint == ctx->file_alloc_start)
31  			break;
32  		nr = table->alloc_hint;
33  		table->alloc_hint = ctx->file_alloc_start;
34  	} while (1);
35  
36  	return -ENFILE;
37  }
38  
io_alloc_file_tables(struct io_file_table * table,unsigned nr_files)39  bool io_alloc_file_tables(struct io_file_table *table, unsigned nr_files)
40  {
41  	table->files = kvcalloc(nr_files, sizeof(table->files[0]),
42  				GFP_KERNEL_ACCOUNT);
43  	if (unlikely(!table->files))
44  		return false;
45  
46  	table->bitmap = bitmap_zalloc(nr_files, GFP_KERNEL_ACCOUNT);
47  	if (unlikely(!table->bitmap)) {
48  		kvfree(table->files);
49  		return false;
50  	}
51  
52  	return true;
53  }
54  
io_free_file_tables(struct io_file_table * table)55  void io_free_file_tables(struct io_file_table *table)
56  {
57  	kvfree(table->files);
58  	bitmap_free(table->bitmap);
59  	table->files = NULL;
60  	table->bitmap = NULL;
61  }
62  
io_install_fixed_file(struct io_ring_ctx * ctx,struct file * file,u32 slot_index)63  static int io_install_fixed_file(struct io_ring_ctx *ctx, struct file *file,
64  				 u32 slot_index)
65  	__must_hold(&req->ctx->uring_lock)
66  {
67  	struct io_fixed_file *file_slot;
68  	int ret;
69  
70  	if (io_is_uring_fops(file))
71  		return -EBADF;
72  	if (!ctx->file_data)
73  		return -ENXIO;
74  	if (slot_index >= ctx->nr_user_files)
75  		return -EINVAL;
76  
77  	slot_index = array_index_nospec(slot_index, ctx->nr_user_files);
78  	file_slot = io_fixed_file_slot(&ctx->file_table, slot_index);
79  
80  	if (file_slot->file_ptr) {
81  		ret = io_queue_rsrc_removal(ctx->file_data, slot_index,
82  					    io_slot_file(file_slot));
83  		if (ret)
84  			return ret;
85  
86  		file_slot->file_ptr = 0;
87  	} else {
88  		io_file_bitmap_set(&ctx->file_table, slot_index);
89  	}
90  
91  	*io_get_tag_slot(ctx->file_data, slot_index) = 0;
92  	io_fixed_file_set(file_slot, file);
93  	return 0;
94  }
95  
__io_fixed_fd_install(struct io_ring_ctx * ctx,struct file * file,unsigned int file_slot)96  int __io_fixed_fd_install(struct io_ring_ctx *ctx, struct file *file,
97  			  unsigned int file_slot)
98  {
99  	bool alloc_slot = file_slot == IORING_FILE_INDEX_ALLOC;
100  	int ret;
101  
102  	if (alloc_slot) {
103  		ret = io_file_bitmap_get(ctx);
104  		if (unlikely(ret < 0))
105  			return ret;
106  		file_slot = ret;
107  	} else {
108  		file_slot--;
109  	}
110  
111  	ret = io_install_fixed_file(ctx, file, file_slot);
112  	if (!ret && alloc_slot)
113  		ret = file_slot;
114  	return ret;
115  }
116  /*
117   * Note when io_fixed_fd_install() returns error value, it will ensure
118   * fput() is called correspondingly.
119   */
io_fixed_fd_install(struct io_kiocb * req,unsigned int issue_flags,struct file * file,unsigned int file_slot)120  int io_fixed_fd_install(struct io_kiocb *req, unsigned int issue_flags,
121  			struct file *file, unsigned int file_slot)
122  {
123  	struct io_ring_ctx *ctx = req->ctx;
124  	int ret;
125  
126  	io_ring_submit_lock(ctx, issue_flags);
127  	ret = __io_fixed_fd_install(ctx, file, file_slot);
128  	io_ring_submit_unlock(ctx, issue_flags);
129  
130  	if (unlikely(ret < 0))
131  		fput(file);
132  	return ret;
133  }
134  
io_fixed_fd_remove(struct io_ring_ctx * ctx,unsigned int offset)135  int io_fixed_fd_remove(struct io_ring_ctx *ctx, unsigned int offset)
136  {
137  	struct io_fixed_file *file_slot;
138  	int ret;
139  
140  	if (unlikely(!ctx->file_data))
141  		return -ENXIO;
142  	if (offset >= ctx->nr_user_files)
143  		return -EINVAL;
144  
145  	offset = array_index_nospec(offset, ctx->nr_user_files);
146  	file_slot = io_fixed_file_slot(&ctx->file_table, offset);
147  	if (!file_slot->file_ptr)
148  		return -EBADF;
149  
150  	ret = io_queue_rsrc_removal(ctx->file_data, offset,
151  				    io_slot_file(file_slot));
152  	if (ret)
153  		return ret;
154  
155  	file_slot->file_ptr = 0;
156  	io_file_bitmap_clear(&ctx->file_table, offset);
157  	return 0;
158  }
159  
io_register_file_alloc_range(struct io_ring_ctx * ctx,struct io_uring_file_index_range __user * arg)160  int io_register_file_alloc_range(struct io_ring_ctx *ctx,
161  				 struct io_uring_file_index_range __user *arg)
162  {
163  	struct io_uring_file_index_range range;
164  	u32 end;
165  
166  	if (copy_from_user(&range, arg, sizeof(range)))
167  		return -EFAULT;
168  	if (check_add_overflow(range.off, range.len, &end))
169  		return -EOVERFLOW;
170  	if (range.resv || end > ctx->nr_user_files)
171  		return -EINVAL;
172  
173  	io_file_table_set_alloc_range(ctx, range.off, range.len);
174  	return 0;
175  }
176