~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/io_uring/xattr.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 
 19 struct io_xattr {
 20         struct file                     *file;
 21         struct xattr_ctx                ctx;
 22         struct filename                 *filename;
 23 };
 24 
 25 void io_xattr_cleanup(struct io_kiocb *req)
 26 {
 27         struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
 28 
 29         if (ix->filename)
 30                 putname(ix->filename);
 31 
 32         kfree(ix->ctx.kname);
 33         kvfree(ix->ctx.kvalue);
 34 }
 35 
 36 static void io_xattr_finish(struct io_kiocb *req, int ret)
 37 {
 38         req->flags &= ~REQ_F_NEED_CLEANUP;
 39 
 40         io_xattr_cleanup(req);
 41         io_req_set_res(req, ret, 0);
 42 }
 43 
 44 static int __io_getxattr_prep(struct io_kiocb *req,
 45                               const struct io_uring_sqe *sqe)
 46 {
 47         struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
 48         const char __user *name;
 49         int ret;
 50 
 51         if (unlikely(req->flags & REQ_F_FIXED_FILE))
 52                 return -EBADF;
 53 
 54         ix->filename = NULL;
 55         ix->ctx.kvalue = NULL;
 56         name = u64_to_user_ptr(READ_ONCE(sqe->addr));
 57         ix->ctx.cvalue = u64_to_user_ptr(READ_ONCE(sqe->addr2));
 58         ix->ctx.size = READ_ONCE(sqe->len);
 59         ix->ctx.flags = READ_ONCE(sqe->xattr_flags);
 60 
 61         if (ix->ctx.flags)
 62                 return -EINVAL;
 63 
 64         ix->ctx.kname = kmalloc(sizeof(*ix->ctx.kname), GFP_KERNEL);
 65         if (!ix->ctx.kname)
 66                 return -ENOMEM;
 67 
 68         ret = strncpy_from_user(ix->ctx.kname->name, name,
 69                                 sizeof(ix->ctx.kname->name));
 70         if (!ret || ret == sizeof(ix->ctx.kname->name))
 71                 ret = -ERANGE;
 72         if (ret < 0) {
 73                 kfree(ix->ctx.kname);
 74                 return ret;
 75         }
 76 
 77         req->flags |= REQ_F_NEED_CLEANUP;
 78         req->flags |= REQ_F_FORCE_ASYNC;
 79         return 0;
 80 }
 81 
 82 int io_fgetxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 83 {
 84         return __io_getxattr_prep(req, sqe);
 85 }
 86 
 87 int io_getxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 88 {
 89         struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
 90         const char __user *path;
 91         int ret;
 92 
 93         ret = __io_getxattr_prep(req, sqe);
 94         if (ret)
 95                 return ret;
 96 
 97         path = u64_to_user_ptr(READ_ONCE(sqe->addr3));
 98 
 99         ix->filename = getname_flags(path, LOOKUP_FOLLOW);
100         if (IS_ERR(ix->filename)) {
101                 ret = PTR_ERR(ix->filename);
102                 ix->filename = NULL;
103         }
104 
105         return ret;
106 }
107 
108 int io_fgetxattr(struct io_kiocb *req, unsigned int issue_flags)
109 {
110         struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
111         int ret;
112 
113         WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
114 
115         ret = do_getxattr(file_mnt_idmap(req->file),
116                         req->file->f_path.dentry,
117                         &ix->ctx);
118 
119         io_xattr_finish(req, ret);
120         return IOU_OK;
121 }
122 
123 int io_getxattr(struct io_kiocb *req, unsigned int issue_flags)
124 {
125         struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
126         unsigned int lookup_flags = LOOKUP_FOLLOW;
127         struct path path;
128         int ret;
129 
130         WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
131 
132 retry:
133         ret = filename_lookup(AT_FDCWD, ix->filename, lookup_flags, &path, NULL);
134         if (!ret) {
135                 ret = do_getxattr(mnt_idmap(path.mnt), path.dentry, &ix->ctx);
136 
137                 path_put(&path);
138                 if (retry_estale(ret, lookup_flags)) {
139                         lookup_flags |= LOOKUP_REVAL;
140                         goto retry;
141                 }
142         }
143 
144         io_xattr_finish(req, ret);
145         return IOU_OK;
146 }
147 
148 static int __io_setxattr_prep(struct io_kiocb *req,
149                         const struct io_uring_sqe *sqe)
150 {
151         struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
152         const char __user *name;
153         int ret;
154 
155         if (unlikely(req->flags & REQ_F_FIXED_FILE))
156                 return -EBADF;
157 
158         ix->filename = NULL;
159         name = u64_to_user_ptr(READ_ONCE(sqe->addr));
160         ix->ctx.cvalue = u64_to_user_ptr(READ_ONCE(sqe->addr2));
161         ix->ctx.kvalue = NULL;
162         ix->ctx.size = READ_ONCE(sqe->len);
163         ix->ctx.flags = READ_ONCE(sqe->xattr_flags);
164 
165         ix->ctx.kname = kmalloc(sizeof(*ix->ctx.kname), GFP_KERNEL);
166         if (!ix->ctx.kname)
167                 return -ENOMEM;
168 
169         ret = setxattr_copy(name, &ix->ctx);
170         if (ret) {
171                 kfree(ix->ctx.kname);
172                 return ret;
173         }
174 
175         req->flags |= REQ_F_NEED_CLEANUP;
176         req->flags |= REQ_F_FORCE_ASYNC;
177         return 0;
178 }
179 
180 int io_setxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
181 {
182         struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
183         const char __user *path;
184         int ret;
185 
186         ret = __io_setxattr_prep(req, sqe);
187         if (ret)
188                 return ret;
189 
190         path = u64_to_user_ptr(READ_ONCE(sqe->addr3));
191 
192         ix->filename = getname_flags(path, LOOKUP_FOLLOW);
193         if (IS_ERR(ix->filename)) {
194                 ret = PTR_ERR(ix->filename);
195                 ix->filename = NULL;
196         }
197 
198         return ret;
199 }
200 
201 int io_fsetxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
202 {
203         return __io_setxattr_prep(req, sqe);
204 }
205 
206 static int __io_setxattr(struct io_kiocb *req, unsigned int issue_flags,
207                         const struct path *path)
208 {
209         struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
210         int ret;
211 
212         ret = mnt_want_write(path->mnt);
213         if (!ret) {
214                 ret = do_setxattr(mnt_idmap(path->mnt), path->dentry, &ix->ctx);
215                 mnt_drop_write(path->mnt);
216         }
217 
218         return ret;
219 }
220 
221 int io_fsetxattr(struct io_kiocb *req, unsigned int issue_flags)
222 {
223         int ret;
224 
225         WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
226 
227         ret = __io_setxattr(req, issue_flags, &req->file->f_path);
228         io_xattr_finish(req, ret);
229         return IOU_OK;
230 }
231 
232 int io_setxattr(struct io_kiocb *req, unsigned int issue_flags)
233 {
234         struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
235         unsigned int lookup_flags = LOOKUP_FOLLOW;
236         struct path path;
237         int ret;
238 
239         WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
240 
241 retry:
242         ret = filename_lookup(AT_FDCWD, ix->filename, lookup_flags, &path, NULL);
243         if (!ret) {
244                 ret = __io_setxattr(req, issue_flags, &path);
245                 path_put(&path);
246                 if (retry_estale(ret, lookup_flags)) {
247                         lookup_flags |= LOOKUP_REVAL;
248                         goto retry;
249                 }
250         }
251 
252         io_xattr_finish(req, ret);
253         return IOU_OK;
254 }
255 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php