Commit 430f24f9 authored by Matthew Wilcox (Oracle)'s avatar Matthew Wilcox (Oracle)
Browse files

XArray: Fix infinite loop with entry at ULONG_MAX



If there is an entry at ULONG_MAX, xa_for_each() will overflow the
'index + 1' in xa_find_after() and wrap around to 0.  Catch this case
and terminate the loop by returning NULL.

Signed-off-by: default avatarMatthew Wilcox (Oracle) <willy@infradead.org>
Cc: stable@vger.kernel.org
parent 82a95849
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -1046,11 +1046,28 @@ static noinline void check_find_3(struct xarray *xa)
	xa_destroy(xa);
}

static noinline void check_find_4(struct xarray *xa)
{
	unsigned long index = 0;
	void *entry;

	xa_store_index(xa, ULONG_MAX, GFP_KERNEL);

	entry = xa_find_after(xa, &index, ULONG_MAX, XA_PRESENT);
	XA_BUG_ON(xa, entry != xa_mk_index(ULONG_MAX));

	entry = xa_find_after(xa, &index, ULONG_MAX, XA_PRESENT);
	XA_BUG_ON(xa, entry);

	xa_erase_index(xa, ULONG_MAX);
}

static noinline void check_find(struct xarray *xa)
{
	check_find_1(xa);
	check_find_2(xa);
	check_find_3(xa);
	check_find_4(xa);
	check_multi_find(xa);
	check_multi_find_2(xa);
}
+3 −0
Original line number Diff line number Diff line
@@ -1849,6 +1849,9 @@ void *xa_find_after(struct xarray *xa, unsigned long *indexp,
	XA_STATE(xas, xa, *indexp + 1);
	void *entry;

	if (xas.xa_index == 0)
		return NULL;

	rcu_read_lock();
	for (;;) {
		if ((__force unsigned int)filter < XA_MAX_MARKS)