From: Breno Leitao <leitao@debian.org>
To: Farhad Alemi <farhad.alemi@berkeley.edu>
Cc: Andreas Hindborg <a.hindborg@kernel.org>,
linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [BUG] configfs: slab-use-after-free in configfs_drop_dentry() on rmdir
Date: Wed, 27 May 2026 11:27:57 +0100 [thread overview]
Message-ID: <ahbG94EFLD5ntnYr@gmail.com> (raw)
In-Reply-To: <CA+0ovCjv-VYvn-4jUj3wDn+DuP9FSv-GL+yPAHbR=ZGKU0wmGg@mail.gmail.com>
On Tue, May 26, 2026 at 08:42:00PM +0000, Farhad Alemi wrote:
> Hello Andreas and the configfs team,
>
> I am reporting a configfs use-after-free found by syzkaller.
>
> Summary:
> A configfs config-item rmdir(2) can land in configfs_drop_dentry() with
> sd->s_dentry pointing at a dentry whose RCU grace period has not yet
> elapsed. The spin_lock(&dentry->d_lock) at fs/configfs/inode.c:209 then
> reads freed slab memory and KASAN reports a slab-use-after-free.
Thanks for the report. I was able to reproduce it on linus' upstream
tree.
I've came up with the following fix, would you mind trying it, please?
commit d78c04736ef0ede76093c780a188560b6baed3c3
Author: Breno Leitao <leitao@debian.org>
Date: Wed May 27 06:25:49 2026 -0400
configfs: fix UAF in configfs_drop_dentry() after failed attribute lookup
When configfs_lookup() matches an attribute it publishes the new dentry
into sd->s_dentry (and dentry->d_fsdata) before calling
configfs_create() to allocate the inode:
dentry->d_fsdata = configfs_get(sd);
sd->s_dentry = dentry;
spin_unlock(&configfs_dirent_lock);
inode = configfs_create(dentry, mode);
if (IS_ERR(inode)) {
configfs_put(sd);
return ERR_CAST(inode);
}
If configfs_create() fails (e.g. new_inode() returns NULL under memory
pressure or fault injection), the lookup returns an error and the
caller dputs the now-negative dentry, which goes through
__dentry_kill() and is freed via call_rcu().
Because the dentry never gained an inode it does not go through the
.d_iput op (configfs_d_iput), which is the only place that clears
sd->s_dentry. sd therefore keeps a stale pointer to the freed dentry.
A subsequent rmdir of the parent item walks the parent's s_children
list in detach_attrs() and configfs_drop_dentry() does
spin_lock(&sd->s_dentry->d_lock) on freed memory:
BUG: KASAN: slab-use-after-free in _raw_spin_lock+0xac/0x110
Read of size 1 at addr ffff00012bacd028 by task repro/2440
_raw_spin_lock+0xac/0x110
configfs_drop_dentry+0x48/0x158 [configfs]
detach_attrs.isra.0+0x18c/0x494 [configfs]
configfs_rmdir+0x450/0x71c [configfs]
vfs_rmdir+0x170/0x620
...
Freed by task 0:
__d_free+0x28/0x34
rcu_do_batch+0x37c/0x1bd0
...
Last potentially related work creation:
call_rcu+0x34/0x68
dentry_free+0xe8/0x3e0
__dentry_kill+0x404/0x604
dput+0x14/0x30
lookup_open.isra.0+0x6ac/0xc00
path_openat+0xd18/0x2588
Fix this by tearing down the sd<->dentry linkage in the
configfs_create() error path, under configfs_dirent_lock, mirroring
what configfs_d_iput() would have done for a positive dentry.
Reported-by: Farhad Alemi <farhad.alemi@berkeley.edu>
Signed-off-by: Breno Leitao <leitao@debian.org>
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 362b6ff9b908..68d857dcb2d9 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -486,6 +486,22 @@ static struct dentry * configfs_lookup(struct inode *dir,
inode = configfs_create(dentry, mode);
if (IS_ERR(inode)) {
+ /*
+ * configfs_create() failed (e.g. -ENOMEM
+ * from new_inode()). The dentry will be
+ * dput()ed by the caller and freed via RCU;
+ * because it never gained an inode,
+ * configfs_d_iput() will not run to clear
+ * sd->s_dentry. Drop the linkage here so a
+ * later detach_attrs() walking the parent's
+ * s_children list does not dereference a
+ * freed dentry in configfs_drop_dentry().
+ */
+ spin_lock(&configfs_dirent_lock);
+ if (sd->s_dentry == dentry)
+ sd->s_dentry = NULL;
+ dentry->d_fsdata = NULL;
+ spin_unlock(&configfs_dirent_lock);
configfs_put(sd);
return ERR_CAST(inode);
}
next prev parent reply other threads:[~2026-05-27 10:28 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-27 3:42 [BUG] configfs: slab-use-after-free in configfs_drop_dentry() on rmdir Farhad Alemi
2026-05-27 10:27 ` Breno Leitao [this message]
2026-05-30 17:18 ` Farhad Alemi
2026-06-02 7:17 ` Al Viro
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=ahbG94EFLD5ntnYr@gmail.com \
--to=leitao@debian.org \
--cc=a.hindborg@kernel.org \
--cc=farhad.alemi@berkeley.edu \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.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