15e2a18d9SJens Axboe // SPDX-License-Identifier: GPL-2.0 25e2a18d9SJens Axboe #include <linux/kernel.h> 35e2a18d9SJens Axboe #include <linux/errno.h> 45e2a18d9SJens Axboe #include <linux/fs.h> 55e2a18d9SJens Axboe #include <linux/file.h> 65e2a18d9SJens Axboe #include <linux/mm.h> 75e2a18d9SJens Axboe #include <linux/slab.h> 85e2a18d9SJens Axboe #include <linux/namei.h> 95e2a18d9SJens Axboe #include <linux/io_uring.h> 105e2a18d9SJens Axboe #include <linux/xattr.h> 115e2a18d9SJens Axboe 125e2a18d9SJens Axboe #include <uapi/linux/io_uring.h> 135e2a18d9SJens Axboe 145e2a18d9SJens Axboe #include "../fs/internal.h" 155e2a18d9SJens Axboe 165e2a18d9SJens Axboe #include "io_uring.h" 175e2a18d9SJens Axboe #include "xattr.h" 185e2a18d9SJens Axboe 195e2a18d9SJens Axboe struct io_xattr { 205e2a18d9SJens Axboe struct file *file; 21537c7662SChristian Göttsche struct kernel_xattr_ctx ctx; 225e2a18d9SJens Axboe struct filename *filename; 235e2a18d9SJens Axboe }; 245e2a18d9SJens Axboe 255e2a18d9SJens Axboe void io_xattr_cleanup(struct io_kiocb *req) 265e2a18d9SJens Axboe { 27f2ccb5aeSStefan Metzmacher struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); 285e2a18d9SJens Axboe 295e2a18d9SJens Axboe if (ix->filename) 305e2a18d9SJens Axboe putname(ix->filename); 315e2a18d9SJens Axboe 325e2a18d9SJens Axboe kfree(ix->ctx.kname); 335e2a18d9SJens Axboe kvfree(ix->ctx.kvalue); 345e2a18d9SJens Axboe } 355e2a18d9SJens Axboe 365e2a18d9SJens Axboe static void io_xattr_finish(struct io_kiocb *req, int ret) 375e2a18d9SJens Axboe { 385e2a18d9SJens Axboe req->flags &= ~REQ_F_NEED_CLEANUP; 395e2a18d9SJens Axboe 405e2a18d9SJens Axboe io_xattr_cleanup(req); 415e2a18d9SJens Axboe io_req_set_res(req, ret, 0); 425e2a18d9SJens Axboe } 435e2a18d9SJens Axboe 445e2a18d9SJens Axboe static int __io_getxattr_prep(struct io_kiocb *req, 455e2a18d9SJens Axboe const struct io_uring_sqe *sqe) 465e2a18d9SJens Axboe { 47f2ccb5aeSStefan Metzmacher struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); 485e2a18d9SJens Axboe const char __user *name; 495e2a18d9SJens Axboe int ret; 505e2a18d9SJens Axboe 515e2a18d9SJens Axboe ix->filename = NULL; 525e2a18d9SJens Axboe ix->ctx.kvalue = NULL; 535e2a18d9SJens Axboe name = u64_to_user_ptr(READ_ONCE(sqe->addr)); 54*0158005aSAl Viro ix->ctx.value = u64_to_user_ptr(READ_ONCE(sqe->addr2)); 555e2a18d9SJens Axboe ix->ctx.size = READ_ONCE(sqe->len); 565e2a18d9SJens Axboe ix->ctx.flags = READ_ONCE(sqe->xattr_flags); 575e2a18d9SJens Axboe 585e2a18d9SJens Axboe if (ix->ctx.flags) 595e2a18d9SJens Axboe return -EINVAL; 605e2a18d9SJens Axboe 615e2a18d9SJens Axboe ix->ctx.kname = kmalloc(sizeof(*ix->ctx.kname), GFP_KERNEL); 625e2a18d9SJens Axboe if (!ix->ctx.kname) 635e2a18d9SJens Axboe return -ENOMEM; 645e2a18d9SJens Axboe 65a10c4c5eSAl Viro ret = import_xattr_name(ix->ctx.kname, name); 66a10c4c5eSAl Viro if (ret) { 675e2a18d9SJens Axboe kfree(ix->ctx.kname); 685e2a18d9SJens Axboe return ret; 695e2a18d9SJens Axboe } 705e2a18d9SJens Axboe 715e2a18d9SJens Axboe req->flags |= REQ_F_NEED_CLEANUP; 72aebb224fSDylan Yudaken req->flags |= REQ_F_FORCE_ASYNC; 735e2a18d9SJens Axboe return 0; 745e2a18d9SJens Axboe } 755e2a18d9SJens Axboe 765e2a18d9SJens Axboe int io_fgetxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 775e2a18d9SJens Axboe { 785e2a18d9SJens Axboe return __io_getxattr_prep(req, sqe); 795e2a18d9SJens Axboe } 805e2a18d9SJens Axboe 815e2a18d9SJens Axboe int io_getxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 825e2a18d9SJens Axboe { 83f2ccb5aeSStefan Metzmacher struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); 845e2a18d9SJens Axboe const char __user *path; 855e2a18d9SJens Axboe int ret; 865e2a18d9SJens Axboe 87dc7e76baSJens Axboe if (unlikely(req->flags & REQ_F_FIXED_FILE)) 88dc7e76baSJens Axboe return -EBADF; 89dc7e76baSJens Axboe 905e2a18d9SJens Axboe ret = __io_getxattr_prep(req, sqe); 915e2a18d9SJens Axboe if (ret) 925e2a18d9SJens Axboe return ret; 935e2a18d9SJens Axboe 945e2a18d9SJens Axboe path = u64_to_user_ptr(READ_ONCE(sqe->addr3)); 955e2a18d9SJens Axboe 96b8cdd253SAl Viro ix->filename = getname(path); 97*0158005aSAl Viro if (IS_ERR(ix->filename)) 98*0158005aSAl Viro return PTR_ERR(ix->filename); 995e2a18d9SJens Axboe 100*0158005aSAl Viro return 0; 1015e2a18d9SJens Axboe } 1025e2a18d9SJens Axboe 1035e2a18d9SJens Axboe int io_fgetxattr(struct io_kiocb *req, unsigned int issue_flags) 1045e2a18d9SJens Axboe { 105f2ccb5aeSStefan Metzmacher struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); 1065e2a18d9SJens Axboe int ret; 1075e2a18d9SJens Axboe 108aebb224fSDylan Yudaken WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK); 1095e2a18d9SJens Axboe 110*0158005aSAl Viro ret = file_getxattr(req->file, &ix->ctx); 1115e2a18d9SJens Axboe io_xattr_finish(req, ret); 1125e2a18d9SJens Axboe return IOU_OK; 1135e2a18d9SJens Axboe } 1145e2a18d9SJens Axboe 1155e2a18d9SJens Axboe int io_getxattr(struct io_kiocb *req, unsigned int issue_flags) 1165e2a18d9SJens Axboe { 117f2ccb5aeSStefan Metzmacher struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); 1185e2a18d9SJens Axboe int ret; 1195e2a18d9SJens Axboe 120aebb224fSDylan Yudaken WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK); 1215e2a18d9SJens Axboe 122*0158005aSAl Viro ret = filename_getxattr(AT_FDCWD, ix->filename, LOOKUP_FOLLOW, &ix->ctx); 123*0158005aSAl Viro ix->filename = NULL; 1245e2a18d9SJens Axboe io_xattr_finish(req, ret); 1255e2a18d9SJens Axboe return IOU_OK; 1265e2a18d9SJens Axboe } 1275e2a18d9SJens Axboe 1285e2a18d9SJens Axboe static int __io_setxattr_prep(struct io_kiocb *req, 1295e2a18d9SJens Axboe const struct io_uring_sqe *sqe) 1305e2a18d9SJens Axboe { 131f2ccb5aeSStefan Metzmacher struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); 1325e2a18d9SJens Axboe const char __user *name; 1335e2a18d9SJens Axboe int ret; 1345e2a18d9SJens Axboe 1355e2a18d9SJens Axboe ix->filename = NULL; 1365e2a18d9SJens Axboe name = u64_to_user_ptr(READ_ONCE(sqe->addr)); 1375e2a18d9SJens Axboe ix->ctx.cvalue = u64_to_user_ptr(READ_ONCE(sqe->addr2)); 1385e2a18d9SJens Axboe ix->ctx.kvalue = NULL; 1395e2a18d9SJens Axboe ix->ctx.size = READ_ONCE(sqe->len); 1405e2a18d9SJens Axboe ix->ctx.flags = READ_ONCE(sqe->xattr_flags); 1415e2a18d9SJens Axboe 1425e2a18d9SJens Axboe ix->ctx.kname = kmalloc(sizeof(*ix->ctx.kname), GFP_KERNEL); 1435e2a18d9SJens Axboe if (!ix->ctx.kname) 1445e2a18d9SJens Axboe return -ENOMEM; 1455e2a18d9SJens Axboe 1465e2a18d9SJens Axboe ret = setxattr_copy(name, &ix->ctx); 1475e2a18d9SJens Axboe if (ret) { 1485e2a18d9SJens Axboe kfree(ix->ctx.kname); 1495e2a18d9SJens Axboe return ret; 1505e2a18d9SJens Axboe } 1515e2a18d9SJens Axboe 1525e2a18d9SJens Axboe req->flags |= REQ_F_NEED_CLEANUP; 153aebb224fSDylan Yudaken req->flags |= REQ_F_FORCE_ASYNC; 1545e2a18d9SJens Axboe return 0; 1555e2a18d9SJens Axboe } 1565e2a18d9SJens Axboe 1575e2a18d9SJens Axboe int io_setxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 1585e2a18d9SJens Axboe { 159f2ccb5aeSStefan Metzmacher struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); 1605e2a18d9SJens Axboe const char __user *path; 1615e2a18d9SJens Axboe int ret; 1625e2a18d9SJens Axboe 163dc7e76baSJens Axboe if (unlikely(req->flags & REQ_F_FIXED_FILE)) 164dc7e76baSJens Axboe return -EBADF; 165dc7e76baSJens Axboe 1665e2a18d9SJens Axboe ret = __io_setxattr_prep(req, sqe); 1675e2a18d9SJens Axboe if (ret) 1685e2a18d9SJens Axboe return ret; 1695e2a18d9SJens Axboe 1705e2a18d9SJens Axboe path = u64_to_user_ptr(READ_ONCE(sqe->addr3)); 1715e2a18d9SJens Axboe 172b8cdd253SAl Viro ix->filename = getname(path); 17366d7ac6bSAl Viro if (IS_ERR(ix->filename)) 17466d7ac6bSAl Viro return PTR_ERR(ix->filename); 1755e2a18d9SJens Axboe 17666d7ac6bSAl Viro return 0; 1775e2a18d9SJens Axboe } 1785e2a18d9SJens Axboe 1795e2a18d9SJens Axboe int io_fsetxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 1805e2a18d9SJens Axboe { 1815e2a18d9SJens Axboe return __io_setxattr_prep(req, sqe); 1825e2a18d9SJens Axboe } 1835e2a18d9SJens Axboe 18466d7ac6bSAl Viro int io_fsetxattr(struct io_kiocb *req, unsigned int issue_flags) 1855e2a18d9SJens Axboe { 186f2ccb5aeSStefan Metzmacher struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); 1875e2a18d9SJens Axboe int ret; 1885e2a18d9SJens Axboe 189aebb224fSDylan Yudaken WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK); 1905e2a18d9SJens Axboe 19166d7ac6bSAl Viro ret = file_setxattr(req->file, &ix->ctx); 1925e2a18d9SJens Axboe io_xattr_finish(req, ret); 1935e2a18d9SJens Axboe return IOU_OK; 1945e2a18d9SJens Axboe } 1955e2a18d9SJens Axboe 1965e2a18d9SJens Axboe int io_setxattr(struct io_kiocb *req, unsigned int issue_flags) 1975e2a18d9SJens Axboe { 198f2ccb5aeSStefan Metzmacher struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); 1995e2a18d9SJens Axboe int ret; 2005e2a18d9SJens Axboe 201aebb224fSDylan Yudaken WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK); 2025e2a18d9SJens Axboe 20366d7ac6bSAl Viro ret = filename_setxattr(AT_FDCWD, ix->filename, LOOKUP_FOLLOW, &ix->ctx); 20466d7ac6bSAl Viro ix->filename = NULL; 2055e2a18d9SJens Axboe io_xattr_finish(req, ret); 2065e2a18d9SJens Axboe return IOU_OK; 2075e2a18d9SJens Axboe } 208