[PATCH] ecryptfs: reject destroy mount crypt stat if sb's active refer is 1

From: Edward Adam Davis

Date: Thu Sep 17 2026 - 20:35:39 EST


When sget_fc() is executed within ecryptfs_get_tree(), the active reference
count of the superblock is not incremented (e.g., via grab_super()).

A fault injection [0] causes super_setup_bdi() to fail and return -ENOMEM,
triggering a jump to the out1 label in ecryptfs_get_tree(). At this point,
the superblock's active reference count remains at its initial value of 1,
it causing deactivate_locked_super() to free the superblock and the sbi,
potentially hitting uaf [1].

Destroy mount crypt stat should only be performed when the superblock's
active reference count is greater than 1.

[0]
FAULT_INJECTION: forcing a failure.
name failslab, interval 1, probability 0, space 0, times 0
Call Trace:
security_sb_alloc+0x25/0x240
sget_fc+0x3ca/0x1f20
ecryptfs_get_tree+0x615/0x15b0
vfs_get_tree+0x92/0x320
path_mount+0x7d0/0x24c0

[1]
BUG: KASAN: slab-use-after-free in ecryptfs_destroy_mount_crypt_stat+0x28f/0x360 fs/ecryptfs/crypto.c:137
Read of size 4 at addr ffff88802b378610 by task syz.0.20/5927
Call Trace:
ecryptfs_destroy_mount_crypt_stat+0x28f/0x360 fs/ecryptfs/crypto.c:137
ecryptfs_get_tree+0x10b6/0x15b0 fs/ecryptfs/main.c:566
vfs_get_tree+0x92/0x320 fs/super.c:1933
fc_mount fs/namespace.c:1198 [inline]
do_new_mount_fc fs/namespace.c:3772 [inline]
do_new_mount fs/namespace.c:3848 [inline]

Allocated by task 5927:
ecryptfs_init_fs_context+0x6b/0x200 fs/ecryptfs/main.c:617
alloc_fs_context+0x60c/0xf40 fs/fs_context.c:295
do_new_mount fs/namespace.c:3828 [inline]

Freed by task 5927:
ecryptfs_kill_block_super+0x81/0xa0 fs/ecryptfs/main.c:586
deactivate_locked_super+0xbd/0x140 fs/super.c:589
ecryptfs_get_tree+0x10e9/0x15b0 fs/ecryptfs/main.c:563
vfs_get_tree+0x92/0x320 fs/super.c:1933
fc_mount fs/namespace.c:1198 [inline]
do_new_mount_fc fs/namespace.c:3772 [inline]
do_new_mount fs/namespace.c:3848 [inline]

Fixes: 2ccde7c631f9 ("Clean ecryptfs ->get_sb() up")
Reported-by: syzbot+baa24e4b7e349e388442@xxxxxxxxxxxxxxxxxxxxxxxxx
Closes: https://syzkaller.appspot.com/bug?extid=baa24e4b7e349e388442
Tested-by: syzbot+baa24e4b7e349e388442@xxxxxxxxxxxxxxxxxxxxxxxxx
Signed-off-by: Edward Adam Davis <eadavis@xxxxxxxx>
---
fs/ecryptfs/main.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index 5f37cddb956f..6b82c077c0d6 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -441,7 +441,7 @@ static int ecryptfs_get_tree(struct fs_context *fc)
const char *err = "Getting sb failed";
struct inode *inode;
struct path path;
- int rc;
+ int rc, active;

if (!fc->source) {
rc = -EINVAL;
@@ -468,6 +468,7 @@ static int ecryptfs_get_tree(struct fs_context *fc)
goto out;
}

+ active = atomic_read(&s->s_active);
rc = super_setup_bdi(s);
if (rc)
goto out1;
@@ -562,7 +563,7 @@ static int ecryptfs_get_tree(struct fs_context *fc)
out1:
deactivate_locked_super(s);
out:
- if (sbi)
+ if (sbi && active > 1)
ecryptfs_destroy_mount_crypt_stat(&sbi->mount_crypt_stat);

printk(KERN_ERR "%s; rc = [%d]\n", err, rc);
--
2.43.0