| From: |
| Artem Blagodarenko <artem.blagodarenko-AT-gmail.com> |
| To: |
| linux-ext4-AT-vger.kernel.org |
| Subject: |
| [PATCH v4 00/11] Data in direntry (dirdata) feature |
| Date: |
| Wed, 24 Jun 2026 09:36:29 -0400 |
| Message-ID: |
| <20260624133642.18438-1-ablagodarenko@thelustrecollective.com> |
| Cc: |
| adilger.kernel-AT-dilger.ca, Artem Blagodarenko <ablagodarenko-AT-thelustrecollective.com> |
| Archive-link: |
| Article |
EXT4 currently stores a hash in the directory entry
(dirent) immediately after the file name to support
simultaneous fscrypt and casefold functionality.
It has been discussed within the EXT4 community that
this hash could instead be stored in dirdata. This
would make it the second (or third, in the case of
64-bit inode counts) user of dirdata.
At the same time, the existing format—where the hash
is placed after the file name—must continue to be
supported. With these patches, EXT4 can handle the
hash in both formats.
The first user of this feature is LUFID -
Locally Unique File ID.
Support for fscrypt and case-insensitive directories
with dirdata enabled has been verified using a
dedicated xfstest submitted to the xfstests list as
a separate patch.
e2fsprogs support is provided in a separate patches
series.
Changes in v4:
- syzbot ci actually ran the v3 series and found real,
reproducible KASAN slab-out-of-bounds and use-after-free
reads, all rooted in ext4_dir_entry_len() decoding
de->rec_len with a hardcoded full-block size even when
the entry lives in a smaller buffer (inline directory
data). Gave it an explicit blocksize parameter and fixed
every caller to pass the real containing-buffer size.
- dx_get_dx_info() and get_dx_countlimit() additionally
needed dir=NULL (not just the right blocksize) when
computing past the on-disk '.'/'..' entries, since those
never carry the casefold+fscrypt hash regardless of the
directory's feature flags; passing the real dir made
ext4_dirent_rec_len() add 8 bytes of hash space that was
never written on disk, corrupting dx_root_info's offset
for every casefold+encrypt directory.
- ext4_dirdata_get()/ext4_dirdata_set(): fixed bounds checks
that were off by EXT4_BASE_DIR_LEN (the 8-byte dirent
header), a LUFID memcpy that used the wrong source/length,
an out-of-bounds array write for maximum-length filenames,
and an uninitialized gap byte leaking a stale memory byte
to disk.
- EXT4_IOC_SET_LUFID: fixed ddh_length under-counting the
header byte (silently dropping the last byte of every
LUFID payload), rejected '.'/'..' as targets, added a
missing inode_permission(dir, MAY_WRITE) check, and closed
a data race on the shared i_dirdata field by also locking
the target inode (not just the parent directory) for the
duration it's used.
- Fixed a missing bounds check in ext4_dx_csum_verify()/
ext4_dx_csum_set() that let an unvalidated on-disk `count`
field drive an out-of-bounds checksum read. This bug
predates this series, but is included as patch 1 (ahead
of the patch that touches this function) since it was
found via review of this series.
- Thanks to Sashiko AI review and to Xiao (xiaowu.417@qq.com)
for reproducing several of the above with concrete crash
logs and PoCs.
Artem Blagodarenko (11):
ext4: validate count against limit in ext4_dx_csum_verify/_set
ext4: replace ext4_dir_entry with ext4_dir_entry_2
ext4: add ext4_dir_entry_is_tail()
ext4: refactor dx_root to support variable dirent sizes
ext4: add dirdata format definitions and access helpers
ext4: preserve dirdata bits in get_dtype()
ext4: add ext4_dir_entry_len() and harden dirdata parsing
ext4: rename ext4_dir_rec_len() and clarify dirdata usage
ext4: dirdata feature
ext4: add dirdata set/get helpers
ext4: Add EXT4_IOC_SET_LUFID ioctl for setting LUFID on directory
entries
foofile.txt | 0
fs/ext4/dir.c | 9 +-
fs/ext4/ext4.h | 211 +++++++++++-
fs/ext4/inline.c | 41 ++-
fs/ext4/ioctl.c | 84 +++++
fs/ext4/namei.c | 699 +++++++++++++++++++++++++++++---------
fs/ext4/sysfs.c | 2 +
include/uapi/linux/ext4.h | 13 +
8 files changed, 861 insertions(+), 198 deletions(-)
create mode 100644 foofile.txt
--
2.43.7