at for-next 4.7 kB view raw
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 19struct io_xattr { 20 struct file *file; 21 struct kernel_xattr_ctx ctx; 22 struct filename *filename; 23}; 24 25void io_xattr_cleanup(struct io_kiocb *req) 26{ 27 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); 28 29 if (ix->filename) 30 putname(ix->filename); 31 32 kfree(ix->ctx.kname); 33 kvfree(ix->ctx.kvalue); 34} 35 36static void io_xattr_finish(struct io_kiocb *req, int ret) 37{ 38 req->flags &= ~REQ_F_NEED_CLEANUP; 39 40 io_xattr_cleanup(req); 41 io_req_set_res(req, ret, 0); 42} 43 44static int __io_getxattr_prep(struct io_kiocb *req, 45 const struct io_uring_sqe *sqe) 46{ 47 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); 48 const char __user *name; 49 int ret; 50 51 ix->filename = NULL; 52 ix->ctx.kvalue = NULL; 53 name = u64_to_user_ptr(READ_ONCE(sqe->addr)); 54 ix->ctx.value = u64_to_user_ptr(READ_ONCE(sqe->addr2)); 55 ix->ctx.size = READ_ONCE(sqe->len); 56 ix->ctx.flags = READ_ONCE(sqe->xattr_flags); 57 58 if (ix->ctx.flags) 59 return -EINVAL; 60 61 ix->ctx.kname = kmalloc(sizeof(*ix->ctx.kname), GFP_KERNEL); 62 if (!ix->ctx.kname) 63 return -ENOMEM; 64 65 ret = import_xattr_name(ix->ctx.kname, name); 66 if (ret) { 67 kfree(ix->ctx.kname); 68 return ret; 69 } 70 71 req->flags |= REQ_F_NEED_CLEANUP; 72 req->flags |= REQ_F_FORCE_ASYNC; 73 return 0; 74} 75 76int io_fgetxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 77{ 78 return __io_getxattr_prep(req, sqe); 79} 80 81int io_getxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 82{ 83 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); 84 const char __user *path; 85 int ret; 86 87 if (unlikely(req->flags & REQ_F_FIXED_FILE)) 88 return -EBADF; 89 90 ret = __io_getxattr_prep(req, sqe); 91 if (ret) 92 return ret; 93 94 path = u64_to_user_ptr(READ_ONCE(sqe->addr3)); 95 96 ix->filename = getname(path); 97 if (IS_ERR(ix->filename)) 98 return PTR_ERR(ix->filename); 99 100 return 0; 101} 102 103int io_fgetxattr(struct io_kiocb *req, unsigned int issue_flags) 104{ 105 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); 106 int ret; 107 108 WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK); 109 110 ret = file_getxattr(req->file, &ix->ctx); 111 io_xattr_finish(req, ret); 112 return IOU_OK; 113} 114 115int io_getxattr(struct io_kiocb *req, unsigned int issue_flags) 116{ 117 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); 118 int ret; 119 120 WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK); 121 122 ret = filename_getxattr(AT_FDCWD, ix->filename, LOOKUP_FOLLOW, &ix->ctx); 123 ix->filename = NULL; 124 io_xattr_finish(req, ret); 125 return IOU_OK; 126} 127 128static int __io_setxattr_prep(struct io_kiocb *req, 129 const struct io_uring_sqe *sqe) 130{ 131 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); 132 const char __user *name; 133 int ret; 134 135 ix->filename = NULL; 136 name = u64_to_user_ptr(READ_ONCE(sqe->addr)); 137 ix->ctx.cvalue = u64_to_user_ptr(READ_ONCE(sqe->addr2)); 138 ix->ctx.kvalue = NULL; 139 ix->ctx.size = READ_ONCE(sqe->len); 140 ix->ctx.flags = READ_ONCE(sqe->xattr_flags); 141 142 ix->ctx.kname = kmalloc(sizeof(*ix->ctx.kname), GFP_KERNEL); 143 if (!ix->ctx.kname) 144 return -ENOMEM; 145 146 ret = setxattr_copy(name, &ix->ctx); 147 if (ret) { 148 kfree(ix->ctx.kname); 149 return ret; 150 } 151 152 req->flags |= REQ_F_NEED_CLEANUP; 153 req->flags |= REQ_F_FORCE_ASYNC; 154 return 0; 155} 156 157int io_setxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 158{ 159 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); 160 const char __user *path; 161 int ret; 162 163 if (unlikely(req->flags & REQ_F_FIXED_FILE)) 164 return -EBADF; 165 166 ret = __io_setxattr_prep(req, sqe); 167 if (ret) 168 return ret; 169 170 path = u64_to_user_ptr(READ_ONCE(sqe->addr3)); 171 172 ix->filename = getname(path); 173 if (IS_ERR(ix->filename)) 174 return PTR_ERR(ix->filename); 175 176 return 0; 177} 178 179int io_fsetxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 180{ 181 return __io_setxattr_prep(req, sqe); 182} 183 184int io_fsetxattr(struct io_kiocb *req, unsigned int issue_flags) 185{ 186 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); 187 int ret; 188 189 WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK); 190 191 ret = file_setxattr(req->file, &ix->ctx); 192 io_xattr_finish(req, ret); 193 return IOU_OK; 194} 195 196int io_setxattr(struct io_kiocb *req, unsigned int issue_flags) 197{ 198 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); 199 int ret; 200 201 WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK); 202 203 ret = filename_setxattr(AT_FDCWD, ix->filename, LOOKUP_FOLLOW, &ix->ctx); 204 ix->filename = NULL; 205 io_xattr_finish(req, ret); 206 return IOU_OK; 207}