All of lore.kernel.org
 help / color / mirror / Atom feed
* [f2fs-dev] [PATCH] f2fs-tools: fix casefolded dentry hash for names that fold beyond F2FS_NAME_LEN
@ 2026-10-05 20:17 Juhyung Park
  2026-10-10 17:27 ` Juhyung Park
  2026-10-11  1:12 ` Chao Yu via Linux-f2fs-devel
  0 siblings, 2 replies; 3+ messages in thread
From: Juhyung Park @ 2026-10-05 20:17 UTC (permalink / raw)
  To: linux-f2fs-devel, jaegeuk, kernel-team

Since kernel commit 43c780ba2624 ("f2fs: rework filename handling",
v5.8), the kernel casefolds a name into an F2FS_NAME_LEN buffer, and if
the folded name doesn't fit, it falls back to hashing the raw on-disk
name (f2fs_init_casefolded_name()).

f2fs_dentry_hash() still folds into a PATH_MAX buffer, as the original
kernel implementation did, so it hashes the folded name instead. NFD
decomposition can grow a name considerably (each 3-byte Hangul syllable
becomes 6-9 bytes), so a valid <= 255-byte name can fold to more than
255 bytes. For such a name, fsck.f2fs computes a different hash than the
kernel. It then "fixes" the kernel-written hash_code to a wrong value,
and the file becomes unreachable via lookup (ENOENT) unless the kernel
falls back to linear lookup (e.g. lookup_mode=compat). Later fsck runs
consider the broken hash correct and report nothing.

This silently makes user files unreachable on Android, where /data/media
is casefolded and fsck is triggered on a full OTA and a kernel version
change. This personally happened to me on my daily driver unit. Since
the buggy fsck considers its own hash correct afterwards, the damage is
never reported, and it repeats for every new such file the kernel
creates.

Minimal reproducer:

  NAME=$(printf '가%.0s' $(seq 43))  # 129 bytes raw, 258 bytes folded
  truncate -s 128M cf.img
  mkfs.f2fs -q -O extra_attr,casefold -C utf8 cf.img
  mount -o loop cf.img mnt
  mkdir mnt/d && chattr +F mnt/d && touch "mnt/d/$NAME"
  umount mnt
  fsck.f2fs -f -y cf.img
  mount -o loop,ro cf.img mnt
  stat "mnt/d/$NAME"

Before this patch, fsck.f2fs wrongfully modifies the hash and breaks
kernel lookup:

  stat: cannot statx 'mnt/d/가가가가가가가가가가가가가가가가가가가가가가가가가가가가가가가가가가가가가가가가가가가': No such file or directory

Use an F2FS_NAME_LEN buffer, as the kernel does. utf8_casefold() already
returns -ENAMETOOLONG on overflow, which falls back to the raw-name hash.
With this, fsck.f2fs leaves the reproducer image untouched, and it also
repairs the hashes that the buggy version previously rewrote.

Fixes: ce64ea0815bf ("f2fs-tools: Add support for Casefolding")
Signed-off-by: Juhyung Park <qkrwngud825@gmail.com>
---
 lib/libf2fs.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/libf2fs.c b/lib/libf2fs.c
index 93f36ca6a30c..75b7e1a7376f 100644
--- a/lib/libf2fs.c
+++ b/lib/libf2fs.c
@@ -499,10 +499,10 @@ f2fs_hash_t f2fs_dentry_hash(int encoding, int casefolded,
 	unsigned char *buff;
 
 	if (len && casefolded) {
-		buff = malloc(sizeof(char) * PATH_MAX);
+		buff = malloc(sizeof(char) * F2FS_NAME_LEN);
 		ASSERT(buff);
 
-		dlen = table->ops->casefold(table, name, len, buff, PATH_MAX);
+		dlen = table->ops->casefold(table, name, len, buff, F2FS_NAME_LEN);
 		if (dlen < 0) {
 			free(buff);
 			goto opaque_seq;
-- 
2.55.0



_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-10-11  1:12 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-05 20:17 [f2fs-dev] [PATCH] f2fs-tools: fix casefolded dentry hash for names that fold beyond F2FS_NAME_LEN Juhyung Park
2026-10-10 17:27 ` Juhyung Park
2026-10-11  1:12 ` Chao Yu via Linux-f2fs-devel

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.