LCOV - code coverage report
Current view: top level - io_uring - xattr.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 112 0.0 %
Date: 2023-08-24 13:40:31 Functions: 0 12 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             : #include <linux/xattr.h>
      11             : 
      12             : #include <uapi/linux/io_uring.h>
      13             : 
      14             : #include "../fs/internal.h"
      15             : 
      16             : #include "io_uring.h"
      17             : #include "xattr.h"
      18             : 
      19             : struct io_xattr {
      20             :         struct file                     *file;
      21             :         struct xattr_ctx                ctx;
      22             :         struct filename                 *filename;
      23             : };
      24             : 
      25           0 : void io_xattr_cleanup(struct io_kiocb *req)
      26             : {
      27           0 :         struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
      28             : 
      29           0 :         if (ix->filename)
      30           0 :                 putname(ix->filename);
      31             : 
      32           0 :         kfree(ix->ctx.kname);
      33           0 :         kvfree(ix->ctx.kvalue);
      34           0 : }
      35             : 
      36             : static void io_xattr_finish(struct io_kiocb *req, int ret)
      37             : {
      38           0 :         req->flags &= ~REQ_F_NEED_CLEANUP;
      39             : 
      40           0 :         io_xattr_cleanup(req);
      41           0 :         io_req_set_res(req, ret, 0);
      42             : }
      43             : 
      44           0 : static int __io_getxattr_prep(struct io_kiocb *req,
      45             :                               const struct io_uring_sqe *sqe)
      46             : {
      47           0 :         struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
      48             :         const char __user *name;
      49             :         int ret;
      50             : 
      51           0 :         if (unlikely(req->flags & REQ_F_FIXED_FILE))
      52             :                 return -EBADF;
      53             : 
      54           0 :         ix->filename = NULL;
      55           0 :         ix->ctx.kvalue = NULL;
      56           0 :         name = u64_to_user_ptr(READ_ONCE(sqe->addr));
      57           0 :         ix->ctx.cvalue = u64_to_user_ptr(READ_ONCE(sqe->addr2));
      58           0 :         ix->ctx.size = READ_ONCE(sqe->len);
      59           0 :         ix->ctx.flags = READ_ONCE(sqe->xattr_flags);
      60             : 
      61           0 :         if (ix->ctx.flags)
      62             :                 return -EINVAL;
      63             : 
      64           0 :         ix->ctx.kname = kmalloc(sizeof(*ix->ctx.kname), GFP_KERNEL);
      65           0 :         if (!ix->ctx.kname)
      66             :                 return -ENOMEM;
      67             : 
      68           0 :         ret = strncpy_from_user(ix->ctx.kname->name, name,
      69             :                                 sizeof(ix->ctx.kname->name));
      70           0 :         if (!ret || ret == sizeof(ix->ctx.kname->name))
      71           0 :                 ret = -ERANGE;
      72           0 :         if (ret < 0) {
      73           0 :                 kfree(ix->ctx.kname);
      74           0 :                 return ret;
      75             :         }
      76             : 
      77           0 :         req->flags |= REQ_F_NEED_CLEANUP;
      78           0 :         req->flags |= REQ_F_FORCE_ASYNC;
      79           0 :         return 0;
      80             : }
      81             : 
      82           0 : int io_fgetxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
      83             : {
      84           0 :         return __io_getxattr_prep(req, sqe);
      85             : }
      86             : 
      87           0 : int io_getxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
      88             : {
      89           0 :         struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
      90             :         const char __user *path;
      91             :         int ret;
      92             : 
      93           0 :         ret = __io_getxattr_prep(req, sqe);
      94           0 :         if (ret)
      95             :                 return ret;
      96             : 
      97           0 :         path = u64_to_user_ptr(READ_ONCE(sqe->addr3));
      98             : 
      99           0 :         ix->filename = getname_flags(path, LOOKUP_FOLLOW, NULL);
     100           0 :         if (IS_ERR(ix->filename)) {
     101           0 :                 ret = PTR_ERR(ix->filename);
     102           0 :                 ix->filename = NULL;
     103             :         }
     104             : 
     105             :         return ret;
     106             : }
     107             : 
     108           0 : int io_fgetxattr(struct io_kiocb *req, unsigned int issue_flags)
     109             : {
     110           0 :         struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
     111             :         int ret;
     112             : 
     113           0 :         WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
     114             : 
     115           0 :         ret = do_getxattr(mnt_idmap(req->file->f_path.mnt),
     116           0 :                         req->file->f_path.dentry,
     117             :                         &ix->ctx);
     118             : 
     119           0 :         io_xattr_finish(req, ret);
     120           0 :         return IOU_OK;
     121             : }
     122             : 
     123           0 : int io_getxattr(struct io_kiocb *req, unsigned int issue_flags)
     124             : {
     125           0 :         struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
     126           0 :         unsigned int lookup_flags = LOOKUP_FOLLOW;
     127             :         struct path path;
     128             :         int ret;
     129             : 
     130           0 :         WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
     131             : 
     132             : retry:
     133           0 :         ret = filename_lookup(AT_FDCWD, ix->filename, lookup_flags, &path, NULL);
     134           0 :         if (!ret) {
     135           0 :                 ret = do_getxattr(mnt_idmap(path.mnt), path.dentry, &ix->ctx);
     136             : 
     137           0 :                 path_put(&path);
     138           0 :                 if (retry_estale(ret, lookup_flags)) {
     139             :                         lookup_flags |= LOOKUP_REVAL;
     140             :                         goto retry;
     141             :                 }
     142             :         }
     143             : 
     144           0 :         io_xattr_finish(req, ret);
     145           0 :         return IOU_OK;
     146             : }
     147             : 
     148           0 : static int __io_setxattr_prep(struct io_kiocb *req,
     149             :                         const struct io_uring_sqe *sqe)
     150             : {
     151           0 :         struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
     152             :         const char __user *name;
     153             :         int ret;
     154             : 
     155           0 :         if (unlikely(req->flags & REQ_F_FIXED_FILE))
     156             :                 return -EBADF;
     157             : 
     158           0 :         ix->filename = NULL;
     159           0 :         name = u64_to_user_ptr(READ_ONCE(sqe->addr));
     160           0 :         ix->ctx.cvalue = u64_to_user_ptr(READ_ONCE(sqe->addr2));
     161           0 :         ix->ctx.kvalue = NULL;
     162           0 :         ix->ctx.size = READ_ONCE(sqe->len);
     163           0 :         ix->ctx.flags = READ_ONCE(sqe->xattr_flags);
     164             : 
     165           0 :         ix->ctx.kname = kmalloc(sizeof(*ix->ctx.kname), GFP_KERNEL);
     166           0 :         if (!ix->ctx.kname)
     167             :                 return -ENOMEM;
     168             : 
     169           0 :         ret = setxattr_copy(name, &ix->ctx);
     170           0 :         if (ret) {
     171           0 :                 kfree(ix->ctx.kname);
     172           0 :                 return ret;
     173             :         }
     174             : 
     175           0 :         req->flags |= REQ_F_NEED_CLEANUP;
     176           0 :         req->flags |= REQ_F_FORCE_ASYNC;
     177           0 :         return 0;
     178             : }
     179             : 
     180           0 : int io_setxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
     181             : {
     182           0 :         struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
     183             :         const char __user *path;
     184             :         int ret;
     185             : 
     186           0 :         ret = __io_setxattr_prep(req, sqe);
     187           0 :         if (ret)
     188             :                 return ret;
     189             : 
     190           0 :         path = u64_to_user_ptr(READ_ONCE(sqe->addr3));
     191             : 
     192           0 :         ix->filename = getname_flags(path, LOOKUP_FOLLOW, NULL);
     193           0 :         if (IS_ERR(ix->filename)) {
     194           0 :                 ret = PTR_ERR(ix->filename);
     195           0 :                 ix->filename = NULL;
     196             :         }
     197             : 
     198             :         return ret;
     199             : }
     200             : 
     201           0 : int io_fsetxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
     202             : {
     203           0 :         return __io_setxattr_prep(req, sqe);
     204             : }
     205             : 
     206           0 : static int __io_setxattr(struct io_kiocb *req, unsigned int issue_flags,
     207             :                         const struct path *path)
     208             : {
     209           0 :         struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
     210             :         int ret;
     211             : 
     212           0 :         ret = mnt_want_write(path->mnt);
     213           0 :         if (!ret) {
     214           0 :                 ret = do_setxattr(mnt_idmap(path->mnt), path->dentry, &ix->ctx);
     215           0 :                 mnt_drop_write(path->mnt);
     216             :         }
     217             : 
     218           0 :         return ret;
     219             : }
     220             : 
     221           0 : int io_fsetxattr(struct io_kiocb *req, unsigned int issue_flags)
     222             : {
     223             :         int ret;
     224             : 
     225           0 :         WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
     226             : 
     227           0 :         ret = __io_setxattr(req, issue_flags, &req->file->f_path);
     228           0 :         io_xattr_finish(req, ret);
     229           0 :         return IOU_OK;
     230             : }
     231             : 
     232           0 : int io_setxattr(struct io_kiocb *req, unsigned int issue_flags)
     233             : {
     234           0 :         struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
     235           0 :         unsigned int lookup_flags = LOOKUP_FOLLOW;
     236             :         struct path path;
     237             :         int ret;
     238             : 
     239           0 :         WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
     240             : 
     241             : retry:
     242           0 :         ret = filename_lookup(AT_FDCWD, ix->filename, lookup_flags, &path, NULL);
     243           0 :         if (!ret) {
     244           0 :                 ret = __io_setxattr(req, issue_flags, &path);
     245           0 :                 path_put(&path);
     246           0 :                 if (retry_estale(ret, lookup_flags)) {
     247             :                         lookup_flags |= LOOKUP_REVAL;
     248             :                         goto retry;
     249             :                 }
     250             :         }
     251             : 
     252           0 :         io_xattr_finish(req, ret);
     253           0 :         return IOU_OK;
     254             : }

Generated by: LCOV version 1.14