[PATCH v2] gfs2: reject an over-long directory entry name in gfs2_check_dirent

From: Michael Bommarito

Date: Tue Jul 14 2026 - 08:06:57 EST


gfs2_check_dirent() validates a directory entry against the space in its
dirent record but never bounds de_name_len to GFS2_FNAMESIZE. A dirent
with a large de_rec_len can therefore carry a de_name_len far greater than
GFS2_FNAMESIZE and still pass the check. That length flows unclamped
through do_filldir_main() -> dir_emit() to the ctx->actor. In the
NFS-export get_name path get_name_filldir() copies the name into the
fixed NAME_MAX+1 byte buffer nbuf[] on the exportfs_decode_fh_raw() stack
with memcpy(gnfd->name, name, length), so a crafted or corrupted on-disk
directory overflows that buffer.

Impact: an out-of-bounds write past the NAME_MAX+1 byte name buffer
(KASAN), reachable when a gfs2 filesystem carrying a crafted directory
entry is re-exported over NFS and a file handle is resolved.

Reject dirents whose name length exceeds GFS2_FNAMESIZE at the read-path
check, so no over-long name reaches any dirent consumer.

Fixes: b3b94faa5fe5 ("[GFS2] The core of GFS2")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Michael Bommarito <michael.bommarito@xxxxxxxxx>
---
v2: move the validation from get_name_filldir() into gfs2_check_dirent()
on the dirent read path, per Andrew Price's review, so every dirent
consumer is protected rather than only the NFS get_name path; and
correct the buffer description (the destination is the NAME_MAX+1
byte nbuf[] in exportfs_decode_fh_raw(), not a GFS2_FNAMESIZE buffer).
v1: https://lore.kernel.org/gfs2/20260711150845.gfs2-getname-v1@bommarito/

v1: https://lore.kernel.org/gfs2/20260711150808.2919076-1-michael.bommarito@xxxxxxxxx/

Evidence: a crafted gfs2 image with a directory dirent whose de_name_len
is 300 (record length left valid so the existing size check passes),
resolved with open_by_handle_at() on a KASAN + KASAN_STACK kernel. Stock:
BUG: KASAN: stack-out-of-bounds in get_name_filldir, Write of size 300 into
the NAME_MAX+1 byte nbuf[] object of the exportfs_decode_fh_raw() stack
frame, via open_by_handle_at -> exportfs_decode_fh_raw -> reconnect_path ->
gfs2_get_name -> do_filldir_main -> get_name_filldir. Patched:
gfs2_check_dirent() rejects the entry (name length exceeds GFS2_FNAMESIZE)
and the handle resolves to ESTALE; a valid name still reconnects. Built
clean, no new warnings.

fs/gfs2/dir.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index 0237b36b9eb16..905b658a05177 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -521,6 +521,10 @@ static int gfs2_check_dirent(struct gfs2_sbd *sdp,
unlikely(sizeof(struct gfs2_dirent)+be16_to_cpu(dent->de_name_len) >
size))
goto error;
+ msg = "name length exceeds GFS2_FNAMESIZE";
+ if (!gfs2_dirent_sentinel(dent) &&
+ unlikely(be16_to_cpu(dent->de_name_len) > GFS2_FNAMESIZE))
+ goto error;
return 0;
error:
fs_warn(sdp, "%s: %s (%s)\n",
--
2.53.0