From: Shakeel Butt <shakeel.butt@linux.dev>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Tejun Heo <tj@kernel.org>,
Christian Brauner <christian@brauner.io>
Cc: Meta kernel team <kernel-team@meta.com>,
linux-kselftest@vger.kernel.org, driver-core@lists.linux.dev,
linux-kernel@vger.kernel.org
Subject: [PATCH v2 4/4] kernfs: fix up the unlocked attribute reads on the creation paths
Date: Sat, 5 Sep 2026 12:16:13 -0700 [thread overview]
Message-ID: <20260905191613.3143937-5-shakeel.butt@linux.dev> (raw)
In-Reply-To: <20260905191613.3143937-1-shakeel.butt@linux.dev>
Two creation paths read a live node's attributes without holding
kernfs_iattr_rwsem, which kernfs_iop_setattr() takes for writing. They
need different fixes.
kernfs_create_link() copies the target's ia_uid and then its ia_gid into
the new link. A chown of the target between the two reads leaves the
link with the old uid and the new gid, an owner the target never had.
Read both under the rwsem.
kernfs_new_node() reads the parent's mode and ia_gid for S_ISGID
inheritance. Either value is fine there: the node does not exist yet,
so nothing orders a racing chmod or chown against the creation. Taking
the rwsem would only pick between two answers that are both right. Mark
the reads with READ_ONCE() instead.
The pointer that leads to them is already fine: __kernfs_iattrs()
publishes kernfs_node::iattr with try_cmpxchg(), and both sides read it
with READ_ONCE(), like the rest of fs/kernfs.
The Fixes tag is for the symlink half. kernfs_create_link() has read
the pair unlocked since it started copying the target's owner; only the
name of the lock its writer takes has changed. The READ_ONCE() markings
are not a fix.
Fixes: 488dee96bb62 ("kernfs: allow creating kernfs objects with arbitrary uid/gid")
Acked-by: Tejun Heo <tj@kernel.org>
Assisted-by: LLM
Signed-off-by: Shakeel Butt <shakeel.butt@linux.dev>
---
fs/kernfs/dir.c | 12 +++++++++---
fs/kernfs/symlink.c | 17 ++++++++++++++---
2 files changed, 23 insertions(+), 6 deletions(-)
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index 214c97130a8a..07abf59f0264 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -736,13 +736,19 @@ struct kernfs_node *kernfs_new_node(struct kernfs_node *parent,
{
struct kernfs_node *kn;
- if (parent->mode & S_ISGID) {
+ /*
+ * The mode and the gid below are read unlocked on purpose: they feed
+ * a node that does not exist yet, so nothing orders a racing chmod or
+ * chown against this creation.
+ */
+ if (READ_ONCE(parent->mode) & S_ISGID) {
/* this code block imitates inode_init_owner() for
* kernfs
*/
+ struct kernfs_iattrs *attrs = READ_ONCE(parent->iattr);
- if (parent->iattr)
- gid = parent->iattr->ia_gid;
+ if (attrs)
+ gid = READ_ONCE(attrs->ia_gid);
if (flags & KERNFS_DIR)
mode |= S_ISGID;
diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c
index 90e2b3221b83..3e53105d3abf 100644
--- a/fs/kernfs/symlink.c
+++ b/fs/kernfs/symlink.c
@@ -31,9 +31,20 @@ struct kernfs_node *kernfs_create_link(struct kernfs_node *parent,
kuid_t uid = GLOBAL_ROOT_UID;
kgid_t gid = GLOBAL_ROOT_GID;
- if (target->iattr) {
- uid = target->iattr->ia_uid;
- gid = target->iattr->ia_gid;
+ /*
+ * A symlink takes its owner from its target, so both fields have to
+ * come from the same moment: read them under kernfs_iattr_rwsem, or
+ * a chown of the target racing this could leave the link with the
+ * old uid and the new gid. The section ends before kernfs_add_one()
+ * takes kernfs_rwsem.
+ */
+ scoped_guard(rwsem_read, &kernfs_root(target)->kernfs_iattr_rwsem) {
+ struct kernfs_iattrs *attrs = READ_ONCE(target->iattr);
+
+ if (attrs) {
+ uid = attrs->ia_uid;
+ gid = attrs->ia_gid;
+ }
}
kn = kernfs_new_node(parent, name, S_IFLNK|0777, uid, gid, KERNFS_LINK);
--
2.53.0-Meta
prev parent reply other threads:[~2026-09-05 19:16 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-05 19:16 [PATCH v2 0/4] kernfs: three standalone fixes Shakeel Butt
2026-09-05 19:16 ` [PATCH v2 1/4] selftests: cover kernfs file handles and same-parent rename Shakeel Butt
2026-09-05 19:16 ` [PATCH v2 2/4] kernfs: take kernfs_rename_lock for same-parent renames too Shakeel Butt
2026-09-05 19:16 ` [PATCH v2 3/4] kernfs: don't lose IN_DELETE_SELF when decoding a file handle Shakeel Butt
2026-09-05 19:16 ` Shakeel Butt [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260905191613.3143937-5-shakeel.butt@linux.dev \
--to=shakeel.butt@linux.dev \
--cc=christian@brauner.io \
--cc=driver-core@lists.linux.dev \
--cc=gregkh@linuxfoundation.org \
--cc=kernel-team@meta.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=tj@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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®