mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] adfs: bound big-directory entry name length to ADFS_FPLUS_NAME_LEN
@ 2026-11-06  9:45 hyunjungg
  0 siblings, 0 replies; only message in thread
From: hyunjungg @ 2026-11-06  9:45 UTC (permalink / raw)
  To: Andrew Morton; +Cc: Russell King, linux-fsdevel, linux-kernel, Hyunjung Ko

From: Hyunjung Ko <hj351016@gmail.com>

adfs_fplus_getnext() reads a directory entry's name length straight from
the on-disk big-directory entry and uses it, unchecked, as the length of
a copy into the fixed-size name buffer of the on-stack struct object_info:

	obj->name_len = le32_to_cpu(bde.bigdirobnamelen);

	offset = adfs_fplus_offset(h, le32_to_cpu(h->bigdirentries));
	offset += le32_to_cpu(bde.bigdirobnameptr);

	ret = adfs_dir_copyfrom(obj->name, dir, offset, obj->name_len);

obj->name is char[ADFS_MAX_NAME_LEN] (260 bytes), but bigdirobnamelen is
an attacker-controlled __le32 with no upper bound.  adfs_dir_copyfrom()
only validates that the source offset+length stay within the directory
buffers; it does not bound the length against the destination.  A crafted
image whose directory holds enough data at the name offset therefore lets
a single entry drive a copy of up to ~4 GiB into the 260-byte stack
buffer, a stack out-of-bounds write (detected by CONFIG_STACKPROTECTOR as
a corrupted canary, or by KASAN with CONFIG_KASAN_STACK).  The copy is
reached from both readdir and ->lookup via adfs_dir_lookup_byname().

The old-format directory parser (dir_f.c) already caps names at
ADFS_F_NAME_LEN while reading them; the big-directory parser has no
equivalent guard even though ADFS_FPLUS_NAME_LEN (255) is defined for
exactly this limit and is used elsewhere (super.c, s_namelen).

Reject entries whose name length exceeds ADFS_FPLUS_NAME_LEN before the
copy.  255 bytes fit in the 260-byte buffer and still leave room for the
4-byte ",xyz" filetype suffix that adfs_object_fixup() may append.

To trigger: build an ADFS image with a valid F+ ("big") directory whose
header, tail (BIGDIRENDNAME magic, matching masseq) and computed
check byte all validate, containing one adfs_bigdirentry with
bigdirobnamelen set to e.g. 300 and bigdirobnameptr pointing at 300 bytes
of in-bounds directory data.  mount -o loop followed by ls (or opening a
path under the mount) overflows obj->name.  The check byte is a computed
checksum, which is why random fuzzing rarely reaches this code; a
hand-crafted image does.

Reproduced under KASAN on 7.3-rc3 and 7.4-rc1 by mounting a crafted
ADFS image and running ls: KASAN reports a stack-out-of-bounds in the
adfs_fplus_getnext() name copy path.

Signed-off-by: Hyunjung Ko <hj351016@gmail.com>
---
 fs/adfs/dir_fplus.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/fs/adfs/dir_fplus.c b/fs/adfs/dir_fplus.c
--- a/fs/adfs/dir_fplus.c
+++ b/fs/adfs/dir_fplus.c
@@ -191,6 +191,9 @@ adfs_fplus_getnext(struct adfs_dir *dir, struct object_info *obj)
 	obj->attr     = le32_to_cpu(bde.bigdirattr);
 	obj->name_len = le32_to_cpu(bde.bigdirobnamelen);

+	if (obj->name_len > ADFS_FPLUS_NAME_LEN)
+		return -EIO;
+
 	offset = adfs_fplus_offset(h, le32_to_cpu(h->bigdirentries));
 	offset += le32_to_cpu(bde.bigdirobnameptr);

--
2.43.0

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-11-06  9:45 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-06  9:45 [PATCH] adfs: bound big-directory entry name length to ADFS_FPLUS_NAME_LEN hyunjungg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®