[PATCH 5.15 180/206] ext4: fix memory leaks in ext4_fname_{setup_filename,prepare_lookup}

Greg Kroah-Hartman
2026-02-04T15:01:29Z

From: Luís Henriques <lhenriques@suse.de>

[ Upstream commit 7ca4b085f430f3774c3838b3da569ceccd6a0177 ]

If the filename casefolding fails, we'll be leaking memory from the
fscrypt_name struct, namely from the 'crypto_buf.name' member.

Make sure we free it in the error path on both ext4_fname_setup_filename()
and ext4_fname_prepare_lookup() functions.

Cc: stable@kernel.org
Fixes: 1ae98e295fa2 ("ext4: optimize match for casefolded encrypted dirs")
Signed-off-by: Luís Henriques <lhenriques@suse.de>
Reviewed-by: Eric Biggers <ebiggers@google.com>
Link: https://lore.kernel.org/r/20230803091713.13239-1-lhenriques@suse.de
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
[ fs/ext4/crypto.c was removed by commit
a7550b30ab70 ("ext4 crypto: migrate into vfs's crypto engine") since
v4.8, so apply this patch to fs/ext4/ext4.h in v5.15. Move
ext4_fname_free_filename() to the front of ext4_fname_setup_filename()
to fix a build issue. ]
Signed-off-by: Bin Lan <lanbincn@139.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/ext4/ext4.h | 38 +++++++++++++++++++++-----------------
1 file changed, 21 insertions(+), 17 deletions(-)

--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2749,6 +2749,23 @@ static inline void ext4_fname_from_fscry
dst->crypto_buf = src->crypto_buf;
}

+static inline void ext4_fname_free_filename(struct ext4_filename *fname)
+{
+ struct fscrypt_name name;
+
+ name.crypto_buf = fname->crypto_buf;
+ fscrypt_free_filename(&name);
+
+ fname->crypto_buf.name = NULL;
+ fname->usr_fname = NULL;
+ fname->disk_name.name = NULL;
+
+#ifdef CONFIG_UNICODE
+ kfree(fname->cf_name.name);
+ fname->cf_name.name = NULL;
+#endif
+}
+
static inline int ext4_fname_setup_filename(struct inode *dir,
const struct qstr *iname,
int lookup,
@@ -2765,6 +2782,8 @@ static inline int ext4_fname_setup_filen

#ifdef CONFIG_UNICODE
err = ext4_fname_setup_ci_filename(dir, iname, fname);
+ if (err)
+ ext4_fname_free_filename(fname);
#endif
return err;
}
@@ -2784,26 +2803,11 @@ static inline int ext4_fname_prepare_loo

#ifdef CONFIG_UNICODE
err = ext4_fname_setup_ci_filename(dir, &dentry->d_name, fname);
+ if (err)
+ ext4_fname_free_filename(fname);
#endif
return err;
}
-
-static inline void ext4_fname_free_filename(struct ext4_filename *fname)
-{
- struct fscrypt_name name;
-
- name.crypto_buf = fname->crypto_buf;
- fscrypt_free_filename(&name);
-
- fname->crypto_buf.name = NULL;
- fname->usr_fname = NULL;
- fname->disk_name.name = NULL;
-
-#ifdef CONFIG_UNICODE
- kfree(fname->cf_name.name);
- fname->cf_name.name = NULL;
-#endif
-}
#else /* !CONFIG_FS_ENCRYPTION */
static inline int ext4_fname_setup_filename(struct inode *dir,
const struct qstr *iname,