From 27600805e62f800bacf990354632eae4e487d34c Mon Sep 17 00:00:00 2001 From: Yazen Ghannam Date: Thu, 3 Sep 2026 10:43:25 -0500 Subject: x86/amd_node: Fix PCI device reference counting in amd_smn_init() The local "root" pointer is a temporary variable used during the device search. Therefore, refcount related to the search iterators should be cleaned up after the search is complete. Use the __free() cleanup macro to ensure the refcount is decremented when the temporary pointer goes out of scope. Additionally, increment the refcount when caching a root pointer. This ensures the in-use refcount is separate from the temporary search refcounting. Finally, drop the redundant "root = NULL" before the second search loop. The pci_get_class() iterator always decrements the refcount of its "from" argument, so the first loop can only fall through with "root" already NULL. Fixes: 0a4b61d9c2e4 ("x86/amd_node: Fix AMD root device caching") Closes: https://sashiko.dev/#/patchset/20260806160159.230453-1-jason.andryuk%40amd.com Reported-by: Sashiko Assisted-by: LLM Signed-off-by: Yazen Ghannam Signed-off-by: Borislav Petkov (AMD) Reviewed-by: Mario Limonciello (AMD) Cc: Link: https://patch.msgid.link/20260903154325.74343-1-yazen.ghannam@amd.com --- io_uring/xattr.c | 197 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 io_uring/xattr.c (limited to 'io_uring/xattr.c') diff --git a/io_uring/xattr.c b/io_uring/xattr.c new file mode 100644 index 000000000..5303df3f2 --- /dev/null +++ b/io_uring/xattr.c @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "../fs/internal.h" + +#include "io_uring.h" +#include "xattr.h" + +struct io_xattr { + struct file *file; + struct kernel_xattr_ctx ctx; + struct delayed_filename filename; +}; + +void io_xattr_cleanup(struct io_kiocb *req) +{ + struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); + + dismiss_delayed_filename(&ix->filename); + kfree(ix->ctx.kname); + kvfree(ix->ctx.kvalue); +} + +static void io_xattr_finish(struct io_kiocb *req, int ret) +{ + req->flags &= ~REQ_F_NEED_CLEANUP; + + io_xattr_cleanup(req); + io_req_set_res(req, ret, 0); +} + +static int __io_getxattr_prep(struct io_kiocb *req, + const struct io_uring_sqe *sqe) +{ + struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); + const char __user *name; + int ret; + + INIT_DELAYED_FILENAME(&ix->filename); + ix->ctx.kvalue = NULL; + name = u64_to_user_ptr(READ_ONCE(sqe->addr)); + ix->ctx.value = u64_to_user_ptr(READ_ONCE(sqe->addr2)); + ix->ctx.size = READ_ONCE(sqe->len); + ix->ctx.flags = READ_ONCE(sqe->xattr_flags); + + if (ix->ctx.flags) + return -EINVAL; + + ix->ctx.kname = kmalloc_obj(*ix->ctx.kname); + if (!ix->ctx.kname) + return -ENOMEM; + + ret = import_xattr_name(ix->ctx.kname, name); + if (ret) { + kfree(ix->ctx.kname); + return ret; + } + + req->flags |= REQ_F_NEED_CLEANUP; + req->flags |= REQ_F_FORCE_ASYNC; + return 0; +} + +int io_fgetxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) +{ + return __io_getxattr_prep(req, sqe); +} + +int io_getxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) +{ + struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); + const char __user *path; + int ret; + + if (unlikely(req->flags & REQ_F_FIXED_FILE)) + return -EBADF; + + ret = __io_getxattr_prep(req, sqe); + if (ret) + return ret; + + path = u64_to_user_ptr(READ_ONCE(sqe->addr3)); + + return delayed_getname(&ix->filename, path); +} + +int io_fgetxattr(struct io_kiocb *req, unsigned int issue_flags) +{ + struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); + int ret; + + WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK); + + ret = file_getxattr(req->file, &ix->ctx); + io_xattr_finish(req, ret); + return IOU_COMPLETE; +} + +int io_getxattr(struct io_kiocb *req, unsigned int issue_flags) +{ + struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); + CLASS(filename_complete_delayed, name)(&ix->filename); + int ret; + + WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK); + + ret = filename_getxattr(AT_FDCWD, name, LOOKUP_FOLLOW, &ix->ctx); + io_xattr_finish(req, ret); + return IOU_COMPLETE; +} + +static int __io_setxattr_prep(struct io_kiocb *req, + const struct io_uring_sqe *sqe) +{ + struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); + const char __user *name; + int ret; + + INIT_DELAYED_FILENAME(&ix->filename); + name = u64_to_user_ptr(READ_ONCE(sqe->addr)); + ix->ctx.cvalue = u64_to_user_ptr(READ_ONCE(sqe->addr2)); + ix->ctx.kvalue = NULL; + ix->ctx.size = READ_ONCE(sqe->len); + ix->ctx.flags = READ_ONCE(sqe->xattr_flags); + + ix->ctx.kname = kmalloc_obj(*ix->ctx.kname); + if (!ix->ctx.kname) + return -ENOMEM; + + ret = setxattr_copy(name, &ix->ctx); + if (ret) { + kfree(ix->ctx.kname); + return ret; + } + + req->flags |= REQ_F_NEED_CLEANUP; + req->flags |= REQ_F_FORCE_ASYNC; + return 0; +} + +int io_setxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) +{ + struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); + const char __user *path; + int ret; + + if (unlikely(req->flags & REQ_F_FIXED_FILE)) + return -EBADF; + + ret = __io_setxattr_prep(req, sqe); + if (ret) + return ret; + + path = u64_to_user_ptr(READ_ONCE(sqe->addr3)); + + return delayed_getname(&ix->filename, path); +} + +int io_fsetxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) +{ + return __io_setxattr_prep(req, sqe); +} + +int io_fsetxattr(struct io_kiocb *req, unsigned int issue_flags) +{ + struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); + int ret; + + WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK); + + ret = file_setxattr(req->file, &ix->ctx); + io_xattr_finish(req, ret); + return IOU_COMPLETE; +} + +int io_setxattr(struct io_kiocb *req, unsigned int issue_flags) +{ + struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr); + CLASS(filename_complete_delayed, name)(&ix->filename); + int ret; + + WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK); + + ret = filename_setxattr(AT_FDCWD, name, LOOKUP_FOLLOW, &ix->ctx); + io_xattr_finish(req, ret); + return IOU_COMPLETE; +} -- cgit v1.3.1