Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
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 }