Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 89db5346 authored by Matthew Wilcox (Oracle)'s avatar Matthew Wilcox (Oracle) Committed by Greg Kroah-Hartman
Browse files

ida: Fix crash in ida_free when the bitmap is empty



commit af73483f4e8b6f5c68c9aa63257bdd929a9c194a upstream.

The IDA usually detects double-frees, but that detection failed to
consider the case when there are no nearby IDs allocated and so we have a
NULL bitmap rather than simply having a clear bit.  Add some tests to the
test-suite to be sure we don't inadvertently reintroduce this problem.
Unfortunately they're quite noisy so include a message to disregard
the warnings.

Reported-by: default avatarZhenghan Wang <wzhmmmmm@gmail.com>
Signed-off-by: default avatarMatthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: default avatarHugo SIMELIERE <hsimeliere.opensource@witekio.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 6a967835
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -471,7 +471,7 @@ static void ida_remove(struct ida *ida, int id)
	} else {
		btmp = bitmap->bitmap;
	}
	if (!test_bit(offset, btmp))
	if (!bitmap || !test_bit(offset, btmp))
		goto err;

	__clear_bit(offset, btmp);
+40 −0
Original line number Diff line number Diff line
@@ -150,6 +150,45 @@ static void ida_check_conv(struct ida *ida)
	IDA_BUG_ON(ida, !ida_is_empty(ida));
}

/*
 * Check various situations where we attempt to free an ID we don't own.
 */
static void ida_check_bad_free(struct ida *ida)
{
	unsigned long i;

	printk("vvv Ignore \"not allocated\" warnings\n");
	/* IDA is empty; all of these will fail */
	ida_free(ida, 0);
	for (i = 0; i < 31; i++)
		ida_free(ida, 1 << i);

	/* IDA contains a single value entry */
	IDA_BUG_ON(ida, ida_alloc_min(ida, 3, GFP_KERNEL) != 3);
	ida_free(ida, 0);
	for (i = 0; i < 31; i++)
		ida_free(ida, 1 << i);

	/* IDA contains a single bitmap */
	IDA_BUG_ON(ida, ida_alloc_min(ida, 1023, GFP_KERNEL) != 1023);
	ida_free(ida, 0);
	for (i = 0; i < 31; i++)
		ida_free(ida, 1 << i);

	/* IDA contains a tree */
	IDA_BUG_ON(ida, ida_alloc_min(ida, (1 << 20) - 1, GFP_KERNEL) != (1 << 20) - 1);
	ida_free(ida, 0);
	for (i = 0; i < 31; i++)
		ida_free(ida, 1 << i);
	printk("^^^ \"not allocated\" warnings over\n");

	ida_free(ida, 3);
	ida_free(ida, 1023);
	ida_free(ida, (1 << 20) - 1);

	IDA_BUG_ON(ida, !ida_is_empty(ida));
}

static DEFINE_IDA(ida);

static int ida_checks(void)
@@ -162,6 +201,7 @@ static int ida_checks(void)
	ida_check_leaf(&ida, 1024 * 64);
	ida_check_max(&ida);
	ida_check_conv(&ida);
	ida_check_bad_free(&ida);

	printk("IDA: %u of %u tests passed\n", tests_passed, tests_run);
	return (tests_run != tests_passed) ? 0 : -EINVAL;