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 kernel_xattr_ctx ctx; 22 struct filename *filename; 23 }; 24 25 void 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 36 static 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 44 static 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 76 int io_fgetxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 77 { 78 return __io_getxattr_prep(req, sqe); 79 } 80 81 int 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 103 int 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 115 int 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 128 static 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 157 int 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 179 int io_fsetxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 180 { 181 return __io_setxattr_prep(req, sqe); 182 } 183 184 int 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 196 int 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 } 208