1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/kernel.h>
3 #include <linux/errno.h>
4 #include <linux/fs.h>
5 #include <linux/file.h>
6 #include <linux/mm.h>
7 #include <linux/slab.h>
8 #include <linux/namei.h>
9 #include <linux/io_uring.h>
10
11 #include <uapi/linux/io_uring.h>
12
13 #include "../fs/internal.h"
14
15 #include "io_uring.h"
16 #include "fs.h"
17
18 struct io_rename {
19 struct file *file;
20 int old_dfd;
21 int new_dfd;
22 struct delayed_filename oldpath;
23 struct delayed_filename newpath;
24 int flags;
25 };
26
27 struct io_unlink {
28 struct file *file;
29 int dfd;
30 int flags;
31 struct delayed_filename filename;
32 };
33
34 struct io_mkdir {
35 struct file *file;
36 int dfd;
37 umode_t mode;
38 struct delayed_filename filename;
39 };
40
41 struct io_link {
42 struct file *file;
43 int old_dfd;
44 int new_dfd;
45 struct delayed_filename oldpath;
46 struct delayed_filename newpath;
47 int flags;
48 };
49
io_renameat_prep(struct io_kiocb * req,const struct io_uring_sqe * sqe)50 int io_renameat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
51 {
52 struct io_rename *ren = io_kiocb_to_cmd(req, struct io_rename);
53 const char __user *oldf, *newf;
54 int err;
55
56 if (sqe->buf_index || sqe->splice_fd_in)
57 return -EINVAL;
58 if (unlikely(req->flags & REQ_F_FIXED_FILE))
59 return -EBADF;
60
61 ren->old_dfd = READ_ONCE(sqe->fd);
62 oldf = u64_to_user_ptr(READ_ONCE(sqe->addr));
63 newf = u64_to_user_ptr(READ_ONCE(sqe->addr2));
64 ren->new_dfd = READ_ONCE(sqe->len);
65 ren->flags = READ_ONCE(sqe->rename_flags);
66
67 err = delayed_getname(&ren->oldpath, oldf);
68 if (unlikely(err))
69 return err;
70
71 err = delayed_getname(&ren->newpath, newf);
72 if (unlikely(err)) {
73 dismiss_delayed_filename(&ren->oldpath);
74 return err;
75 }
76
77 req->flags |= REQ_F_NEED_CLEANUP;
78 req->flags |= REQ_F_FORCE_ASYNC;
79 return 0;
80 }
81
io_renameat(struct io_kiocb * req,unsigned int issue_flags)82 int io_renameat(struct io_kiocb *req, unsigned int issue_flags)
83 {
84 struct io_rename *ren = io_kiocb_to_cmd(req, struct io_rename);
85 CLASS(filename_complete_delayed, old)(&ren->oldpath);
86 CLASS(filename_complete_delayed, new)(&ren->newpath);
87 int ret;
88
89 WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
90
91 ret = filename_renameat2(ren->old_dfd, old,
92 ren->new_dfd, new, ren->flags);
93
94 req->flags &= ~REQ_F_NEED_CLEANUP;
95 io_req_set_res(req, ret, 0);
96 return IOU_COMPLETE;
97 }
98
io_renameat_cleanup(struct io_kiocb * req)99 void io_renameat_cleanup(struct io_kiocb *req)
100 {
101 struct io_rename *ren = io_kiocb_to_cmd(req, struct io_rename);
102
103 dismiss_delayed_filename(&ren->oldpath);
104 dismiss_delayed_filename(&ren->newpath);
105 }
106
io_unlinkat_prep(struct io_kiocb * req,const struct io_uring_sqe * sqe)107 int io_unlinkat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
108 {
109 struct io_unlink *un = io_kiocb_to_cmd(req, struct io_unlink);
110 const char __user *fname;
111 int err;
112
113 if (sqe->off || sqe->len || sqe->buf_index || sqe->splice_fd_in ||
114 sqe->addr3 || sqe->__pad2[0])
115 return -EINVAL;
116 if (unlikely(req->flags & REQ_F_FIXED_FILE))
117 return -EBADF;
118
119 un->dfd = READ_ONCE(sqe->fd);
120
121 un->flags = READ_ONCE(sqe->unlink_flags);
122 if (un->flags & ~AT_REMOVEDIR)
123 return -EINVAL;
124
125 fname = u64_to_user_ptr(READ_ONCE(sqe->addr));
126 err = delayed_getname(&un->filename, fname);
127 if (unlikely(err))
128 return err;
129
130 req->flags |= REQ_F_NEED_CLEANUP;
131 req->flags |= REQ_F_FORCE_ASYNC;
132 return 0;
133 }
134
io_unlinkat(struct io_kiocb * req,unsigned int issue_flags)135 int io_unlinkat(struct io_kiocb *req, unsigned int issue_flags)
136 {
137 struct io_unlink *un = io_kiocb_to_cmd(req, struct io_unlink);
138 CLASS(filename_complete_delayed, name)(&un->filename);
139 int ret;
140
141 WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
142
143 if (un->flags & AT_REMOVEDIR)
144 ret = filename_rmdir(un->dfd, name);
145 else
146 ret = filename_unlinkat(un->dfd, name);
147
148 req->flags &= ~REQ_F_NEED_CLEANUP;
149 io_req_set_res(req, ret, 0);
150 return IOU_COMPLETE;
151 }
152
io_unlinkat_cleanup(struct io_kiocb * req)153 void io_unlinkat_cleanup(struct io_kiocb *req)
154 {
155 struct io_unlink *ul = io_kiocb_to_cmd(req, struct io_unlink);
156
157 dismiss_delayed_filename(&ul->filename);
158 }
159
io_mkdirat_prep(struct io_kiocb * req,const struct io_uring_sqe * sqe)160 int io_mkdirat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
161 {
162 struct io_mkdir *mkd = io_kiocb_to_cmd(req, struct io_mkdir);
163 const char __user *fname;
164 int err;
165
166 if (sqe->off || sqe->rw_flags || sqe->buf_index || sqe->splice_fd_in)
167 return -EINVAL;
168 if (unlikely(req->flags & REQ_F_FIXED_FILE))
169 return -EBADF;
170
171 mkd->dfd = READ_ONCE(sqe->fd);
172 mkd->mode = READ_ONCE(sqe->len);
173
174 fname = u64_to_user_ptr(READ_ONCE(sqe->addr));
175 err = delayed_getname(&mkd->filename, fname);
176 if (unlikely(err))
177 return err;
178
179 req->flags |= REQ_F_NEED_CLEANUP;
180 req->flags |= REQ_F_FORCE_ASYNC;
181 return 0;
182 }
183
io_mkdirat(struct io_kiocb * req,unsigned int issue_flags)184 int io_mkdirat(struct io_kiocb *req, unsigned int issue_flags)
185 {
186 struct io_mkdir *mkd = io_kiocb_to_cmd(req, struct io_mkdir);
187 CLASS(filename_complete_delayed, name)(&mkd->filename);
188 int ret;
189
190 WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
191
192 ret = filename_mkdirat(mkd->dfd, name, mkd->mode);
193
194 req->flags &= ~REQ_F_NEED_CLEANUP;
195 io_req_set_res(req, ret, 0);
196 return IOU_COMPLETE;
197 }
198
io_mkdirat_cleanup(struct io_kiocb * req)199 void io_mkdirat_cleanup(struct io_kiocb *req)
200 {
201 struct io_mkdir *md = io_kiocb_to_cmd(req, struct io_mkdir);
202
203 dismiss_delayed_filename(&md->filename);
204 }
205
io_symlinkat_prep(struct io_kiocb * req,const struct io_uring_sqe * sqe)206 int io_symlinkat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
207 {
208 struct io_link *sl = io_kiocb_to_cmd(req, struct io_link);
209 const char __user *oldpath, *newpath;
210 int err;
211
212 if (sqe->len || sqe->rw_flags || sqe->buf_index || sqe->splice_fd_in)
213 return -EINVAL;
214 if (unlikely(req->flags & REQ_F_FIXED_FILE))
215 return -EBADF;
216
217 sl->new_dfd = READ_ONCE(sqe->fd);
218 oldpath = u64_to_user_ptr(READ_ONCE(sqe->addr));
219 newpath = u64_to_user_ptr(READ_ONCE(sqe->addr2));
220
221 err = delayed_getname(&sl->oldpath, oldpath);
222 if (unlikely(err))
223 return err;
224
225 err = delayed_getname(&sl->newpath, newpath);
226 if (unlikely(err)) {
227 dismiss_delayed_filename(&sl->oldpath);
228 return err;
229 }
230
231 req->flags |= REQ_F_NEED_CLEANUP;
232 req->flags |= REQ_F_FORCE_ASYNC;
233 return 0;
234 }
235
io_symlinkat(struct io_kiocb * req,unsigned int issue_flags)236 int io_symlinkat(struct io_kiocb *req, unsigned int issue_flags)
237 {
238 struct io_link *sl = io_kiocb_to_cmd(req, struct io_link);
239 CLASS(filename_complete_delayed, old)(&sl->oldpath);
240 CLASS(filename_complete_delayed, new)(&sl->newpath);
241 int ret;
242
243 WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
244
245 ret = filename_symlinkat(old, sl->new_dfd, new);
246
247 req->flags &= ~REQ_F_NEED_CLEANUP;
248 io_req_set_res(req, ret, 0);
249 return IOU_COMPLETE;
250 }
251
io_linkat_prep(struct io_kiocb * req,const struct io_uring_sqe * sqe)252 int io_linkat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
253 {
254 struct io_link *lnk = io_kiocb_to_cmd(req, struct io_link);
255 const char __user *oldf, *newf;
256 int err;
257
258 if (sqe->buf_index || sqe->splice_fd_in)
259 return -EINVAL;
260 if (unlikely(req->flags & REQ_F_FIXED_FILE))
261 return -EBADF;
262
263 lnk->old_dfd = READ_ONCE(sqe->fd);
264 lnk->new_dfd = READ_ONCE(sqe->len);
265 oldf = u64_to_user_ptr(READ_ONCE(sqe->addr));
266 newf = u64_to_user_ptr(READ_ONCE(sqe->addr2));
267 lnk->flags = READ_ONCE(sqe->hardlink_flags);
268
269 err = delayed_getname_uflags(&lnk->oldpath, oldf, lnk->flags);
270 if (unlikely(err))
271 return err;
272
273 err = delayed_getname(&lnk->newpath, newf);
274 if (unlikely(err)) {
275 dismiss_delayed_filename(&lnk->oldpath);
276 return err;
277 }
278
279 req->flags |= REQ_F_NEED_CLEANUP;
280 req->flags |= REQ_F_FORCE_ASYNC;
281 return 0;
282 }
283
io_linkat(struct io_kiocb * req,unsigned int issue_flags)284 int io_linkat(struct io_kiocb *req, unsigned int issue_flags)
285 {
286 struct io_link *lnk = io_kiocb_to_cmd(req, struct io_link);
287 CLASS(filename_complete_delayed, old)(&lnk->oldpath);
288 CLASS(filename_complete_delayed, new)(&lnk->newpath);
289 int ret;
290
291 WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
292
293 ret = filename_linkat(lnk->old_dfd, old, lnk->new_dfd, new, lnk->flags);
294
295 req->flags &= ~REQ_F_NEED_CLEANUP;
296 io_req_set_res(req, ret, 0);
297 return IOU_COMPLETE;
298 }
299
io_link_cleanup(struct io_kiocb * req)300 void io_link_cleanup(struct io_kiocb *req)
301 {
302 struct io_link *sl = io_kiocb_to_cmd(req, struct io_link);
303
304 dismiss_delayed_filename(&sl->oldpath);
305 dismiss_delayed_filename(&sl->newpath);
306 }
307