From: Andrew Morton <akpm@linux-foundation.org>
To: mm-commits@vger.kernel.org,willy@infradead.org,
syzbot+b72767277f29b6407083@syzkaller.appspotmail.com,stable@vger.kernel.org,
rppt@kernel.org,jose.fernandez@linux.dev,krystianmkaniewski@gmail.com,
akpm@linux-foundation.org
Subject: [merged mm-hotfixes-stable] xarray-fix-index-jumping-backwards-in-xas_find.patch removed from -mm tree
Date: Mon, 09 Nov 2026 22:45:49 -0800 [thread overview]
Message-ID: <20261110064549.C6E331F0089F@smtp.kernel.org> (raw)
The quilt patch titled
Subject: xarray: fix index jumping backwards in xas_find()
has been removed from the -mm tree. Its filename was
xarray-fix-index-jumping-backwards-in-xas_find.patch
This patch was dropped because it was merged into the mm-hotfixes-stable branch
of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
------------------------------------------------------
From: Krystian Kaniewski <krystianmkaniewski@gmail.com>
Subject: xarray: fix index jumping backwards in xas_find()
Date: Fri, 4 Sep 2026 14:12:59 +0200
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().
A userspace access that faults in a file-backed mapping can trigger this
path. When the index moves backwards, filemap_map_pages() can calculate a
PTE outside the page locked for fault-around and dereference a freed
page-table page, resulting in a KASAN-detected use-after-free read.
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.
Link: https://lore.kernel.org/20260904121301.200049-1-krystianmkaniewski@gmail.com
Fixes: b803b42823d0 ("xarray: Add XArray iterators")
Reported-by: syzbot+b72767277f29b6407083@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=b72767277f29b6407083
Closes: https://syzkaller.appspot.com/ai_job?id=a01c56bd-74d0-411c-afb4-ee6f0cb6cb61
Signed-off-by: Krystian Kaniewski <krystianmkaniewski@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Tested-by: Jose Fernandez (Anthropic) <jose.fernandez@linux.dev>
Link: https://lore.kernel.org/20261104-jf-filemap-v2-pedro-reply-r2-74c87c6fbcf@linux.dev
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: <stable@vger.kernel.org>
---
lib/test_xarray.c | 70 ++++++++++++++++++++++++++++++++++++++++++++
lib/xarray.c | 8 +++--
2 files changed, 75 insertions(+), 3 deletions(-)
--- a/lib/test_xarray.c~xarray-fix-index-jumping-backwards-in-xas_find
+++ a/lib/test_xarray.c
@@ -1247,6 +1247,75 @@ static noinline void check_multi_find_3(
}
}
+static noinline void check_multi_find_4(struct xarray *xa)
+{
+#ifdef CONFIG_XARRAY_MULTI
+ unsigned int order = XA_CHUNK_SHIFT + 1;
+ unsigned long next = 1UL << order;
+ unsigned long start = next - 1;
+ XA_STATE(xas, xa, start);
+ XA_STATE_ORDER(split, xa, 0, 0);
+ void *entry;
+ unsigned long i;
+
+ /* Multi-index entry in two slots of a non-leaf node. */
+ xa_store_order(xa, 0, order, xa_mk_index(0), GFP_KERNEL);
+ XA_BUG_ON(xa, xa_store_index(xa, next, GFP_KERNEL) != NULL);
+
+ rcu_read_lock();
+ entry = xas_find(&xas, ULONG_MAX);
+ XA_BUG_ON(xa, entry != xa_mk_index(0));
+ XA_BUG_ON(xa, xas.xa_index != start);
+
+ entry = xas_find(&xas, ULONG_MAX);
+ XA_BUG_ON(xa, entry != xa_mk_index(next));
+ XA_BUG_ON(xa, xas.xa_index != next);
+
+ entry = xas_find(&xas, ULONG_MAX);
+ XA_BUG_ON(xa, entry != NULL);
+ rcu_read_unlock();
+
+ xa_erase_index(xa, next);
+ xa_erase_index(xa, 0);
+ XA_BUG_ON(xa, !xa_empty(xa));
+
+ /* Split the multi-index entry after a lookup begins inside it. */
+ xa_store_order(xa, 0, order, xa_mk_index(0), GFP_KERNEL);
+ XA_BUG_ON(xa, xa_store_index(xa, next, GFP_KERNEL) != NULL);
+
+ xas_set(&xas, start);
+ rcu_read_lock();
+ entry = xas_find(&xas, ULONG_MAX);
+ XA_BUG_ON(xa, entry != xa_mk_index(0));
+ XA_BUG_ON(xa, xas.xa_index != start);
+ rcu_read_unlock();
+
+ xas_split_alloc(&split, xa_mk_index(0), order, GFP_KERNEL);
+ if (xas_error(&split)) {
+ XA_BUG_ON(xa, true);
+ goto out;
+ }
+ xas_lock(&split);
+ xas_split(&split, xa_mk_index(0), order);
+ for (i = 0; i < next; i++)
+ __xa_store(xa, i, xa_mk_index(i), 0);
+ xas_unlock(&split);
+
+ rcu_read_lock();
+ entry = xas_find(&xas, ULONG_MAX);
+ XA_BUG_ON(xa, entry != xa_mk_index(next));
+ XA_BUG_ON(xa, xas.xa_index != next);
+
+ entry = xas_find(&xas, ULONG_MAX);
+ XA_BUG_ON(xa, entry != NULL);
+ rcu_read_unlock();
+
+out:
+ xa_destroy(xa);
+ XA_BUG_ON(xa, !xa_empty(xa));
+#endif
+}
+
static noinline void check_find_1(struct xarray *xa)
{
unsigned long i, j, k;
@@ -1370,6 +1439,7 @@ static noinline void check_find(struct x
check_multi_find_1(xa, i);
check_multi_find_2(xa);
check_multi_find_3(xa);
+ check_multi_find_4(xa);
}
/* See find_swap_entry() in mm/shmem.c */
--- a/lib/xarray.c~xarray-fix-index-jumping-backwards-in-xas_find
+++ a/lib/xarray.c
@@ -1410,9 +1410,11 @@ void *xas_find(struct xa_state *xas, uns
entry = xas_load(xas);
if (entry || xas_not_node(xas->xa_node))
return entry;
- } else if (!xas->xa_node->shift &&
- xas->xa_offset != (xas->xa_index & XA_CHUNK_MASK)) {
- xas->xa_offset = ((xas->xa_index - 1) & XA_CHUNK_MASK) + 1;
+ } else if (xas->xa_offset != get_offset(xas->xa_index, xas->xa_node)) {
+ if (!xas->xa_node->shift)
+ xas->xa_offset = ((xas->xa_index - 1) & XA_CHUNK_MASK) + 1;
+ else
+ xas->xa_offset = get_offset(xas->xa_index, xas->xa_node);
}
xas_next_offset(xas);
_
Patches currently in -mm which might be from krystianmkaniewski@gmail.com are
reply other threads:[~2026-11-10 6:45 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261110064549.C6E331F0089F@smtp.kernel.org \
--to=akpm@linux-foundation.org \
--cc=jose.fernandez@linux.dev \
--cc=krystianmkaniewski@gmail.com \
--cc=mm-commits@vger.kernel.org \
--cc=rppt@kernel.org \
--cc=stable@vger.kernel.org \
--cc=syzbot+b72767277f29b6407083@syzkaller.appspotmail.com \
--cc=willy@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.