1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/kernel.h>
3 #include <linux/errno.h>
5 #include <linux/file.h>
7 #include <linux/slab.h>
8 #include <linux/namei.h>
9 #include <linux/io_uring.h>
10 #include <linux/xattr.h>
12 #include <uapi/linux/io_uring.h>
14 #include "../fs/internal.h"
16 #include "io_uring_types.h"
23 struct filename *filename;
26 void io_xattr_cleanup(struct io_kiocb *req)
28 struct io_xattr *ix = io_kiocb_to_cmd(req);
31 putname(ix->filename);
34 kvfree(ix->ctx.kvalue);
37 static void io_xattr_finish(struct io_kiocb *req, int ret)
39 req->flags &= ~REQ_F_NEED_CLEANUP;
41 io_xattr_cleanup(req);
42 io_req_set_res(req, ret, 0);
45 static int __io_getxattr_prep(struct io_kiocb *req,
46 const struct io_uring_sqe *sqe)
48 struct io_xattr *ix = io_kiocb_to_cmd(req);
49 const char __user *name;
52 if (unlikely(req->flags & REQ_F_FIXED_FILE))
56 ix->ctx.kvalue = NULL;
57 name = u64_to_user_ptr(READ_ONCE(sqe->addr));
58 ix->ctx.cvalue = u64_to_user_ptr(READ_ONCE(sqe->addr2));
59 ix->ctx.size = READ_ONCE(sqe->len);
60 ix->ctx.flags = READ_ONCE(sqe->xattr_flags);
65 ix->ctx.kname = kmalloc(sizeof(*ix->ctx.kname), GFP_KERNEL);
69 ret = strncpy_from_user(ix->ctx.kname->name, name,
70 sizeof(ix->ctx.kname->name));
71 if (!ret || ret == sizeof(ix->ctx.kname->name))
78 req->flags |= REQ_F_NEED_CLEANUP;
82 int io_fgetxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
84 return __io_getxattr_prep(req, sqe);
87 int io_getxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
89 struct io_xattr *ix = io_kiocb_to_cmd(req);
90 const char __user *path;
93 ret = __io_getxattr_prep(req, sqe);
97 path = u64_to_user_ptr(READ_ONCE(sqe->addr3));
99 ix->filename = getname_flags(path, LOOKUP_FOLLOW, NULL);
100 if (IS_ERR(ix->filename)) {
101 ret = PTR_ERR(ix->filename);
108 int io_fgetxattr(struct io_kiocb *req, unsigned int issue_flags)
110 struct io_xattr *ix = io_kiocb_to_cmd(req);
113 if (issue_flags & IO_URING_F_NONBLOCK)
116 ret = do_getxattr(mnt_user_ns(req->file->f_path.mnt),
117 req->file->f_path.dentry,
120 io_xattr_finish(req, ret);
124 int io_getxattr(struct io_kiocb *req, unsigned int issue_flags)
126 struct io_xattr *ix = io_kiocb_to_cmd(req);
127 unsigned int lookup_flags = LOOKUP_FOLLOW;
131 if (issue_flags & IO_URING_F_NONBLOCK)
135 ret = filename_lookup(AT_FDCWD, ix->filename, lookup_flags, &path, NULL);
137 ret = do_getxattr(mnt_user_ns(path.mnt),
142 if (retry_estale(ret, lookup_flags)) {
143 lookup_flags |= LOOKUP_REVAL;
148 io_xattr_finish(req, ret);
152 static int __io_setxattr_prep(struct io_kiocb *req,
153 const struct io_uring_sqe *sqe)
155 struct io_xattr *ix = io_kiocb_to_cmd(req);
156 const char __user *name;
159 if (unlikely(req->flags & REQ_F_FIXED_FILE))
163 name = u64_to_user_ptr(READ_ONCE(sqe->addr));
164 ix->ctx.cvalue = u64_to_user_ptr(READ_ONCE(sqe->addr2));
165 ix->ctx.kvalue = NULL;
166 ix->ctx.size = READ_ONCE(sqe->len);
167 ix->ctx.flags = READ_ONCE(sqe->xattr_flags);
169 ix->ctx.kname = kmalloc(sizeof(*ix->ctx.kname), GFP_KERNEL);
173 ret = setxattr_copy(name, &ix->ctx);
175 kfree(ix->ctx.kname);
179 req->flags |= REQ_F_NEED_CLEANUP;
183 int io_setxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
185 struct io_xattr *ix = io_kiocb_to_cmd(req);
186 const char __user *path;
189 ret = __io_setxattr_prep(req, sqe);
193 path = u64_to_user_ptr(READ_ONCE(sqe->addr3));
195 ix->filename = getname_flags(path, LOOKUP_FOLLOW, NULL);
196 if (IS_ERR(ix->filename)) {
197 ret = PTR_ERR(ix->filename);
204 int io_fsetxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
206 return __io_setxattr_prep(req, sqe);
209 static int __io_setxattr(struct io_kiocb *req, unsigned int issue_flags,
212 struct io_xattr *ix = io_kiocb_to_cmd(req);
215 ret = mnt_want_write(path->mnt);
217 ret = do_setxattr(mnt_user_ns(path->mnt), path->dentry, &ix->ctx);
218 mnt_drop_write(path->mnt);
224 int io_fsetxattr(struct io_kiocb *req, unsigned int issue_flags)
228 if (issue_flags & IO_URING_F_NONBLOCK)
231 ret = __io_setxattr(req, issue_flags, &req->file->f_path);
232 io_xattr_finish(req, ret);
236 int io_setxattr(struct io_kiocb *req, unsigned int issue_flags)
238 struct io_xattr *ix = io_kiocb_to_cmd(req);
239 unsigned int lookup_flags = LOOKUP_FOLLOW;
243 if (issue_flags & IO_URING_F_NONBLOCK)
247 ret = filename_lookup(AT_FDCWD, ix->filename, lookup_flags, &path, NULL);
249 ret = __io_setxattr(req, issue_flags, &path);
251 if (retry_estale(ret, lookup_flags)) {
252 lookup_flags |= LOOKUP_REVAL;
257 io_xattr_finish(req, ret);