Re: [PATCH] xarray: fix index jumping backwards in xas_find()

From: Krystian Kaniewski

Date: Fri Sep 04 2026 - 09:18:21 EST


I have fixed the test issue and submitted patch as v2. I'm sorry about issue v1 caused, hopefully v2 is going to be fully correct now.

On 9/4/2026 10:41 AM, Krystian Kaniewski wrote:
Hello,

Thanks for running tests on my patch. I've quickly looked into the test
result and the problem seems to be related to check_multi_find_4() test and
not the fix itself. I'll send a v2 patch once I get the test fixed.

pt., 4 wrz 2026 o 10:22 Mike Rapoport <rppt@xxxxxxxxxx> napisał(a):

On Thu, Sep 03, 2026 at 11:22:51AM -0700, Andrew Morton wrote:
On Thu, 3 Sep 2026 13:48:55 +0000 (UTC) "syzbot" <syzbot@xxxxxxxxxx>
wrote:
From: Krystian Kaniewski <krystianmkaniewski@xxxxxxxxx>

A bug in the XArray iterator xas_find() causes the iterator's index
(xas->xa_index) to jump backwards when iterating over a multi-index
entry
(like a THP) that resides in a non-leaf node and is concurrently split.

When iterating over a multi-index entry in a non-leaf node, xas_load()
sets
xas->xa_offset to the base offset of the entry, but leaves
xas->xa_index at
the requested index. When the caller subsequently wants to advance to
the
next entry, xas_find() is called. xas_find() attempts to synchronize
xas->xa_offset with xas->xa_index before advancing. However, the fixup
logic was incorrectly restricted to leaf nodes (!xas->xa_node->shift).
Because the THP resides in a non-leaf node, the fixup is skipped.

As a result, xas_find() simply increments xas->xa_offset and
recalculates
xas->xa_index based on this new offset. This causes xas->xa_index to
jump
backwards. If the THP was concurrently split, the entry at the new
offset
is a node pointer, so xas_find() descends into it and returns the
folio at
the backwards index. The caller (filemap_map_pages()) then calculates
the
PTE pointer based on this backwards index, resulting in an invalid
memory
access such as an out-of-bounds read or use-after-free on a page-table
page
freed via tlb_remove_table_rcu().

To fix this, check if xas->xa_offset matches get_offset(xas->xa_index,
xas->xa_node). If it does not and the node is a non-leaf node, set
xas->xa_offset to get_offset(xas->xa_index, xas->xa_node) before
advancing.
Also add test cases in test_xarray to verify xas_find() behavior when
iterating over and splitting multi-index entries.
Thanks. But the changelog omits vital information: a description of
the userspace-visible runtime effects of the bug.

Fixes: b803b42823d0 ("xarray: Add XArray iterators")
Assisted-by: Gemini:gemini-3.7-flash syzbot
Reported-by: syzbot+b72767277f29b6407083@xxxxxxxxxxxxxxxxxxxxxxxxx
Closes: https://syzkaller.appspot.com/bug?extid=b72767277f29b6407083
I see from there that it was a use-after-free, detected by KASAN. I'll
update the changelog and I'll add cc:stable.

I'll queue the patch for testing while awaiting review input.
The testing shows there are issues with this patch:


https://github.com/linux-mm/linux-mm/actions/runs/33815757662/job/100847425973

And since it's in mm-unstable now it breaks all CI jobs :(

Link:
https://syzkaller.appspot.com/ai_job?id=a01c56bd-74d0-411c-afb4-ee6f0cb6cb61

--
Sincerely yours,
Mike.