From nobody Mon Sep 28 17:49:53 2026 Received: from mail-m49197.qiye.163.com (mail-m49197.qiye.163.com [45.254.49.197]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 957EB2F8EAA; Sun, 27 Sep 2026 08:20:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.254.49.197 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790497236; cv=none; b=H0on87v+EZLGMTyr2ZSEakFd+bjobJb/rwNiTnovB1Gs5EESJwZIlCZ+N9UMtAWda7PTswqdJXahUBGHl4n/5C6sys8IAK9zLQbImE4VFcFDPBdnwRcNEfE7yDaaXtQI9yasJUOtzynpdK+hi/tnFq/4fhJWq6ISKMHaag3xy+c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790497236; c=relaxed/simple; bh=UxRIepd9CwHfhzVnTwJXcA5lIX7ZBdjXk0+/LMHOYF0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=CgBJsLEzmuGQbNCEsMHCKHPlMrKNB+ap0ivl4vikiyN9vWDlw8N5GbEzuZeUJHeTI2/jo+YriRDJ7c/psaDPXLREQU0WeLN2J0RxVYVY20r6j6jXft7DA2/9m6xKpuSKNqNx9yDr/aGSN+YkGLNGw1ZR06HLCGBohkmK85iqQVw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=seu.edu.cn; spf=pass smtp.mailfrom=seu.edu.cn; dkim=pass (1024-bit key) header.d=seu.edu.cn header.i=@seu.edu.cn header.b=VZHAPQrn; arc=none smtp.client-ip=45.254.49.197 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=seu.edu.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=seu.edu.cn Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=seu.edu.cn header.i=@seu.edu.cn header.b="VZHAPQrn" Received: from PC-202605011814.localdomain (unknown [222.191.246.242]) by smtp.qiye.163.com (Hmail) with ESMTP id 4f3a443fa; Sun, 27 Sep 2026 16:20:24 +0800 (GMT+08:00) From: Runyu Xiao To: Christoph Hellwig Cc: Breno Leitao , Andreas Hindborg , Sagi Grimberg , Chaitanya Kulkarni , Keith Busch , Logan Gunthorpe , "Martin K . Petersen" , Lee Duncan , Hannes Reinecke , Nicholas Bellinger , linux-nvme@lists.infradead.org, linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, linux-kernel@vger.kernel.org, stable@vger.kernel.org, Runyu Xiao , Jianhao Xu Subject: [PATCH v7 1/4] fs: configfs: add helpers for opening non-configfs paths Date: Sun, 27 Sep 2026 16:20:08 +0800 Message-Id: <20260927082011.638723-2-runyu.xiao@seu.edu.cn> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260927082011.638723-1-runyu.xiao@seu.edu.cn> References: <20260927082011.638723-1-runyu.xiao@seu.edu.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-HM-Tid: 0aa0e1f377d203a1kunm12f6b69c1ac336 X-HM-MType: 10 X-HM-Spam-Status: e1kfGhgUHx5ZQUpXWQgPGg8OCBgUHx5ZQUlOS1dZFg8aDwILHllBWSg2Ly tZV1koWUFITzdXWRgWCB1ZQUpXWS1ZQUlXWQ8JGhUIEh9ZQVlCGBkZVk4aHkhJQx5LSE5CGVYeHw 5VEwETFhoSFyQUDg9ZV1kYEgtZQVlJSUlVSkJKVUlPTVVJT0lZV1kWGg8SFR0UWUFZT0tIVUpLSE pPSExVSktLVUpCS0tZBg++ DKIM-Signature: a=rsa-sha256; b=VZHAPQrn96pCV7pTnfuY6/AdqV/6JKT6ykY8D5GikQ0gvRv5efzXtxhlT4GRiuxYrsLq00MEmqRdTZPSxCSrdOe6wO3eAusLhf1G0blildWHc31P145qDG/tIXY7uU27DRWBe7nSzsvFiiFb2RTJim0YMOPfuPAyB+ilcU5lOzk=; c=relaxed/relaxed; s=default; d=seu.edu.cn; v=1; bh=d5JnXFH+gOpA+ULZ4kh2lFWrt905jPAi3bCsy9qIaq0=; h=date:mime-version:subject:message-id:from; Content-Type: text/plain; charset="utf-8" Configfs store callbacks hold frag_sem while they run. Reopening a path that resolves to configfs from such a callback can acquire the same non-recursive semaphore again. Add configfs_file_open() for configured pathnames and configfs_open_root() for paths relative to a resolved root. Reject configfs roots before using file_open_root() so the normal open checks remain in place. Assisted-by: LLM Codex Signed-off-by: Runyu Xiao Reviewed-by: Christoph Hellwig --- fs/configfs/mount.c | 57 ++++++++++++++++++++++++++++++++++++++++ include/linux/configfs.h | 5 ++++ 2 files changed, 62 insertions(+) diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c index d8cac1cbf3bd5..aa79be05dd5bc 100644 --- a/fs/configfs/mount.c +++ b/fs/configfs/mount.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -118,6 +119,62 @@ static struct file_system_type configfs_fs_type =3D { }; MODULE_ALIAS_FS("configfs"); =20 +/** + * configfs_open_root - open a path below a non-configfs root + * @root: resolved root path + * @name: path relative to @root + * @flags: open flags + * @mode: mode for a newly created file + * + * Use this from configfs store callbacks with a resolved non-configfs root + * to avoid re-entering configfs while the callback holds its fragment + * semaphore. + * + * Return: opened file, or an ERR_PTR() value. Returns -EINVAL if @root + * is on configfs. + */ +struct file *configfs_open_root(const struct path *root, const char *name, + int flags, umode_t mode) +{ + if (root->dentry->d_sb->s_type =3D=3D &configfs_fs_type) + return ERR_PTR(-EINVAL); + + return file_open_root(root, name, flags, mode); +} +EXPORT_SYMBOL_GPL(configfs_open_root); + +/** + * configfs_file_open - open an existing non-configfs pathname + * @filename: pathname to open; it must already exist + * @flags: open flags for the existing pathname + * @mode: unused; creation is not supported + * + * Resolve @filename and reject configfs paths. Use this from configfs + * store callbacks for existing configured paths. O_NOFOLLOW is honored + * when resolving the final path component. + * + * Return: opened file, or an ERR_PTR() value. Returns -EINVAL if the + * resolved path is on configfs. + */ +struct file *configfs_file_open(const char *filename, int flags, umode_t m= ode) +{ + struct file *file; + struct path path; + unsigned int lookup_flags =3D 0; + int ret; + + if (!(flags & O_NOFOLLOW)) + lookup_flags =3D LOOKUP_FOLLOW; + ret =3D kern_path(filename, lookup_flags, &path); + if (ret) + return ERR_PTR(ret); + + file =3D configfs_open_root(&path, "", flags, mode); + path_put(&path); + return file; +} +EXPORT_SYMBOL_GPL(configfs_file_open); + struct dentry *configfs_pin_fs(void) { int err =3D simple_pin_fs(&configfs_fs_type, &configfs_mount, diff --git a/include/linux/configfs.h b/include/linux/configfs.h index ef65c75beeaad..2a803bb836b4d 100644 --- a/include/linux/configfs.h +++ b/include/linux/configfs.h @@ -34,6 +34,8 @@ struct configfs_group_operations; struct configfs_attribute; struct configfs_bin_attribute; struct configfs_subsystem; +struct file; +struct path; =20 struct config_item { char *ci_name; @@ -243,6 +245,9 @@ void configfs_unregister_subsystem(struct configfs_subs= ystem *subsys); int configfs_register_group(struct config_group *parent_group, struct config_group *group); void configfs_unregister_group(struct config_group *group); +struct file *configfs_open_root(const struct path *root, const char *name, + int flags, umode_t mode); +struct file *configfs_file_open(const char *filename, int flags, umode_t m= ode); =20 void configfs_remove_default_groups(struct config_group *group); =20 --=20 2.34.1 From nobody Mon Sep 28 17:49:53 2026 Received: from mail-m49197.qiye.163.com (mail-m49197.qiye.163.com [45.254.49.197]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 07A55380FCA; Sun, 27 Sep 2026 08:20:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.254.49.197 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790497234; cv=none; b=m06BrA3qWYSjaaCdeoTtJRk0WhRCNrPOYtJ7NtfP1xttRly6Lg5mRzrfukT31sRyQUE9cgaSlhilqfocWMESAsdbiFzXvt7rAhJ57RylQprQjKmkx7xJXqCdOwhl5RAxHZO9YokISQWgfTDs95I38Tx6mWlHhOWC2QHQfuyj6UI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790497234; c=relaxed/simple; bh=N08GINapGkfvCosW7+xLnWZKpuPPjBW9LdLNoq/FvI0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Mcx03fFXKRS1LvvTjSiUUjYDYVsS+2qFsWIwGY/HDS8jcz4zxLd8oNFRsZOBAAhfUT7onP8ydU37+ETMJ3Mm7bc524CkiEAwlDWbNHyBvF5pNP2VMVUCiQnXzBMkIgjJ/yr6jpVVjE8f07zHFe7sqAu8lc2evxqz/BqzBLC65VE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=seu.edu.cn; spf=pass smtp.mailfrom=seu.edu.cn; dkim=pass (1024-bit key) header.d=seu.edu.cn header.i=@seu.edu.cn header.b=EkGWP8qd; arc=none smtp.client-ip=45.254.49.197 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=seu.edu.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=seu.edu.cn Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=seu.edu.cn header.i=@seu.edu.cn header.b="EkGWP8qd" Received: from PC-202605011814.localdomain (unknown [222.191.246.242]) by smtp.qiye.163.com (Hmail) with ESMTP id 4f3a443fc; Sun, 27 Sep 2026 16:20:26 +0800 (GMT+08:00) From: Runyu Xiao To: Christoph Hellwig Cc: Breno Leitao , Andreas Hindborg , Sagi Grimberg , Chaitanya Kulkarni , Keith Busch , Logan Gunthorpe , "Martin K . Petersen" , Lee Duncan , Hannes Reinecke , Nicholas Bellinger , linux-nvme@lists.infradead.org, linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, linux-kernel@vger.kernel.org, stable@vger.kernel.org, Runyu Xiao , Jianhao Xu Subject: [PATCH v7 2/4] nvmet: avoid recursive configfs open for file-backed namespaces Date: Sun, 27 Sep 2026 16:20:09 +0800 Message-Id: <20260927082011.638723-3-runyu.xiao@seu.edu.cn> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260927082011.638723-1-runyu.xiao@seu.edu.cn> References: <20260927082011.638723-1-runyu.xiao@seu.edu.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-HM-Tid: 0aa0e1f37d1d03a1kunm12f6b69c1ac33a X-HM-MType: 10 X-HM-Spam-Status: e1kfGhgUHx5ZQUpXWQgPGg8OCBgUHx5ZQUlOS1dZFg8aDwILHllBWSg2Ly tZV1koWUFITzdXWRgWCB1ZQUpXWS1ZQUlXWQ8JGhUIEh9ZQVlCTB0aVklCSRgfGB4dGk9PTVYeHw 5VEwETFhoSFyQUDg9ZV1kYEgtZQVlJSUlVSkJKVUlPTVVJT0lZV1kWGg8SFR0UWUFZT0tIVUpLSE pPSExVSktLVUpCS0tZBg++ DKIM-Signature: a=rsa-sha256; b=EkGWP8qdG+5LiGL046+jDR7uE+tkvN9/pv/AqCEZ+0VOtrpTtvc8uSnQLJSI0Dpn/RXEjZNtfPhs+Z8yxpLgy/xGKSVsaAyTqh+gdjPTqa3ZQx2kS3jPbrGtRP5j/T5YCEMfVAg9c8gJJB1KlksGzjTLQ0EoJ49jUtRgwBRQNhM=; c=relaxed/relaxed; s=default; d=seu.edu.cn; v=1; bh=Tcbi5MYjrLiwUZJP1iBOkaEwqrphN9t9A1anWrBn1xQ=; h=date:mime-version:subject:message-id:from; Content-Type: text/plain; charset="utf-8" nvmet_ns_enable_store() runs as a configfs store callback while configfs holds the item frag_sem. File-backed namespace enable used filp_open() on the configured device_path, so a path into configfs could re-enter __configfs_open_file() and try to acquire the same semaphore again. Use configfs_file_open() so the path is resolved before opening, configfs-backed paths are rejected, and the resolved path is opened with file_open_root() while retaining the normal open-time permission and security checks. Fixes: d5eff33ee6f8 ("nvmet: add simple file backed ns support") Cc: stable@vger.kernel.org Reviewed-by: Christoph Hellwig Assisted-by: LLM Codex Signed-off-by: Runyu Xiao --- drivers/nvme/target/io-cmd-file.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/target/io-cmd-file.c b/drivers/nvme/target/io-cmd= -file.c index 0b22d183f9279..2a4f25de94ba1 100644 --- a/drivers/nvme/target/io-cmd-file.c +++ b/drivers/nvme/target/io-cmd-file.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "nvmet.h" =20 @@ -38,7 +39,7 @@ int nvmet_file_ns_enable(struct nvmet_ns *ns) if (!ns->buffered_io) flags |=3D O_DIRECT; =20 - ns->file =3D filp_open(ns->device_path, flags, 0); + ns->file =3D configfs_file_open(ns->device_path, flags, 0); if (IS_ERR(ns->file)) { ret =3D PTR_ERR(ns->file); pr_err("failed to open file %s: (%d)\n", --=20 2.34.1 From nobody Mon Sep 28 17:49:53 2026 Received: from mail-m49197.qiye.163.com (mail-m49197.qiye.163.com [45.254.49.197]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 354573B813D; Sun, 27 Sep 2026 08:20:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.254.49.197 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790497234; cv=none; b=JG0cSFr805NKNPApQAYuQfmHYl7TBmk5YURnWc15TRK2i0yC//Ne4Z0RRKMF6IAZmpQmLsQWlLuf4IVrwervt5+IPYFUKkq4/Y9IEzUfU0k13tG1ZB20AKBWZlJAHxRAZeOklAmqkqEtnsgyy0nWHKGVev8uCRFMFFFQyKbdirQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790497234; c=relaxed/simple; bh=gwbthItRhuypYUcH713iH/hnNoRFDlBtn4qTU9lz7/M=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=RSxaL8oHEoLNWwOhqc61K9AlXgfDBVQ3PS1f9nKmJmwOX5gaoxl1RCQVyZKb3YANfF52PTQ3v8R0KuXLmxs2Uf0LWvyV5GsPlwo+bEfW1pzbFElLomjwwjJ1FKen+QJRRKzlF7YPPSPkw3L0+zvX49SJtQpx5QFUMxem2dKIsUQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=seu.edu.cn; spf=pass smtp.mailfrom=seu.edu.cn; dkim=pass (1024-bit key) header.d=seu.edu.cn header.i=@seu.edu.cn header.b=TOkT3Rcy; arc=none smtp.client-ip=45.254.49.197 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=seu.edu.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=seu.edu.cn Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=seu.edu.cn header.i=@seu.edu.cn header.b="TOkT3Rcy" Received: from PC-202605011814.localdomain (unknown [222.191.246.242]) by smtp.qiye.163.com (Hmail) with ESMTP id 4f3a443fd; Sun, 27 Sep 2026 16:20:27 +0800 (GMT+08:00) From: Runyu Xiao To: Christoph Hellwig Cc: Breno Leitao , Andreas Hindborg , Sagi Grimberg , Chaitanya Kulkarni , Keith Busch , Logan Gunthorpe , "Martin K . Petersen" , Lee Duncan , Hannes Reinecke , Nicholas Bellinger , linux-nvme@lists.infradead.org, linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, linux-kernel@vger.kernel.org, stable@vger.kernel.org, Runyu Xiao , Jianhao Xu Subject: [PATCH v7 3/4] nvmet: avoid recursive configfs open for passthru Date: Sun, 27 Sep 2026 16:20:10 +0800 Message-Id: <20260927082011.638723-4-runyu.xiao@seu.edu.cn> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260927082011.638723-1-runyu.xiao@seu.edu.cn> References: <20260927082011.638723-1-runyu.xiao@seu.edu.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-HM-Tid: 0aa0e1f3823703a1kunm12f6b69c1ac343 X-HM-MType: 10 X-HM-Spam-Status: e1kfGhgUHx5ZQUpXWQgPGg8OCBgUHx5ZQUlOS1dZFg8aDwILHllBWSg2Ly tZV1koWUFITzdXWRgWCB1ZQUpXWS1ZQUlXWQ8JGhUIEh9ZQVlCGktJVkpDTklJQxofGU5OTFYeHw 5VEwETFhoSFyQUDg9ZV1kYEgtZQVlJSUlVSkJKVUlPTVVJT0lZV1kWGg8SFR0UWUFZT0tIVUpLSE pPSExVSktLVUpCS0tZBg++ DKIM-Signature: a=rsa-sha256; b=TOkT3RcyMa/wWWyKVW4uU5c7K2KtXo1sc/Ehl/eL2VWf6bP5sWT6iYzwysrnRRrt+HL8DUiYpzmnXzVMjvg0yei1/9zY+agIUomFeYalEVNrDeeqkQdPio6GTy33cyy9RG/hbDABqDLSSmAJ6C3W/z3poZNQL+oS2f4k1H8MTv8=; c=relaxed/relaxed; s=default; d=seu.edu.cn; v=1; bh=/H/LFwbci3Eh6MNU8eJOEho61nt5VkkYkF/xMDqVmas=; h=date:mime-version:subject:message-id:from; Content-Type: text/plain; charset="utf-8" nvmet_passthru_enable_store() runs as a configfs store callback while configfs holds the item frag_sem. Passthru enable used filp_open() on the configured controller path, so a path into configfs could re-enter __configfs_open_file() and try to acquire the same semaphore again. Use configfs_file_open() so the path is resolved before opening, configfs-backed paths are rejected, and the resolved path is opened with file_open_root() while retaining the normal open-time permission and security checks. Fixes: cae5b01a2afc ("nvmet: introduce the passthru configfs interface") Cc: stable@vger.kernel.org Reviewed-by: Christoph Hellwig Assisted-by: LLM Codex Signed-off-by: Runyu Xiao --- drivers/nvme/target/passthru.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/target/passthru.c b/drivers/nvme/target/passthru.c index fa6527c537e26..d60256004e6cf 100644 --- a/drivers/nvme/target/passthru.c +++ b/drivers/nvme/target/passthru.c @@ -9,6 +9,7 @@ */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include +#include =20 #include "../host/nvme.h" #include "nvmet.h" @@ -602,7 +603,7 @@ int nvmet_passthru_ctrl_enable(struct nvmet_subsys *sub= sys) goto out_unlock; } =20 - file =3D filp_open(subsys->passthru_ctrl_path, O_RDWR, 0); + file =3D configfs_file_open(subsys->passthru_ctrl_path, O_RDWR, 0); if (IS_ERR(file)) { ret =3D PTR_ERR(file); goto out_unlock; --=20 2.34.1 From nobody Mon Sep 28 17:49:53 2026 Received: from mail-m49197.qiye.163.com (mail-m49197.qiye.163.com [45.254.49.197]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9B9AF3C1D61; Sun, 27 Sep 2026 08:20:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.254.49.197 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790497236; cv=none; b=Qk3Tt78lU0iVKciNEXMXr280eji6kKogUjzfG2K4PnNV8yhOkyIz2aCkO6xvMVaFyID0uk9MNbALB7cL3jCPSL1C7YinyLpV/JhUlCNGUHiOI56dOzJeDdn5QgEEjHtk9w4CkYobbfavw5WnQN/QqXxNMmoD6l9p1dYiD4Dyszk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790497236; c=relaxed/simple; bh=PJzqsvxIq3NGKNk203hKX+rbCG2NvovDhRMpAD6sP9E=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Q0RJ4Jl3Qp+QyNTRdOn284lnADxhDX9yqxv3nesa1sTEnaBdi7FJJg4TKhL1Z0CrHyRSenjXhVWeqVuF3Stp9Hi9bGFNdr7TSE8APS5k7h1qRq3CHwH6ER/xkbBDqfcFGD9EB6TGJTDnEZrP6S0NcB/Tw9B80ml6DG0OZSUeYDg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=seu.edu.cn; spf=pass smtp.mailfrom=seu.edu.cn; dkim=pass (1024-bit key) header.d=seu.edu.cn header.i=@seu.edu.cn header.b=c1QQWV0Y; arc=none smtp.client-ip=45.254.49.197 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=seu.edu.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=seu.edu.cn Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=seu.edu.cn header.i=@seu.edu.cn header.b="c1QQWV0Y" Received: from PC-202605011814.localdomain (unknown [222.191.246.242]) by smtp.qiye.163.com (Hmail) with ESMTP id 4f3a443fe; Sun, 27 Sep 2026 16:20:28 +0800 (GMT+08:00) From: Runyu Xiao To: Christoph Hellwig Cc: Breno Leitao , Andreas Hindborg , Sagi Grimberg , Chaitanya Kulkarni , Keith Busch , Logan Gunthorpe , "Martin K . Petersen" , Lee Duncan , Hannes Reinecke , Nicholas Bellinger , linux-nvme@lists.infradead.org, linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, linux-kernel@vger.kernel.org, stable@vger.kernel.org, Runyu Xiao , Jianhao Xu Subject: [PATCH v7 4/4] scsi: target: pin db_root for metadata writes Date: Sun, 27 Sep 2026 16:20:11 +0800 Message-Id: <20260927082011.638723-5-runyu.xiao@seu.edu.cn> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260927082011.638723-1-runyu.xiao@seu.edu.cn> References: <20260927082011.638723-1-runyu.xiao@seu.edu.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-HM-Tid: 0aa0e1f3871c03a1kunm12f6b69c1ac34c X-HM-MType: 10 X-HM-Spam-Status: e1kfGhgUHx5ZQUpXWQgPGg8OCBgUHx5ZQUlOS1dZFg8aDwILHllBWSg2Ly tZV1koWUFITzdXWRgWCB1ZQUpXWS1ZQUlXWQ8JGhUIEh9ZQVlCT0JIVkNPH0pIS0tCGEJLSFYeHw 5VEwETFhoSFyQUDg9ZV1kYEgtZQVlJSUlVSkJKVUlPTVVJT0lZV1kWGg8SFR0UWUFZT0tIVUpLSE pPSExVSktLVUpCS0tZBg++ DKIM-Signature: a=rsa-sha256; b=c1QQWV0YJyNZyPcOzwVo1x6jXiWdb+JFv+cyQzYhQiWT2mM4BRDQfG3nyM+65E0OsLj/ezOv5cx7y59pOD3CAcUBpwaXlpNxCysH1K7ZMyX+bDQdCvs93iSAzaJH5GRWkkyHi5m3B1ZtI0Vh/1SOdSitNazuhFOOm0qGRGkUQHg=; c=relaxed/relaxed; s=default; d=seu.edu.cn; v=1; bh=JEB7g1R4O8vv9+70KUQg9jDc93lN6kuadHZo3AOtcrA=; h=date:mime-version:subject:message-id:from; Content-Type: text/plain; charset="utf-8" ALUA and persistent reservation metadata files are derived from the configurable db_root string and opened with filp_open(). If db_root points at configfs, a metadata update from a configfs store callback can re-enter configfs while the callback still holds frag_sem. A one-time pathname check can also be bypassed by retargeting a symlink. Resolve db_root once and retain the resulting path while target devices use it. Use configfs_open_root() both to reject configfs roots and to open metadata files relative to the pinned root. Protect db_root and db_root_path with a dedicated mutex while metadata paths are opened or the configured root is replaced. Return an error if target devices appear before a validated root can be published. Resolve a new root outside target_devices_lock and recheck the device count before publishing it, so the path walk does not occur under that lock. Fixes: fdddf932269a ("target: use new "dbroot" target attribute") Link: https://lore.kernel.org/r/20260818051442.1523210-1-runyu.xiao@seu.edu= .cn Cc: stable@vger.kernel.org Assisted-by: LLM Codex Signed-off-by: Runyu Xiao Reviewed-by: Christoph Hellwig --- drivers/target/target_core_alua.c | 42 ++++---- drivers/target/target_core_configfs.c | 142 +++++++++++++++++++++----- drivers/target/target_core_internal.h | 5 + drivers/target/target_core_pr.c | 19 ++-- 4 files changed, 153 insertions(+), 55 deletions(-) diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core= _alua.c index 140154d93c430..c39e57c1ebf9e 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -862,15 +861,18 @@ static int core_alua_write_tpg_metadata( loff_t pos =3D 0; int ret; =20 - if (tsk_is_kthread(current)) { - scoped_with_init_fs() - file =3D filp_open(path, O_RDWR | O_CREAT | O_TRUNC, 0600); - } else { - file =3D filp_open(path, O_RDWR | O_CREAT | O_TRUNC, 0600); + mutex_lock(&db_root_lock); + if (!db_root_path.dentry) { + mutex_unlock(&db_root_lock); + pr_err("db_root is not initialized for ALUA metadata path: %s\n", + path); + return -ENODEV; } - + file =3D configfs_open_root(&db_root_path, path, + O_RDWR | O_CREAT | O_TRUNC, 0600); + mutex_unlock(&db_root_lock); if (IS_ERR(file)) { - pr_err("filp_open(%s) for ALUA metadata failed\n", path); + pr_err("configfs_open_root(%s) for ALUA metadata failed\n", path); return -ENODEV; } ret =3D kernel_write(file, md_buf, md_buf_len, &pos); @@ -905,9 +907,9 @@ static int core_alua_update_tpg_primary_metadata( tg_pt_gp->tg_pt_gp_alua_access_status); =20 rc =3D -ENOMEM; - path =3D kasprintf(GFP_KERNEL, "%s/alua/tpgs_%s/%s", db_root, - &wwn->unit_serial[0], - config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item)); + path =3D kasprintf(GFP_KERNEL, "alua/tpgs_%s/%s", + &wwn->unit_serial[0], + config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item)); if (path) { rc =3D core_alua_write_tpg_metadata(path, md_buf, len); kfree(path); @@ -1196,16 +1198,16 @@ static int core_alua_update_tpg_secondary_metadata(= struct se_lun *lun) lun->lun_tg_pt_secondary_stat); =20 if (se_tpg->se_tpg_tfo->tpg_get_tag !=3D NULL) { - path =3D kasprintf(GFP_KERNEL, "%s/alua/%s/%s+%hu/lun_%llu", - db_root, se_tpg->se_tpg_tfo->fabric_name, - se_tpg->se_tpg_tfo->tpg_get_wwn(se_tpg), - se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg), - lun->unpacked_lun); + path =3D kasprintf(GFP_KERNEL, "alua/%s/%s+%hu/lun_%llu", + se_tpg->se_tpg_tfo->fabric_name, + se_tpg->se_tpg_tfo->tpg_get_wwn(se_tpg), + se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg), + lun->unpacked_lun); } else { - path =3D kasprintf(GFP_KERNEL, "%s/alua/%s/%s/lun_%llu", - db_root, se_tpg->se_tpg_tfo->fabric_name, - se_tpg->se_tpg_tfo->tpg_get_wwn(se_tpg), - lun->unpacked_lun); + path =3D kasprintf(GFP_KERNEL, "alua/%s/%s/lun_%llu", + se_tpg->se_tpg_tfo->fabric_name, + se_tpg->se_tpg_tfo->tpg_get_wwn(se_tpg), + lun->unpacked_lun); } if (!path) { rc =3D -ENOMEM; diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_= core_configfs.c index 2b19a956007b7..31cd1ed42b135 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -96,57 +96,126 @@ static ssize_t target_core_item_version_show(struct co= nfig_item *item, CONFIGFS_ATTR_RO(target_core_item_, version); =20 char db_root[DB_ROOT_LEN] =3D DB_ROOT_DEFAULT; -static char db_root_stage[DB_ROOT_LEN]; +struct path db_root_path; +/* Protect db_root and db_root_path. */ +DEFINE_MUTEX(db_root_lock); + +static int target_validate_db_root(const char *path_str, struct path *path) +{ + struct file *file; + int ret; + + ret =3D kern_path(path_str, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, path); + if (ret) { + pr_err("db_root: cannot open: %s\n", path_str); + if (ret =3D=3D -ENOTDIR) + pr_err("db_root: not a directory: %s\n", path_str); + return ret; + } + + file =3D configfs_open_root(path, "", O_RDONLY, 0); + if (IS_ERR(file)) { + ret =3D PTR_ERR(file); + path_put(path); + *path =3D (struct path){}; + if (ret !=3D -EINVAL) + return ret; + + pr_err("db_root: configfs is not a valid target database root: %s\n", + path_str); + return -EINVAL; + } + + path_put(path); + *path =3D file->f_path; + path_get(path); + fput(file); + + return 0; +} =20 static ssize_t target_core_item_dbroot_show(struct config_item *item, char *page) { - return sprintf(page, "%s\n", db_root); + ssize_t ret; + + mutex_lock(&db_root_lock); + ret =3D sprintf(page, "%s\n", db_root); + mutex_unlock(&db_root_lock); + + return ret; } =20 static ssize_t target_core_item_dbroot_store(struct config_item *item, const char *page, size_t count) { + char *db_root_stage; ssize_t read_bytes; ssize_t r =3D -EINVAL; struct path path =3D {}; + struct path old_path =3D {}; + bool have_old_path =3D false; =20 mutex_lock(&target_devices_lock); if (target_devices) { pr_err("db_root: cannot be changed because it's in use\n"); - goto unlock; + mutex_unlock(&target_devices_lock); + return r; } + mutex_unlock(&target_devices_lock); =20 if (count > (DB_ROOT_LEN - 1)) { pr_err("db_root: count %d exceeds DB_ROOT_LEN-1: %u\n", (int)count, DB_ROOT_LEN - 1); - goto unlock; + return r; } =20 + db_root_stage =3D kmalloc(DB_ROOT_LEN, GFP_KERNEL); + if (!db_root_stage) + return -ENOMEM; + read_bytes =3D scnprintf(db_root_stage, DB_ROOT_LEN, "%s", page); if (!read_bytes) - goto unlock; + goto free_stage; =20 if (db_root_stage[read_bytes - 1] =3D=3D '\n') db_root_stage[read_bytes - 1] =3D '\0'; =20 /* validate new db root before accepting it */ - r =3D kern_path(db_root_stage, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path); - if (r) { - pr_err("db_root: cannot open: %s\n", db_root_stage); - if (r =3D=3D -ENOTDIR) - pr_err("db_root: not a directory: %s\n", db_root_stage); - goto unlock; + r =3D target_validate_db_root(db_root_stage, &path); + if (r) + goto free_stage; + + mutex_lock(&target_devices_lock); + if (target_devices) { + pr_err("db_root: cannot be changed because it's in use\n"); + r =3D -EINVAL; + goto unlock_put; } - path_put(&path); =20 + mutex_lock(&db_root_lock); + have_old_path =3D db_root_path.dentry; + if (have_old_path) + old_path =3D db_root_path; + db_root_path =3D path; + path =3D (struct path){}; strscpy(db_root, db_root_stage); pr_debug("Target_Core_ConfigFS: db_root set to %s\n", db_root); + mutex_unlock(&db_root_lock); =20 r =3D read_bytes; =20 -unlock: +unlock_put: mutex_unlock(&target_devices_lock); + if (path.dentry) + path_put(&path); + if (have_old_path) + path_put(&old_path); + kfree(db_root_stage); + return r; + +free_stage: + kfree(db_root_stage); return r; } =20 @@ -3722,23 +3791,37 @@ void target_setup_backend_cits(struct target_backen= d *tb) =20 static void target_init_dbroot(void) { - struct file *fp; + const char *db_root_stage; + struct path path =3D {}; + int ret; =20 - snprintf(db_root_stage, DB_ROOT_LEN, DB_ROOT_PREFERRED); - fp =3D filp_open(db_root_stage, O_RDONLY, 0); - if (IS_ERR(fp)) { - pr_err("db_root: cannot open: %s\n", db_root_stage); - return; - } - if (!S_ISDIR(file_inode(fp)->i_mode)) { - filp_close(fp, NULL); - pr_err("db_root: not a valid directory: %s\n", db_root_stage); - return; + db_root_stage =3D DB_ROOT_PREFERRED; + ret =3D target_validate_db_root(db_root_stage, &path); + if (ret) { + db_root_stage =3D DB_ROOT_DEFAULT; + ret =3D target_validate_db_root(db_root_stage, &path); + if (ret) + return; } - filp_close(fp, NULL); =20 + mutex_lock(&db_root_lock); + db_root_path =3D path; strscpy(db_root, db_root_stage); pr_debug("Target_Core_ConfigFS: db_root set to %s\n", db_root); + mutex_unlock(&db_root_lock); +} + +static void target_release_db_root(void) +{ + struct path path; + + mutex_lock(&db_root_lock); + path =3D db_root_path; + db_root_path =3D (struct path){}; + mutex_unlock(&db_root_lock); + + if (path.dentry) + path_put(&path); } =20 static int __init target_core_init_configfs(void) @@ -3797,6 +3880,10 @@ static int __init target_core_init_configfs(void) /* * Register the target_core_mod subsystem with configfs. */ + /* Resolve db_root before making the configfs attributes visible. */ + scoped_with_kernel_creds() + target_init_dbroot(); + ret =3D configfs_register_subsystem(subsys); if (ret < 0) { pr_err("Error %d while registering subsystem %s\n", @@ -3821,9 +3908,6 @@ static int __init target_core_init_configfs(void) if (ret < 0) goto out; =20 - scoped_with_kernel_creds() - target_init_dbroot(); - return 0; =20 out: @@ -3832,6 +3916,7 @@ static int __init target_core_init_configfs(void) core_dev_release_virtual_lun0(); rd_module_exit(); out_global: + target_release_db_root(); if (default_lu_gp) { core_alua_free_lu_gp(default_lu_gp); default_lu_gp =3D NULL; @@ -3861,6 +3946,7 @@ static void __exit target_core_exit_configfs(void) core_dev_release_virtual_lun0(); rd_module_exit(); target_xcopy_release_pt(); + target_release_db_root(); release_se_kmem_caches(); } =20 diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_= core_internal.h index f0886ea290345..502788ba732dd 100644 --- a/drivers/target/target_core_internal.h +++ b/drivers/target/target_core_internal.h @@ -4,6 +4,7 @@ =20 #include #include +#include #include #include =20 @@ -171,6 +172,10 @@ extern struct se_portal_group xcopy_pt_tpg; #define DB_ROOT_DEFAULT "/var/target" #define DB_ROOT_PREFERRED "/etc/target" =20 +struct path; + extern char db_root[]; +extern struct path db_root_path; +extern struct mutex db_root_lock; =20 #endif /* TARGET_CORE_INTERNAL_H */ diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_p= r.c index 25b1bcacc0c8f..36d20732382f1 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include =20 @@ -1965,16 +1964,22 @@ static int __core_scsi3_write_aptpl_to_file( int ret; loff_t pos =3D 0; =20 - path =3D kasprintf(GFP_KERNEL, "%s/pr/aptpl_%s", db_root, - &wwn->unit_serial[0]); + path =3D kasprintf(GFP_KERNEL, "pr/aptpl_%s", &wwn->unit_serial[0]); if (!path) return -ENOMEM; =20 - scoped_with_init_fs() - file =3D filp_open(path, flags, 0600); + mutex_lock(&db_root_lock); + if (!db_root_path.dentry) { + mutex_unlock(&db_root_lock); + pr_err("db_root is not initialized for APTPL metadata path: %s\n", + path); + kfree(path); + return -ENODEV; + } + file =3D configfs_open_root(&db_root_path, path, flags, 0600); + mutex_unlock(&db_root_lock); if (IS_ERR(file)) { - pr_err("filp_open(%s) for APTPL metadata" - " failed\n", path); + pr_err("configfs_open_root(%s) for APTPL metadata failed\n", path); kfree(path); return PTR_ERR(file); } --=20 2.34.1