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 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 if (unlikely(req->flags & REQ_F_FIXED_FILE)) 52 return -EBADF; 53 54 ix->filename = NULL; 55 ix->ctx.kvalue = NULL; 56 name = u64_to_user_ptr(READ_ONCE(sqe->addr)); 57 ix->ctx.cvalue = u64_to_user_ptr(READ_ONCE(sqe->addr2)); 58 ix->ctx.size = READ_ONCE(sqe->len); 59 ix->ctx.flags = READ_ONCE(sqe->xattr_flags); 60 61 if (ix->ctx.flags) 62 return -EINVAL; 63 64 ix->ctx.kname = kmalloc(sizeof(*ix->ctx.kname), GFP_KERNEL); 65 if (!ix->ctx.kname) 66 return -ENOMEM; 67 68 ret = strncpy_from_user(ix->ctx.kname->name, name, 69 sizeof(ix->ctx.kname->name)); 70 if (!ret || ret == sizeof(ix->ctx.kname->name)) 71 ret = -ERANGE; 72 if (ret < 0) { 73 kfree(ix->ctx.kname); 74 return ret; 75 } 76 77 req->flags |= REQ_F_NEED_CLEANUP; 78 return 0; 79 } 80 81 int io_fgetxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 82 { 83 return __io_getxattr_prep(req, sqe); 84 } 85 86 int io_getxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 87 { 88 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); 89 const char __user *path; 90 int ret; 91 92 ret = __io_getxattr_prep(req, sqe); 93 if (ret) 94 return ret; 95 96 path = u64_to_user_ptr(READ_ONCE(sqe->addr3)); 97 98 ix->filename = getname_flags(path, LOOKUP_FOLLOW, NULL); 99 if (IS_ERR(ix->filename)) { 100 ret = PTR_ERR(ix->filename); 101 ix->filename = NULL; 102 } 103 104 return ret; 105 } 106 107 int io_fgetxattr(struct io_kiocb *req, unsigned int issue_flags) 108 { 109 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); 110 int ret; 111 112 if (issue_flags & IO_URING_F_NONBLOCK) 113 return -EAGAIN; 114 115 ret = do_getxattr(mnt_idmap(req->file->f_path.mnt), 116 req->file->f_path.dentry, 117 &ix->ctx); 118 119 io_xattr_finish(req, ret); 120 return IOU_OK; 121 } 122 123 int io_getxattr(struct io_kiocb *req, unsigned int issue_flags) 124 { 125 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); 126 unsigned int lookup_flags = LOOKUP_FOLLOW; 127 struct path path; 128 int ret; 129 130 if (issue_flags & IO_URING_F_NONBLOCK) 131 return -EAGAIN; 132 133 retry: 134 ret = filename_lookup(AT_FDCWD, ix->filename, lookup_flags, &path, NULL); 135 if (!ret) { 136 ret = do_getxattr(mnt_idmap(path.mnt), path.dentry, &ix->ctx); 137 138 path_put(&path); 139 if (retry_estale(ret, lookup_flags)) { 140 lookup_flags |= LOOKUP_REVAL; 141 goto retry; 142 } 143 } 144 145 io_xattr_finish(req, ret); 146 return IOU_OK; 147 } 148 149 static int __io_setxattr_prep(struct io_kiocb *req, 150 const struct io_uring_sqe *sqe) 151 { 152 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); 153 const char __user *name; 154 int ret; 155 156 if (unlikely(req->flags & REQ_F_FIXED_FILE)) 157 return -EBADF; 158 159 ix->filename = NULL; 160 name = u64_to_user_ptr(READ_ONCE(sqe->addr)); 161 ix->ctx.cvalue = u64_to_user_ptr(READ_ONCE(sqe->addr2)); 162 ix->ctx.kvalue = NULL; 163 ix->ctx.size = READ_ONCE(sqe->len); 164 ix->ctx.flags = READ_ONCE(sqe->xattr_flags); 165 166 ix->ctx.kname = kmalloc(sizeof(*ix->ctx.kname), GFP_KERNEL); 167 if (!ix->ctx.kname) 168 return -ENOMEM; 169 170 ret = setxattr_copy(name, &ix->ctx); 171 if (ret) { 172 kfree(ix->ctx.kname); 173 return ret; 174 } 175 176 req->flags |= REQ_F_NEED_CLEANUP; 177 return 0; 178 } 179 180 int io_setxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 181 { 182 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); 183 const char __user *path; 184 int ret; 185 186 ret = __io_setxattr_prep(req, sqe); 187 if (ret) 188 return ret; 189 190 path = u64_to_user_ptr(READ_ONCE(sqe->addr3)); 191 192 ix->filename = getname_flags(path, LOOKUP_FOLLOW, NULL); 193 if (IS_ERR(ix->filename)) { 194 ret = PTR_ERR(ix->filename); 195 ix->filename = NULL; 196 } 197 198 return ret; 199 } 200 201 int io_fsetxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 202 { 203 return __io_setxattr_prep(req, sqe); 204 } 205 206 static int __io_setxattr(struct io_kiocb *req, unsigned int issue_flags, 207 const struct path *path) 208 { 209 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); 210 int ret; 211 212 ret = mnt_want_write(path->mnt); 213 if (!ret) { 214 ret = do_setxattr(mnt_idmap(path->mnt), path->dentry, &ix->ctx); 215 mnt_drop_write(path->mnt); 216 } 217 218 return ret; 219 } 220 221 int io_fsetxattr(struct io_kiocb *req, unsigned int issue_flags) 222 { 223 int ret; 224 225 if (issue_flags & IO_URING_F_NONBLOCK) 226 return -EAGAIN; 227 228 ret = __io_setxattr(req, issue_flags, &req->file->f_path); 229 io_xattr_finish(req, ret); 230 return IOU_OK; 231 } 232 233 int io_setxattr(struct io_kiocb *req, unsigned int issue_flags) 234 { 235 struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); 236 unsigned int lookup_flags = LOOKUP_FOLLOW; 237 struct path path; 238 int ret; 239 240 if (issue_flags & IO_URING_F_NONBLOCK) 241 return -EAGAIN; 242 243 retry: 244 ret = filename_lookup(AT_FDCWD, ix->filename, lookup_flags, &path, NULL); 245 if (!ret) { 246 ret = __io_setxattr(req, issue_flags, &path); 247 path_put(&path); 248 if (retry_estale(ret, lookup_flags)) { 249 lookup_flags |= LOOKUP_REVAL; 250 goto retry; 251 } 252 } 253 254 io_xattr_finish(req, ret); 255 return IOU_OK; 256 } 257