mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 1/2] configfs: handle unlinked target in configfs_depend_item_unlocked()
@ 2026-10-22 13:44 Slawomir Stepien
  2026-10-22 13:44 ` [PATCH 2/2] configfs: give the root inode its own lockdep class Slawomir Stepien
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Slawomir Stepien @ 2026-10-22 13:44 UTC (permalink / raw)
  To: leitao, a.hindborg, k.opasiak, nab; +Cc: linux-kernel, Slawomir Stepien

configfs_depend_item_unlocked() starts by reading target->ci_group to
find the target's subsystem and the configfs root, and dereferences it
without checking for NULL. ci_group is only valid while the item is
linked into the tree: it is set by link_group() during mkdir and
cleared by unlink_group() during rmdir, both under the subsystem's
su_mutex, which callers of the unlocked variant do not hold.

A caller can therefore pass an item that is allocated but not linked.
f_tcm does this from usbg_make_tpg(): a TCM function instance becomes
visible to the target subsystem in tcm_alloc_inst()/tcm_set_name(),
before configfs_mkdir() links it, and stays visible after
configfs_rmdir() unlinks it until the final reference is dropped.
Creating a TPG in either window makes configfs_is_root(&parent->cg_item)
return false for a NULL parent, and the following parent->cg_subsys
dereference crashes.

An unlinked item is just a target that is not in the tree, which
configfs_depend_prep() already reports as -ENOENT. It skips items
marked CREATING or DROPPING, and rmdir marks an item DROPPING before
unlinking it. Read ci_group once with READ_ONCE() and return -ENOENT
if it is NULL.

If the target is unlinked right after the read, the snapshot still
points at the parent group: unlinking drops the child's reference on
it but does not free it. The depend then fails in the tree scan, since
the target is already marked DROPPING. The parent can only go away if
it is itself removed in that window, which is the same theoretical
race the root walk below already has for every caller of this
function.

Fixes: d79d75b5c518 ("fs: configfs: Add unlocked version of configfs_depend_item()")
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Slawomir Stepien <sst@poczta.fm>
---
 fs/configfs/dir.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 0c80feec5926..7f4f448a6c66 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -1243,7 +1243,14 @@ int configfs_depend_item_unlocked(struct configfs_subsystem *caller_subsys,
 	if (configfs_is_root(target))
 		return -EINVAL;
 
-	parent = target->ci_group;
+	/*
+	 * The target may not be linked into the tree yet (mkdir in progress)
+	 * or may already have been unlinked (rmdir in progress).
+	 */
+	parent = READ_ONCE(target->ci_group);
+	if (!parent)
+		return -ENOENT;
+
 	/*
 	 * This may happen when someone is trying to depend root
 	 * directory of some subsystem
-- 
2.56.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-10-27 13:29 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-22 13:44 [PATCH 1/2] configfs: handle unlinked target in configfs_depend_item_unlocked() Slawomir Stepien
2026-10-22 13:44 ` [PATCH 2/2] configfs: give the root inode its own lockdep class Slawomir Stepien
2026-10-27 12:51   ` Breno Leitao
2026-10-27 12:50 ` [PATCH 1/2] configfs: handle unlinked target in configfs_depend_item_unlocked() Breno Leitao
2026-10-27 13:27 ` Breno Leitao

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®