[PATCH v3 0/4] ntfs: serialize attribute-list access
Hyunchul Lee <[email protected]> Wed, 29 Jul 2026 08:38:28 +0900
| Newsgroups | dev.linux.lists.ntfs,org.kernel.vger.stable |
|---|---|
| Message-ID | <[email protected]> |
ntfs_external_attr_find() walks base_ni->attr_list using raw attr_list_entry pointers stored in ctx->al_entry. Because other paths can replace base_ni->attr_list and free the old buffer while a lookup still holds one of those cursors, a concurrent attribute-list mutation can turn a saved cursor into a stale or freed pointer. Reported in: https://lore.kernel.org/all/[email protected]/ This series fixes that hazard by replacing the raw ctx->al_entry pointer with restartable, generation-checked locators, and by adding locks that serialize attribute-list buffer replacement and on-disk persistence so concurrent mutations cannot corrupt state or double-free memory. The four patches are: 1. ntfs: replace raw ctx->al_entry with restartable attr-list locators 2. ntfs: protect attribute-list buffer replacement with attr_list_persist_lock 3. ntfs: protect attribute-list creation/teardown with attr_list_persist_lock 4. ntfs: protect mapping-pairs attr-list updates with attr_list_persist_lock What changes ------------ Instead of a raw struct attr_list_entry *, the search context now carries three value-only locators: - al_cursor -- where ntfs_external_attr_find() resumes enumeration; invalidated on generation mismatch. - al_insert -- insertion point captured on -ENOENT lookups. - al_exact -- immutable identity snapshot (type, lowest_vcn, mft_reference, instance, name length) used by writers to re-locate the same ALE after a buffer replacement. The inode gains an rw_semaphore, attr_list_lock, and a 64-bit attr_list_gen counter. The lock protects attr_list, attr_list_size, and attr_list_gen; the counter is bumped on every buffer replacement so a stale locator is detected before it is dereferenced. Because ntfs_attrlist_update() can sleep and recurse back into attribute lookups, attr_list_lock cannot be held across persistence. A separate mutex, attr_list_persist_lock, serializes the whole publish-buffer -> persist-to-disk -> rollback-on-failure transaction for each mutator. Lock ordering is: mrec_lock -> attr_list_persist_lock -> attr_list_lock attr_list_lock is never held across anything that can take runlist.lock or extent_lock. --- * Changes in v3: * Patch 1: fix $ATTRIBUTE_LIST extent double-delivery during mapping-pairs rebuild (xfstests generic/040) * Patch 3: fix self-deadlock on attr_list_persist_lock during attr-list rebuild (xfstests generic/040) * Changes in v2: * add Fixes tags * add Reported-by and Tested-by tags --- Hyunchul Lee (4): ntfs: replace raw ctx->al_entry with restartable attr-list locators ntfs: protect attribute-list buffer replacement with attr_list_persist_lock ntfs: protect attribute-list creation/teardown with attr_list_persist_lock ntfs: protect mapping-pairs attr-list updates with attr_list_persist_lock fs/ntfs/attrib.c | 446 ++++++++++++++++++++++++++++++++++++++++++++--------- fs/ntfs/attrib.h | 48 +++++- fs/ntfs/attrlist.c | 139 +++++++++++++---- fs/ntfs/index.c | 3 +- fs/ntfs/inode.c | 71 +++++++-- fs/ntfs/inode.h | 9 ++ fs/ntfs/namei.c | 2 +- fs/ntfs/super.c | 2 +- 8 files changed, 594 insertions(+), 126 deletions(-) --- base-commit: 985e0ded13bc51da8d5eba3a3bad1cb3ffb4870f change-id: 20260727-topic-attr-list-lock-v6-f1a909e3c859 Best regards, -- Hyunchul Lee <[email protected]>