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); 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); 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); 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); 110 int ret; 111 112 if (issue_flags & IO_URING_F_NONBLOCK) 113 return -EAGAIN; 114 115 ret = do_getxattr(mnt_user_ns(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); 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_user_ns(path.mnt), 137 path.dentry, 138 &ix->ctx); 139 140 path_put(&path); 141 if (retry_estale(ret, lookup_flags)) { 142 lookup_flags |= LOOKUP_REVAL; 143 goto retry; 144 } 145 } 146 147 io_xattr_finish(req, ret); 148 return IOU_OK; 149 } 150 151 static int __io_setxattr_prep(struct io_kiocb *req, 152 const struct io_uring_sqe *sqe) 153 { 154 struct io_xattr *ix = io_kiocb_to_cmd(req); 155 const char __user *name; 156 int ret; 157 158 if (unlikely(req->flags & REQ_F_FIXED_FILE)) 159 return -EBADF; 160 161 ix->filename = NULL; 162 name = u64_to_user_ptr(READ_ONCE(sqe->addr)); 163 ix->ctx.cvalue = u64_to_user_ptr(READ_ONCE(sqe->addr2)); 164 ix->ctx.kvalue = NULL; 165 ix->ctx.size = READ_ONCE(sqe->len); 166 ix->ctx.flags = READ_ONCE(sqe->xattr_flags); 167 168 ix->ctx.kname = kmalloc(sizeof(*ix->ctx.kname), GFP_KERNEL); 169 if (!ix->ctx.kname) 170 return -ENOMEM; 171 172 ret = setxattr_copy(name, &ix->ctx); 173 if (ret) { 174 kfree(ix->ctx.kname); 175 return ret; 176 } 177 178 req->flags |= REQ_F_NEED_CLEANUP; 179 return 0; 180 } 181 182 int io_setxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 183 { 184 struct io_xattr *ix = io_kiocb_to_cmd(req); 185 const char __user *path; 186 int ret; 187 188 ret = __io_setxattr_prep(req, sqe); 189 if (ret) 190 return ret; 191 192 path = u64_to_user_ptr(READ_ONCE(sqe->addr3)); 193 194 ix->filename = getname_flags(path, LOOKUP_FOLLOW, NULL); 195 if (IS_ERR(ix->filename)) { 196 ret = PTR_ERR(ix->filename); 197 ix->filename = NULL; 198 } 199 200 return ret; 201 } 202 203 int io_fsetxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 204 { 205 return __io_setxattr_prep(req, sqe); 206 } 207 208 static int __io_setxattr(struct io_kiocb *req, unsigned int issue_flags, 209 struct path *path) 210 { 211 struct io_xattr *ix = io_kiocb_to_cmd(req); 212 int ret; 213 214 ret = mnt_want_write(path->mnt); 215 if (!ret) { 216 ret = do_setxattr(mnt_user_ns(path->mnt), path->dentry, &ix->ctx); 217 mnt_drop_write(path->mnt); 218 } 219 220 return ret; 221 } 222 223 int io_fsetxattr(struct io_kiocb *req, unsigned int issue_flags) 224 { 225 int ret; 226 227 if (issue_flags & IO_URING_F_NONBLOCK) 228 return -EAGAIN; 229 230 ret = __io_setxattr(req, issue_flags, &req->file->f_path); 231 io_xattr_finish(req, ret); 232 return IOU_OK; 233 } 234 235 int io_setxattr(struct io_kiocb *req, unsigned int issue_flags) 236 { 237 struct io_xattr *ix = io_kiocb_to_cmd(req); 238 unsigned int lookup_flags = LOOKUP_FOLLOW; 239 struct path path; 240 int ret; 241 242 if (issue_flags & IO_URING_F_NONBLOCK) 243 return -EAGAIN; 244 245 retry: 246 ret = filename_lookup(AT_FDCWD, ix->filename, lookup_flags, &path, NULL); 247 if (!ret) { 248 ret = __io_setxattr(req, issue_flags, &path); 249 path_put(&path); 250 if (retry_estale(ret, lookup_flags)) { 251 lookup_flags |= LOOKUP_REVAL; 252 goto retry; 253 } 254 } 255 256 io_xattr_finish(req, ret); 257 return IOU_OK; 258 } 259