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 
0011 #include <uapi/linux/io_uring.h>
0012 
0013 #include "../fs/internal.h"
0014 
0015 #include "io_uring.h"
0016 #include "fs.h"
0017 
0018 struct io_rename {
0019     struct file         *file;
0020     int             old_dfd;
0021     int             new_dfd;
0022     struct filename         *oldpath;
0023     struct filename         *newpath;
0024     int             flags;
0025 };
0026 
0027 struct io_unlink {
0028     struct file         *file;
0029     int             dfd;
0030     int             flags;
0031     struct filename         *filename;
0032 };
0033 
0034 struct io_mkdir {
0035     struct file         *file;
0036     int             dfd;
0037     umode_t             mode;
0038     struct filename         *filename;
0039 };
0040 
0041 struct io_link {
0042     struct file         *file;
0043     int             old_dfd;
0044     int             new_dfd;
0045     struct filename         *oldpath;
0046     struct filename         *newpath;
0047     int             flags;
0048 };
0049 
0050 int io_renameat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
0051 {
0052     struct io_rename *ren = io_kiocb_to_cmd(req, struct io_rename);
0053     const char __user *oldf, *newf;
0054 
0055     if (sqe->buf_index || sqe->splice_fd_in)
0056         return -EINVAL;
0057     if (unlikely(req->flags & REQ_F_FIXED_FILE))
0058         return -EBADF;
0059 
0060     ren->old_dfd = READ_ONCE(sqe->fd);
0061     oldf = u64_to_user_ptr(READ_ONCE(sqe->addr));
0062     newf = u64_to_user_ptr(READ_ONCE(sqe->addr2));
0063     ren->new_dfd = READ_ONCE(sqe->len);
0064     ren->flags = READ_ONCE(sqe->rename_flags);
0065 
0066     ren->oldpath = getname(oldf);
0067     if (IS_ERR(ren->oldpath))
0068         return PTR_ERR(ren->oldpath);
0069 
0070     ren->newpath = getname(newf);
0071     if (IS_ERR(ren->newpath)) {
0072         putname(ren->oldpath);
0073         return PTR_ERR(ren->newpath);
0074     }
0075 
0076     req->flags |= REQ_F_NEED_CLEANUP;
0077     return 0;
0078 }
0079 
0080 int io_renameat(struct io_kiocb *req, unsigned int issue_flags)
0081 {
0082     struct io_rename *ren = io_kiocb_to_cmd(req, struct io_rename);
0083     int ret;
0084 
0085     if (issue_flags & IO_URING_F_NONBLOCK)
0086         return -EAGAIN;
0087 
0088     ret = do_renameat2(ren->old_dfd, ren->oldpath, ren->new_dfd,
0089                 ren->newpath, ren->flags);
0090 
0091     req->flags &= ~REQ_F_NEED_CLEANUP;
0092     io_req_set_res(req, ret, 0);
0093     return IOU_OK;
0094 }
0095 
0096 void io_renameat_cleanup(struct io_kiocb *req)
0097 {
0098     struct io_rename *ren = io_kiocb_to_cmd(req, struct io_rename);
0099 
0100     putname(ren->oldpath);
0101     putname(ren->newpath);
0102 }
0103 
0104 int io_unlinkat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
0105 {
0106     struct io_unlink *un = io_kiocb_to_cmd(req, struct io_unlink);
0107     const char __user *fname;
0108 
0109     if (sqe->off || sqe->len || sqe->buf_index || sqe->splice_fd_in)
0110         return -EINVAL;
0111     if (unlikely(req->flags & REQ_F_FIXED_FILE))
0112         return -EBADF;
0113 
0114     un->dfd = READ_ONCE(sqe->fd);
0115 
0116     un->flags = READ_ONCE(sqe->unlink_flags);
0117     if (un->flags & ~AT_REMOVEDIR)
0118         return -EINVAL;
0119 
0120     fname = u64_to_user_ptr(READ_ONCE(sqe->addr));
0121     un->filename = getname(fname);
0122     if (IS_ERR(un->filename))
0123         return PTR_ERR(un->filename);
0124 
0125     req->flags |= REQ_F_NEED_CLEANUP;
0126     return 0;
0127 }
0128 
0129 int io_unlinkat(struct io_kiocb *req, unsigned int issue_flags)
0130 {
0131     struct io_unlink *un = io_kiocb_to_cmd(req, struct io_unlink);
0132     int ret;
0133 
0134     if (issue_flags & IO_URING_F_NONBLOCK)
0135         return -EAGAIN;
0136 
0137     if (un->flags & AT_REMOVEDIR)
0138         ret = do_rmdir(un->dfd, un->filename);
0139     else
0140         ret = do_unlinkat(un->dfd, un->filename);
0141 
0142     req->flags &= ~REQ_F_NEED_CLEANUP;
0143     io_req_set_res(req, ret, 0);
0144     return IOU_OK;
0145 }
0146 
0147 void io_unlinkat_cleanup(struct io_kiocb *req)
0148 {
0149     struct io_unlink *ul = io_kiocb_to_cmd(req, struct io_unlink);
0150 
0151     putname(ul->filename);
0152 }
0153 
0154 int io_mkdirat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
0155 {
0156     struct io_mkdir *mkd = io_kiocb_to_cmd(req, struct io_mkdir);
0157     const char __user *fname;
0158 
0159     if (sqe->off || sqe->rw_flags || sqe->buf_index || sqe->splice_fd_in)
0160         return -EINVAL;
0161     if (unlikely(req->flags & REQ_F_FIXED_FILE))
0162         return -EBADF;
0163 
0164     mkd->dfd = READ_ONCE(sqe->fd);
0165     mkd->mode = READ_ONCE(sqe->len);
0166 
0167     fname = u64_to_user_ptr(READ_ONCE(sqe->addr));
0168     mkd->filename = getname(fname);
0169     if (IS_ERR(mkd->filename))
0170         return PTR_ERR(mkd->filename);
0171 
0172     req->flags |= REQ_F_NEED_CLEANUP;
0173     return 0;
0174 }
0175 
0176 int io_mkdirat(struct io_kiocb *req, unsigned int issue_flags)
0177 {
0178     struct io_mkdir *mkd = io_kiocb_to_cmd(req, struct io_mkdir);
0179     int ret;
0180 
0181     if (issue_flags & IO_URING_F_NONBLOCK)
0182         return -EAGAIN;
0183 
0184     ret = do_mkdirat(mkd->dfd, mkd->filename, mkd->mode);
0185 
0186     req->flags &= ~REQ_F_NEED_CLEANUP;
0187     io_req_set_res(req, ret, 0);
0188     return IOU_OK;
0189 }
0190 
0191 void io_mkdirat_cleanup(struct io_kiocb *req)
0192 {
0193     struct io_mkdir *md = io_kiocb_to_cmd(req, struct io_mkdir);
0194 
0195     putname(md->filename);
0196 }
0197 
0198 int io_symlinkat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
0199 {
0200     struct io_link *sl = io_kiocb_to_cmd(req, struct io_link);
0201     const char __user *oldpath, *newpath;
0202 
0203     if (sqe->len || sqe->rw_flags || sqe->buf_index || sqe->splice_fd_in)
0204         return -EINVAL;
0205     if (unlikely(req->flags & REQ_F_FIXED_FILE))
0206         return -EBADF;
0207 
0208     sl->new_dfd = READ_ONCE(sqe->fd);
0209     oldpath = u64_to_user_ptr(READ_ONCE(sqe->addr));
0210     newpath = u64_to_user_ptr(READ_ONCE(sqe->addr2));
0211 
0212     sl->oldpath = getname(oldpath);
0213     if (IS_ERR(sl->oldpath))
0214         return PTR_ERR(sl->oldpath);
0215 
0216     sl->newpath = getname(newpath);
0217     if (IS_ERR(sl->newpath)) {
0218         putname(sl->oldpath);
0219         return PTR_ERR(sl->newpath);
0220     }
0221 
0222     req->flags |= REQ_F_NEED_CLEANUP;
0223     return 0;
0224 }
0225 
0226 int io_symlinkat(struct io_kiocb *req, unsigned int issue_flags)
0227 {
0228     struct io_link *sl = io_kiocb_to_cmd(req, struct io_link);
0229     int ret;
0230 
0231     if (issue_flags & IO_URING_F_NONBLOCK)
0232         return -EAGAIN;
0233 
0234     ret = do_symlinkat(sl->oldpath, sl->new_dfd, sl->newpath);
0235 
0236     req->flags &= ~REQ_F_NEED_CLEANUP;
0237     io_req_set_res(req, ret, 0);
0238     return IOU_OK;
0239 }
0240 
0241 int io_linkat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
0242 {
0243     struct io_link *lnk = io_kiocb_to_cmd(req, struct io_link);
0244     const char __user *oldf, *newf;
0245 
0246     if (sqe->rw_flags || sqe->buf_index || sqe->splice_fd_in)
0247         return -EINVAL;
0248     if (unlikely(req->flags & REQ_F_FIXED_FILE))
0249         return -EBADF;
0250 
0251     lnk->old_dfd = READ_ONCE(sqe->fd);
0252     lnk->new_dfd = READ_ONCE(sqe->len);
0253     oldf = u64_to_user_ptr(READ_ONCE(sqe->addr));
0254     newf = u64_to_user_ptr(READ_ONCE(sqe->addr2));
0255     lnk->flags = READ_ONCE(sqe->hardlink_flags);
0256 
0257     lnk->oldpath = getname(oldf);
0258     if (IS_ERR(lnk->oldpath))
0259         return PTR_ERR(lnk->oldpath);
0260 
0261     lnk->newpath = getname(newf);
0262     if (IS_ERR(lnk->newpath)) {
0263         putname(lnk->oldpath);
0264         return PTR_ERR(lnk->newpath);
0265     }
0266 
0267     req->flags |= REQ_F_NEED_CLEANUP;
0268     return 0;
0269 }
0270 
0271 int io_linkat(struct io_kiocb *req, unsigned int issue_flags)
0272 {
0273     struct io_link *lnk = io_kiocb_to_cmd(req, struct io_link);
0274     int ret;
0275 
0276     if (issue_flags & IO_URING_F_NONBLOCK)
0277         return -EAGAIN;
0278 
0279     ret = do_linkat(lnk->old_dfd, lnk->oldpath, lnk->new_dfd,
0280                 lnk->newpath, lnk->flags);
0281 
0282     req->flags &= ~REQ_F_NEED_CLEANUP;
0283     io_req_set_res(req, ret, 0);
0284     return IOU_OK;
0285 }
0286 
0287 void io_link_cleanup(struct io_kiocb *req)
0288 {
0289     struct io_link *sl = io_kiocb_to_cmd(req, struct io_link);
0290 
0291     putname(sl->oldpath);
0292     putname(sl->newpath);
0293 }