summaryrefslogtreecommitdiff
path: root/tools/perf/scripts/python
diff options
context:
space:
mode:
authorJoseph Qi <joseph.qi@linux.alibaba.com>2026-10-24 23:10:07 +0800
committerAndrew Morton <akpm@linux-foundation.org>2026-11-02 19:18:54 -0800
commitf48151da595e74efdc23d83d8d6d142207b8c731 (patch)
treee3cef8d4656cad84f2ca1f00a853660a6ebf95c8 /tools/perf/scripts/python
parent0a8f258c0f012314c36b9e4818cdc0178c68f891 (diff)
ocfs2: read the xattr entry hash before defragmenting the bucket
Patch series "ocfs2: fix stale xattr entry pointers and empty header reads", v1. Five defects in the ocfs2 extended attribute code, plus one robustness measure that belongs with them, all on the paths that move entries between a block, a bucket and an index tree. They fall into two groups. Stale entry pointers (patches 1 to 3) ocfs2_xa_set() writes through a pointer into xh_entries[] that two of its callers invalidate first. Defragmenting a bucket ends in a sort() on xe_name_hash, and lib/sort.c is an unstable heapsort, so entries that share a hash can trade slots. Copying a block into a bucket changes the order outright, since a block holds its entries in insertion order while a bucket holds them by hash, yet ocfs2_xattr_update_xattr_search() relocates the search by the index the entry had in the block. Neither path compares the entry's name with the one being set, so setxattr() can replace a neighbouring attribute's value and still report success, or trip ocfs2_xa_reuse_entry()'s BUG_ON. Patch 1 takes the hash before the sort; patches 2 and 3 look the entry up again afterwards. Reads of an empty entry array (patches 4 to 6) A block and a bucket may both hold no entries: ocfs2_xa_remove_entry() keeps the last slot when it removes the only one, so an empty bucket still carries the hash it is keyed by. Three sites index xh_entries[] without checking xh_count and so read xh_entries[-1], which lands on the header and comes back as xh_count | xh_free_start << 16. Nothing faults, but the value is acted on: the collision check reports no collision for an empty bucket, the divide commits a sentinel hash that hides part of the key space from ocfs2_xattr_bucket_find(), and the block to bucket copy claims storage the bucket does not hold. Patches 4 to 6 guard each site and keep the one read of xh_entries[0] that ocfs2_xa_remove_entry() documents as intentional. This patch (of 6): ocfs2_xattr_set_entry_index_block() takes the hash a bucket split has to work with out of xs->here, but only after ocfs2_xattr_set_entry_bucket() has tried and failed to fit the entry. That call defragments the bucket when it runs out of room, and ocfs2_defrag_xattr_bucket() finishes by sorting the entry array by name hash. lib/sort.c is not stable, so two entries sharing a hash may trade slots and xs->here is left naming an entry other than the one the search found. The hash value itself survives the permutation -- the array is already sorted, so a slot can only exchange with an equal-hash neighbour -- but there is no reason to depend on that. Pick the hash up before the set, where xs->here is unambiguously the entry the search landed on. No functional change intended. Link: https://lore.kernel.org/20261024151012.1059683-1-joseph.qi@linux.alibaba.com Link: https://lore.kernel.org/20261024151012.1059683-2-joseph.qi@linux.alibaba.com Fixes: e39baff18b85 ("ocfs2: use the stored hash when checking xattr bucket collision") Signed-off-by: Joseph Qi <joseph.qi@linux.alibaba.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Cc: Heming Zhao <heming.zhao@suse.com> Cc: Mark Fasheh <mark@fasheh.com> Cc: Joel Becker <jlbec@evilplan.org>
Diffstat (limited to 'tools/perf/scripts/python')
0 files changed, 0 insertions, 0 deletions