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