Commit 173a1b3a authored by Matthew Wilcox (Oracle)'s avatar Matthew Wilcox (Oracle) Committed by Wenyu Huang
Browse files

ida: Fix crash in ida_free when the bitmap is empty

stable inclusion
from stable-v4.19.320
commit 89db5346acb5a15e670c4fb3b8f3c30fa30ebc15
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IAZAKK

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=89db5346acb5a15e670c4fb3b8f3c30fa30ebc15



-------------------------------------------------

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>
Signed-off-by: default avatarWenyu Huang <huangwenyu5@huawei.com>
parent 3c02090e
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;