tOS XFS Driver — Heap Out-of-Bounds Read in Shortform Directory
In xfs_vfs_readdir of xfs.c, the XFS_DINODE_FMT_LOCAL (shortform directory) code path parses on-disk directory entries without validating the entry pointer or its derived name length against the bounds of the inode buffer being parsed, unlike the sibling XFS_DINODE_FMT_EXTENTS path which performs an equivalent check. A crafted XFS filesystem image with an oversized namelen or ncount field in a shortform directory inode can cause the parser to read past the end of the inode buffer's heap allocation, leaking adjacent heap memory into the returned directory listing, simply by listing the directory.
After finding the bounds-checking gaps during directory parsing in the NTFS and EXT2 drivers in ASI-2026-0006 and ASI-2026-0007, we reviewed xfs.c to see whether the same pattern existed in the XFS driver. In xfs_vfs_readdir we noticed an interesting asymmetry: the XFS_DINODE_FMT_EXTENTS (extent-format directory) path correctly bounded its entry pointer against the end of the block buffer, but the sibling XFS_DINODE_FMT_LOCAL (shortform directory) path performed no equivalent check at all.
The shortform directory entry pointer was advanced and dereferenced using on-disk namelen/ncount/i8count fields with no check against the end of the inode_buf heap allocation. This stood in direct contrast to the sibling FMT_EXTENTS path, which already bounds its entry pointer against the block buffer end — within the same function, one code path was protected and the other was not.
An attacker prepares a malicious XFS filesystem image containing a directory inode using the shortform (FMT_LOCAL) format with an oversized namelen or ncount field. The victim mounts this image and lists a directory on it (e.g. with ls). During this operation, the parser reads past the end of the inode_buf allocation, leaking adjacent heap memory into the returned directory listing. Exploitation requires physical access (mounting the image) and listing the directory.
The shortform directory entry pointer was advanced and dereferenced using on-disk namelen/ncount/i8count fields with no check against the end of the inode_buf heap allocation, unlike the sibling FMT_EXTENTS path which already bounds its entry pointer against the block buffer end.
Added bounds checks against inode_buf + inode_size before dereferencing each shortform entry's header and name/inode-number bytes, mirroring the check already present in the FMT_EXTENTS branch.
CWE-125, CWE-20
Artfical DT Developer Talha Berk Arslan