[PATCH] fs/adfs: check name length of big directory entries
From: Vamsi Krishna Kattamuri
Date: Fri Oct 02 2026 - 06:28:41 EST
The F+ (big directory) entry format stores the object name length on
disc as a 32-bit value, bigdirobnamelen. adfs_fplus_getnext() stores
this value in struct object_info::name_len and then copies that many
bytes from the directory buffers into the fixed-size obj->name array
with adfs_dir_copyfrom(), which only validates the source range, not
the destination.
Nothing validates bigdirobnamelen, so a corrupt or maliciously
crafted filesystem image can specify a name length greater than
sizeof(obj->name), causing up to 4MB of attacker-controlled data to
be written past the end of the array. Both callers of ->getnext()
instantiate struct object_info on their stacks - adfs_fplus_iterate()
via readdir() and adfs_lookup() via path resolution - so this is a
stack buffer overflow which is trivially triggered by listing or
stat'ing files on a crafted image.
adfs_object_fixup() also appends a four character ",xxx" filetype
suffix to the names of non-directory objects when the ftsuffix mount
option is enabled, so name lengths greater than ADFS_FPLUS_NAME_LEN
could still overflow the buffer by up to four bytes even when the
initial copy itself fits.
Reject entries whose name length exceeds the maximum defined for the
F+ format, which also leaves room for the filetype suffix.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Vamsi Krishna Kattamuri <kattamurivamsikrishna17@xxxxxxxxx>
---
fs/adfs/dir_fplus.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/fs/adfs/dir_fplus.c b/fs/adfs/dir_fplus.c
index 4a15924014da..ec663bc12a92 100644
--- a/fs/adfs/dir_fplus.c
+++ b/fs/adfs/dir_fplus.c
@@ -192,6 +192,11 @@ adfs_fplus_getnext(struct adfs_dir *dir, struct
object_info *obj)
obj->indaddr = le32_to_cpu(bde.bigdirindaddr);
obj->attr = le32_to_cpu(bde.bigdirattr);
obj->name_len = le32_to_cpu(bde.bigdirobnamelen);
+ if (obj->name_len > ADFS_FPLUS_NAME_LEN) {
+ adfs_error(dir->sb, "object name length %u exceeds maximum",
+ obj->name_len);
+ return -ENAMETOOLONG;
+ }
offset = adfs_fplus_offset(h, le32_to_cpu(h->bigdirentries));
offset += le32_to_cpu(bde.bigdirobnameptr);
--
2.47.3