All of lore.kernel.org
 help / color / mirror / Atom feed
From: Juhyung Park <qkrwngud825@gmail.com>
To: linux-f2fs-devel@lists.sourceforge.net, jaegeuk@kernel.org,
	kernel-team@android.com
Subject: [f2fs-dev] [PATCH] f2fs-tools: fix casefolded dentry hash for names that fold beyond F2FS_NAME_LEN
Date: Tue,  6 Oct 2026 05:17:11 +0900	[thread overview]
Message-ID: <20261005201711.699080-1-qkrwngud825@gmail.com> (raw)

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

             reply	other threads:[~2026-10-05 20:17 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-05 20:17 Juhyung Park [this message]
2026-10-10 17:27 ` [f2fs-dev] [PATCH] f2fs-tools: fix casefolded dentry hash for names that fold beyond F2FS_NAME_LEN Juhyung Park
2026-10-11  1:12 ` Chao Yu via Linux-f2fs-devel

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=20261005201711.699080-1-qkrwngud825@gmail.com \
    --to=qkrwngud825@gmail.com \
    --cc=jaegeuk@kernel.org \
    --cc=kernel-team@android.com \
    --cc=linux-f2fs-devel@lists.sourceforge.net \
    /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.