LCOV - code coverage report
Current view: top level - io_uring - fs.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 138 0.0 %
Date: 2023-04-06 08:38:28 Functions: 0 14 0.0 %

          Line data    Source code
       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             : 
      11             : #include <uapi/linux/io_uring.h>
      12             : 
      13             : #include "../fs/internal.h"
      14             : 
      15             : #include "io_uring.h"
      16             : #include "fs.h"
      17             : 
      18             : struct io_rename {
      19             :         struct file                     *file;
      20             :         int                             old_dfd;
      21             :         int                             new_dfd;
      22             :         struct filename                 *oldpath;
      23             :         struct filename                 *newpath;
      24             :         int                             flags;
      25             : };
      26             : 
      27             : struct io_unlink {
      28             :         struct file                     *file;
      29             :         int                             dfd;
      30             :         int                             flags;
      31             :         struct filename                 *filename;
      32             : };
      33             : 
      34             : struct io_mkdir {
      35             :         struct file                     *file;
      36             :         int                             dfd;
      37             :         umode_t                         mode;
      38             :         struct filename                 *filename;
      39             : };
      40             : 
      41             : struct io_link {
      42             :         struct file                     *file;
      43             :         int                             old_dfd;
      44             :         int                             new_dfd;
      45             :         struct filename                 *oldpath;
      46             :         struct filename                 *newpath;
      47             :         int                             flags;
      48             : };
      49             : 
      50           0 : int io_renameat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
      51             : {
      52           0 :         struct io_rename *ren = io_kiocb_to_cmd(req, struct io_rename);
      53             :         const char __user *oldf, *newf;
      54             : 
      55           0 :         if (sqe->buf_index || sqe->splice_fd_in)
      56             :                 return -EINVAL;
      57           0 :         if (unlikely(req->flags & REQ_F_FIXED_FILE))
      58             :                 return -EBADF;
      59             : 
      60           0 :         ren->old_dfd = READ_ONCE(sqe->fd);
      61           0 :         oldf = u64_to_user_ptr(READ_ONCE(sqe->addr));
      62           0 :         newf = u64_to_user_ptr(READ_ONCE(sqe->addr2));
      63           0 :         ren->new_dfd = READ_ONCE(sqe->len);
      64           0 :         ren->flags = READ_ONCE(sqe->rename_flags);
      65             : 
      66           0 :         ren->oldpath = getname(oldf);
      67           0 :         if (IS_ERR(ren->oldpath))
      68           0 :                 return PTR_ERR(ren->oldpath);
      69             : 
      70           0 :         ren->newpath = getname(newf);
      71           0 :         if (IS_ERR(ren->newpath)) {
      72           0 :                 putname(ren->oldpath);
      73           0 :                 return PTR_ERR(ren->newpath);
      74             :         }
      75             : 
      76           0 :         req->flags |= REQ_F_NEED_CLEANUP;
      77           0 :         req->flags |= REQ_F_FORCE_ASYNC;
      78           0 :         return 0;
      79             : }
      80             : 
      81           0 : int io_renameat(struct io_kiocb *req, unsigned int issue_flags)
      82             : {
      83           0 :         struct io_rename *ren = io_kiocb_to_cmd(req, struct io_rename);
      84             :         int ret;
      85             : 
      86           0 :         WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
      87             : 
      88           0 :         ret = do_renameat2(ren->old_dfd, ren->oldpath, ren->new_dfd,
      89           0 :                                 ren->newpath, ren->flags);
      90             : 
      91           0 :         req->flags &= ~REQ_F_NEED_CLEANUP;
      92           0 :         io_req_set_res(req, ret, 0);
      93           0 :         return IOU_OK;
      94             : }
      95             : 
      96           0 : void io_renameat_cleanup(struct io_kiocb *req)
      97             : {
      98           0 :         struct io_rename *ren = io_kiocb_to_cmd(req, struct io_rename);
      99             : 
     100           0 :         putname(ren->oldpath);
     101           0 :         putname(ren->newpath);
     102           0 : }
     103             : 
     104           0 : int io_unlinkat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
     105             : {
     106           0 :         struct io_unlink *un = io_kiocb_to_cmd(req, struct io_unlink);
     107             :         const char __user *fname;
     108             : 
     109           0 :         if (sqe->off || sqe->len || sqe->buf_index || sqe->splice_fd_in)
     110             :                 return -EINVAL;
     111           0 :         if (unlikely(req->flags & REQ_F_FIXED_FILE))
     112             :                 return -EBADF;
     113             : 
     114           0 :         un->dfd = READ_ONCE(sqe->fd);
     115             : 
     116           0 :         un->flags = READ_ONCE(sqe->unlink_flags);
     117           0 :         if (un->flags & ~AT_REMOVEDIR)
     118             :                 return -EINVAL;
     119             : 
     120           0 :         fname = u64_to_user_ptr(READ_ONCE(sqe->addr));
     121           0 :         un->filename = getname(fname);
     122           0 :         if (IS_ERR(un->filename))
     123           0 :                 return PTR_ERR(un->filename);
     124             : 
     125           0 :         req->flags |= REQ_F_NEED_CLEANUP;
     126           0 :         req->flags |= REQ_F_FORCE_ASYNC;
     127           0 :         return 0;
     128             : }
     129             : 
     130           0 : int io_unlinkat(struct io_kiocb *req, unsigned int issue_flags)
     131             : {
     132           0 :         struct io_unlink *un = io_kiocb_to_cmd(req, struct io_unlink);
     133             :         int ret;
     134             : 
     135           0 :         WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
     136             : 
     137           0 :         if (un->flags & AT_REMOVEDIR)
     138           0 :                 ret = do_rmdir(un->dfd, un->filename);
     139             :         else
     140           0 :                 ret = do_unlinkat(un->dfd, un->filename);
     141             : 
     142           0 :         req->flags &= ~REQ_F_NEED_CLEANUP;
     143           0 :         io_req_set_res(req, ret, 0);
     144           0 :         return IOU_OK;
     145             : }
     146             : 
     147           0 : void io_unlinkat_cleanup(struct io_kiocb *req)
     148             : {
     149           0 :         struct io_unlink *ul = io_kiocb_to_cmd(req, struct io_unlink);
     150             : 
     151           0 :         putname(ul->filename);
     152           0 : }
     153             : 
     154           0 : int io_mkdirat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
     155             : {
     156           0 :         struct io_mkdir *mkd = io_kiocb_to_cmd(req, struct io_mkdir);
     157             :         const char __user *fname;
     158             : 
     159           0 :         if (sqe->off || sqe->rw_flags || sqe->buf_index || sqe->splice_fd_in)
     160             :                 return -EINVAL;
     161           0 :         if (unlikely(req->flags & REQ_F_FIXED_FILE))
     162             :                 return -EBADF;
     163             : 
     164           0 :         mkd->dfd = READ_ONCE(sqe->fd);
     165           0 :         mkd->mode = READ_ONCE(sqe->len);
     166             : 
     167           0 :         fname = u64_to_user_ptr(READ_ONCE(sqe->addr));
     168           0 :         mkd->filename = getname(fname);
     169           0 :         if (IS_ERR(mkd->filename))
     170           0 :                 return PTR_ERR(mkd->filename);
     171             : 
     172           0 :         req->flags |= REQ_F_NEED_CLEANUP;
     173           0 :         req->flags |= REQ_F_FORCE_ASYNC;
     174           0 :         return 0;
     175             : }
     176             : 
     177           0 : int io_mkdirat(struct io_kiocb *req, unsigned int issue_flags)
     178             : {
     179           0 :         struct io_mkdir *mkd = io_kiocb_to_cmd(req, struct io_mkdir);
     180             :         int ret;
     181             : 
     182           0 :         WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
     183             : 
     184           0 :         ret = do_mkdirat(mkd->dfd, mkd->filename, mkd->mode);
     185             : 
     186           0 :         req->flags &= ~REQ_F_NEED_CLEANUP;
     187           0 :         io_req_set_res(req, ret, 0);
     188           0 :         return IOU_OK;
     189             : }
     190             : 
     191           0 : void io_mkdirat_cleanup(struct io_kiocb *req)
     192             : {
     193           0 :         struct io_mkdir *md = io_kiocb_to_cmd(req, struct io_mkdir);
     194             : 
     195           0 :         putname(md->filename);
     196           0 : }
     197             : 
     198           0 : int io_symlinkat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
     199             : {
     200           0 :         struct io_link *sl = io_kiocb_to_cmd(req, struct io_link);
     201             :         const char __user *oldpath, *newpath;
     202             : 
     203           0 :         if (sqe->len || sqe->rw_flags || sqe->buf_index || sqe->splice_fd_in)
     204             :                 return -EINVAL;
     205           0 :         if (unlikely(req->flags & REQ_F_FIXED_FILE))
     206             :                 return -EBADF;
     207             : 
     208           0 :         sl->new_dfd = READ_ONCE(sqe->fd);
     209           0 :         oldpath = u64_to_user_ptr(READ_ONCE(sqe->addr));
     210           0 :         newpath = u64_to_user_ptr(READ_ONCE(sqe->addr2));
     211             : 
     212           0 :         sl->oldpath = getname(oldpath);
     213           0 :         if (IS_ERR(sl->oldpath))
     214           0 :                 return PTR_ERR(sl->oldpath);
     215             : 
     216           0 :         sl->newpath = getname(newpath);
     217           0 :         if (IS_ERR(sl->newpath)) {
     218           0 :                 putname(sl->oldpath);
     219           0 :                 return PTR_ERR(sl->newpath);
     220             :         }
     221             : 
     222           0 :         req->flags |= REQ_F_NEED_CLEANUP;
     223           0 :         req->flags |= REQ_F_FORCE_ASYNC;
     224           0 :         return 0;
     225             : }
     226             : 
     227           0 : int io_symlinkat(struct io_kiocb *req, unsigned int issue_flags)
     228             : {
     229           0 :         struct io_link *sl = io_kiocb_to_cmd(req, struct io_link);
     230             :         int ret;
     231             : 
     232           0 :         WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
     233             : 
     234           0 :         ret = do_symlinkat(sl->oldpath, sl->new_dfd, sl->newpath);
     235             : 
     236           0 :         req->flags &= ~REQ_F_NEED_CLEANUP;
     237           0 :         io_req_set_res(req, ret, 0);
     238           0 :         return IOU_OK;
     239             : }
     240             : 
     241           0 : int io_linkat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
     242             : {
     243           0 :         struct io_link *lnk = io_kiocb_to_cmd(req, struct io_link);
     244             :         const char __user *oldf, *newf;
     245             : 
     246           0 :         if (sqe->rw_flags || sqe->buf_index || sqe->splice_fd_in)
     247             :                 return -EINVAL;
     248           0 :         if (unlikely(req->flags & REQ_F_FIXED_FILE))
     249             :                 return -EBADF;
     250             : 
     251           0 :         lnk->old_dfd = READ_ONCE(sqe->fd);
     252           0 :         lnk->new_dfd = READ_ONCE(sqe->len);
     253           0 :         oldf = u64_to_user_ptr(READ_ONCE(sqe->addr));
     254           0 :         newf = u64_to_user_ptr(READ_ONCE(sqe->addr2));
     255           0 :         lnk->flags = READ_ONCE(sqe->hardlink_flags);
     256             : 
     257           0 :         lnk->oldpath = getname(oldf);
     258           0 :         if (IS_ERR(lnk->oldpath))
     259           0 :                 return PTR_ERR(lnk->oldpath);
     260             : 
     261           0 :         lnk->newpath = getname(newf);
     262           0 :         if (IS_ERR(lnk->newpath)) {
     263           0 :                 putname(lnk->oldpath);
     264           0 :                 return PTR_ERR(lnk->newpath);
     265             :         }
     266             : 
     267           0 :         req->flags |= REQ_F_NEED_CLEANUP;
     268           0 :         req->flags |= REQ_F_FORCE_ASYNC;
     269           0 :         return 0;
     270             : }
     271             : 
     272           0 : int io_linkat(struct io_kiocb *req, unsigned int issue_flags)
     273             : {
     274           0 :         struct io_link *lnk = io_kiocb_to_cmd(req, struct io_link);
     275             :         int ret;
     276             : 
     277           0 :         WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
     278             : 
     279           0 :         ret = do_linkat(lnk->old_dfd, lnk->oldpath, lnk->new_dfd,
     280             :                                 lnk->newpath, lnk->flags);
     281             : 
     282           0 :         req->flags &= ~REQ_F_NEED_CLEANUP;
     283           0 :         io_req_set_res(req, ret, 0);
     284           0 :         return IOU_OK;
     285             : }
     286             : 
     287           0 : void io_link_cleanup(struct io_kiocb *req)
     288             : {
     289           0 :         struct io_link *sl = io_kiocb_to_cmd(req, struct io_link);
     290             : 
     291           0 :         putname(sl->oldpath);
     292           0 :         putname(sl->newpath);
     293           0 : }

Generated by: LCOV version 1.14