projects/linux·blob master · refs

197 lines · 4.5 KiB

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#include <linux/xattr.h>
11
12#include <uapi/linux/io_uring.h>
13
14#include "../fs/internal.h"
15
16#include "io_uring.h"
17#include "xattr.h"
18
19struct io_xattr {
20 struct file *file;
21 struct kernel_xattr_ctx ctx;
22 struct delayed_filename filename;
23};
24
25void io_xattr_cleanup(struct io_kiocb *req)
26{
27 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
28
29 dismiss_delayed_filename(&ix->filename);
30 kfree(ix->ctx.kname);
31 kvfree(ix->ctx.kvalue);
32}
33
34static void io_xattr_finish(struct io_kiocb *req, int ret)
35{
36 req->flags &= ~REQ_F_NEED_CLEANUP;
37
38 io_xattr_cleanup(req);
39 io_req_set_res(req, ret, 0);
40}
41
42static int __io_getxattr_prep(struct io_kiocb *req,
43 const struct io_uring_sqe *sqe)
44{
45 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
46 const char __user *name;
47 int ret;
48
49 INIT_DELAYED_FILENAME(&ix->filename);
50 ix->ctx.kvalue = NULL;
51 name = u64_to_user_ptr(READ_ONCE(sqe->addr));
52 ix->ctx.value = u64_to_user_ptr(READ_ONCE(sqe->addr2));
53 ix->ctx.size = READ_ONCE(sqe->len);
54 ix->ctx.flags = READ_ONCE(sqe->xattr_flags);
55
56 if (ix->ctx.flags)
57 return -EINVAL;
58
59 ix->ctx.kname = kmalloc_obj(*ix->ctx.kname);
60 if (!ix->ctx.kname)
61 return -ENOMEM;
62
63 ret = import_xattr_name(ix->ctx.kname, name);
64 if (ret) {
65 kfree(ix->ctx.kname);
66 return ret;
67 }
68
69 req->flags |= REQ_F_NEED_CLEANUP;
70 req->flags |= REQ_F_FORCE_ASYNC;
71 return 0;
72}
73
74int io_fgetxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
75{
76 return __io_getxattr_prep(req, sqe);
77}
78
79int io_getxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
80{
81 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
82 const char __user *path;
83 int ret;
84
85 if (unlikely(req->flags & REQ_F_FIXED_FILE))
86 return -EBADF;
87
88 ret = __io_getxattr_prep(req, sqe);
89 if (ret)
90 return ret;
91
92 path = u64_to_user_ptr(READ_ONCE(sqe->addr3));
93
94 return delayed_getname(&ix->filename, path);
95}
96
97int io_fgetxattr(struct io_kiocb *req, unsigned int issue_flags)
98{
99 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
100 int ret;
101
102 WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
103
104 ret = file_getxattr(req->file, &ix->ctx);
105 io_xattr_finish(req, ret);
106 return IOU_COMPLETE;
107}
108
109int io_getxattr(struct io_kiocb *req, unsigned int issue_flags)
110{
111 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
112 CLASS(filename_complete_delayed, name)(&ix->filename);
113 int ret;
114
115 WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
116
117 ret = filename_getxattr(AT_FDCWD, name, LOOKUP_FOLLOW, &ix->ctx);
118 io_xattr_finish(req, ret);
119 return IOU_COMPLETE;
120}
121
122static int __io_setxattr_prep(struct io_kiocb *req,
123 const struct io_uring_sqe *sqe)
124{
125 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
126 const char __user *name;
127 int ret;
128
129 INIT_DELAYED_FILENAME(&ix->filename);
130 name = u64_to_user_ptr(READ_ONCE(sqe->addr));
131 ix->ctx.cvalue = u64_to_user_ptr(READ_ONCE(sqe->addr2));
132 ix->ctx.kvalue = NULL;
133 ix->ctx.size = READ_ONCE(sqe->len);
134 ix->ctx.flags = READ_ONCE(sqe->xattr_flags);
135
136 ix->ctx.kname = kmalloc_obj(*ix->ctx.kname);
137 if (!ix->ctx.kname)
138 return -ENOMEM;
139
140 ret = setxattr_copy(name, &ix->ctx);
141 if (ret) {
142 kfree(ix->ctx.kname);
143 return ret;
144 }
145
146 req->flags |= REQ_F_NEED_CLEANUP;
147 req->flags |= REQ_F_FORCE_ASYNC;
148 return 0;
149}
150
151int io_setxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
152{
153 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
154 const char __user *path;
155 int ret;
156
157 if (unlikely(req->flags & REQ_F_FIXED_FILE))
158 return -EBADF;
159
160 ret = __io_setxattr_prep(req, sqe);
161 if (ret)
162 return ret;
163
164 path = u64_to_user_ptr(READ_ONCE(sqe->addr3));
165
166 return delayed_getname(&ix->filename, path);
167}
168
169int io_fsetxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
170{
171 return __io_setxattr_prep(req, sqe);
172}
173
174int io_fsetxattr(struct io_kiocb *req, unsigned int issue_flags)
175{
176 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
177 int ret;
178
179 WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
180
181 ret = file_setxattr(req->file, &ix->ctx);
182 io_xattr_finish(req, ret);
183 return IOU_COMPLETE;
184}
185
186int io_setxattr(struct io_kiocb *req, unsigned int issue_flags)
187{
188 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
189 CLASS(filename_complete_delayed, name)(&ix->filename);
190 int ret;
191
192 WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
193
194 ret = filename_setxattr(AT_FDCWD, name, LOOKUP_FOLLOW, &ix->ctx);
195 io_xattr_finish(req, ret);
196 return IOU_COMPLETE;
197}