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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.