0001
0002 #include <linux/kernel.h>
0003 #include <linux/errno.h>
0004 #include <linux/fs.h>
0005 #include <linux/file.h>
0006 #include <linux/mm.h>
0007 #include <linux/slab.h>
0008 #include <linux/namei.h>
0009 #include <linux/io_uring.h>
0010 #include <linux/xattr.h>
0011
0012 #include <uapi/linux/io_uring.h>
0013
0014 #include "../fs/internal.h"
0015
0016 #include "io_uring.h"
0017 #include "xattr.h"
0018
0019 struct io_xattr {
0020 struct file *file;
0021 struct xattr_ctx ctx;
0022 struct filename *filename;
0023 };
0024
0025 void io_xattr_cleanup(struct io_kiocb *req)
0026 {
0027 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
0028
0029 if (ix->filename)
0030 putname(ix->filename);
0031
0032 kfree(ix->ctx.kname);
0033 kvfree(ix->ctx.kvalue);
0034 }
0035
0036 static void io_xattr_finish(struct io_kiocb *req, int ret)
0037 {
0038 req->flags &= ~REQ_F_NEED_CLEANUP;
0039
0040 io_xattr_cleanup(req);
0041 io_req_set_res(req, ret, 0);
0042 }
0043
0044 static int __io_getxattr_prep(struct io_kiocb *req,
0045 const struct io_uring_sqe *sqe)
0046 {
0047 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
0048 const char __user *name;
0049 int ret;
0050
0051 if (unlikely(req->flags & REQ_F_FIXED_FILE))
0052 return -EBADF;
0053
0054 ix->filename = NULL;
0055 ix->ctx.kvalue = NULL;
0056 name = u64_to_user_ptr(READ_ONCE(sqe->addr));
0057 ix->ctx.cvalue = u64_to_user_ptr(READ_ONCE(sqe->addr2));
0058 ix->ctx.size = READ_ONCE(sqe->len);
0059 ix->ctx.flags = READ_ONCE(sqe->xattr_flags);
0060
0061 if (ix->ctx.flags)
0062 return -EINVAL;
0063
0064 ix->ctx.kname = kmalloc(sizeof(*ix->ctx.kname), GFP_KERNEL);
0065 if (!ix->ctx.kname)
0066 return -ENOMEM;
0067
0068 ret = strncpy_from_user(ix->ctx.kname->name, name,
0069 sizeof(ix->ctx.kname->name));
0070 if (!ret || ret == sizeof(ix->ctx.kname->name))
0071 ret = -ERANGE;
0072 if (ret < 0) {
0073 kfree(ix->ctx.kname);
0074 return ret;
0075 }
0076
0077 req->flags |= REQ_F_NEED_CLEANUP;
0078 return 0;
0079 }
0080
0081 int io_fgetxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
0082 {
0083 return __io_getxattr_prep(req, sqe);
0084 }
0085
0086 int io_getxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
0087 {
0088 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
0089 const char __user *path;
0090 int ret;
0091
0092 ret = __io_getxattr_prep(req, sqe);
0093 if (ret)
0094 return ret;
0095
0096 path = u64_to_user_ptr(READ_ONCE(sqe->addr3));
0097
0098 ix->filename = getname_flags(path, LOOKUP_FOLLOW, NULL);
0099 if (IS_ERR(ix->filename)) {
0100 ret = PTR_ERR(ix->filename);
0101 ix->filename = NULL;
0102 }
0103
0104 return ret;
0105 }
0106
0107 int io_fgetxattr(struct io_kiocb *req, unsigned int issue_flags)
0108 {
0109 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
0110 int ret;
0111
0112 if (issue_flags & IO_URING_F_NONBLOCK)
0113 return -EAGAIN;
0114
0115 ret = do_getxattr(mnt_user_ns(req->file->f_path.mnt),
0116 req->file->f_path.dentry,
0117 &ix->ctx);
0118
0119 io_xattr_finish(req, ret);
0120 return IOU_OK;
0121 }
0122
0123 int io_getxattr(struct io_kiocb *req, unsigned int issue_flags)
0124 {
0125 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
0126 unsigned int lookup_flags = LOOKUP_FOLLOW;
0127 struct path path;
0128 int ret;
0129
0130 if (issue_flags & IO_URING_F_NONBLOCK)
0131 return -EAGAIN;
0132
0133 retry:
0134 ret = filename_lookup(AT_FDCWD, ix->filename, lookup_flags, &path, NULL);
0135 if (!ret) {
0136 ret = do_getxattr(mnt_user_ns(path.mnt),
0137 path.dentry,
0138 &ix->ctx);
0139
0140 path_put(&path);
0141 if (retry_estale(ret, lookup_flags)) {
0142 lookup_flags |= LOOKUP_REVAL;
0143 goto retry;
0144 }
0145 }
0146
0147 io_xattr_finish(req, ret);
0148 return IOU_OK;
0149 }
0150
0151 static int __io_setxattr_prep(struct io_kiocb *req,
0152 const struct io_uring_sqe *sqe)
0153 {
0154 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
0155 const char __user *name;
0156 int ret;
0157
0158 if (unlikely(req->flags & REQ_F_FIXED_FILE))
0159 return -EBADF;
0160
0161 ix->filename = NULL;
0162 name = u64_to_user_ptr(READ_ONCE(sqe->addr));
0163 ix->ctx.cvalue = u64_to_user_ptr(READ_ONCE(sqe->addr2));
0164 ix->ctx.kvalue = NULL;
0165 ix->ctx.size = READ_ONCE(sqe->len);
0166 ix->ctx.flags = READ_ONCE(sqe->xattr_flags);
0167
0168 ix->ctx.kname = kmalloc(sizeof(*ix->ctx.kname), GFP_KERNEL);
0169 if (!ix->ctx.kname)
0170 return -ENOMEM;
0171
0172 ret = setxattr_copy(name, &ix->ctx);
0173 if (ret) {
0174 kfree(ix->ctx.kname);
0175 return ret;
0176 }
0177
0178 req->flags |= REQ_F_NEED_CLEANUP;
0179 return 0;
0180 }
0181
0182 int io_setxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
0183 {
0184 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
0185 const char __user *path;
0186 int ret;
0187
0188 ret = __io_setxattr_prep(req, sqe);
0189 if (ret)
0190 return ret;
0191
0192 path = u64_to_user_ptr(READ_ONCE(sqe->addr3));
0193
0194 ix->filename = getname_flags(path, LOOKUP_FOLLOW, NULL);
0195 if (IS_ERR(ix->filename)) {
0196 ret = PTR_ERR(ix->filename);
0197 ix->filename = NULL;
0198 }
0199
0200 return ret;
0201 }
0202
0203 int io_fsetxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
0204 {
0205 return __io_setxattr_prep(req, sqe);
0206 }
0207
0208 static int __io_setxattr(struct io_kiocb *req, unsigned int issue_flags,
0209 struct path *path)
0210 {
0211 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
0212 int ret;
0213
0214 ret = mnt_want_write(path->mnt);
0215 if (!ret) {
0216 ret = do_setxattr(mnt_user_ns(path->mnt), path->dentry, &ix->ctx);
0217 mnt_drop_write(path->mnt);
0218 }
0219
0220 return ret;
0221 }
0222
0223 int io_fsetxattr(struct io_kiocb *req, unsigned int issue_flags)
0224 {
0225 int ret;
0226
0227 if (issue_flags & IO_URING_F_NONBLOCK)
0228 return -EAGAIN;
0229
0230 ret = __io_setxattr(req, issue_flags, &req->file->f_path);
0231 io_xattr_finish(req, ret);
0232 return IOU_OK;
0233 }
0234
0235 int io_setxattr(struct io_kiocb *req, unsigned int issue_flags)
0236 {
0237 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
0238 unsigned int lookup_flags = LOOKUP_FOLLOW;
0239 struct path path;
0240 int ret;
0241
0242 if (issue_flags & IO_URING_F_NONBLOCK)
0243 return -EAGAIN;
0244
0245 retry:
0246 ret = filename_lookup(AT_FDCWD, ix->filename, lookup_flags, &path, NULL);
0247 if (!ret) {
0248 ret = __io_setxattr(req, issue_flags, &path);
0249 path_put(&path);
0250 if (retry_estale(ret, lookup_flags)) {
0251 lookup_flags |= LOOKUP_REVAL;
0252 goto retry;
0253 }
0254 }
0255
0256 io_xattr_finish(req, ret);
0257 return IOU_OK;
0258 }