mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-23 12:14:10 +08:00
resource, kunit: fix user-after-free in resource_test_region_intersects()
In resource_test_insert_resource(), the pointer is used in error message
after kfree(). This is user-after-free. To fix this, we need to call
kunit_add_action_or_reset() to schedule memory freeing after usage. But
kunit_add_action_or_reset() itself may fail and free the memory. So, its
return value should be checked and abort the test for failure. Then, we
found that other usage of kunit_add_action_or_reset() in
resource_test_region_intersects() needs to be fixed too. We fix all these
user-after-free bugs in this patch.
Link: https://lkml.kernel.org/r/20240930070611.353338-1-ying.huang@intel.com
Fixes: 99185c10d5
("resource, kunit: add test case for region_intersects()")
Signed-off-by: "Huang, Ying" <ying.huang@intel.com>
Reported-by: Kees Bakker <kees@ijzerbout.nl>
Closes: https://lore.kernel.org/lkml/87ldzaotcg.fsf@yhuang6-desk2.ccr.corp.intel.com/
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: David Hildenbrand <david@redhat.com>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
3d5854d75e
commit
0665d7a39b
@ -169,6 +169,8 @@ static void resource_test_intersection(struct kunit *test)
|
|||||||
#define RES_TEST_RAM3_SIZE SZ_1M
|
#define RES_TEST_RAM3_SIZE SZ_1M
|
||||||
#define RES_TEST_TOTAL_SIZE ((RES_TEST_WIN1_OFFSET + RES_TEST_WIN1_SIZE))
|
#define RES_TEST_TOTAL_SIZE ((RES_TEST_WIN1_OFFSET + RES_TEST_WIN1_SIZE))
|
||||||
|
|
||||||
|
KUNIT_DEFINE_ACTION_WRAPPER(kfree_wrapper, kfree, const void *);
|
||||||
|
|
||||||
static void remove_free_resource(void *ctx)
|
static void remove_free_resource(void *ctx)
|
||||||
{
|
{
|
||||||
struct resource *res = (struct resource *)ctx;
|
struct resource *res = (struct resource *)ctx;
|
||||||
@ -177,6 +179,14 @@ static void remove_free_resource(void *ctx)
|
|||||||
kfree(res);
|
kfree(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void resource_test_add_action_or_abort(
|
||||||
|
struct kunit *test, void (*action)(void *), void *ctx)
|
||||||
|
{
|
||||||
|
KUNIT_ASSERT_EQ_MSG(test, 0,
|
||||||
|
kunit_add_action_or_reset(test, action, ctx),
|
||||||
|
"Fail to add action");
|
||||||
|
}
|
||||||
|
|
||||||
static void resource_test_request_region(struct kunit *test, struct resource *parent,
|
static void resource_test_request_region(struct kunit *test, struct resource *parent,
|
||||||
resource_size_t start, resource_size_t size,
|
resource_size_t start, resource_size_t size,
|
||||||
const char *name, unsigned long flags)
|
const char *name, unsigned long flags)
|
||||||
@ -185,7 +195,7 @@ static void resource_test_request_region(struct kunit *test, struct resource *pa
|
|||||||
|
|
||||||
res = __request_region(parent, start, size, name, flags);
|
res = __request_region(parent, start, size, name, flags);
|
||||||
KUNIT_ASSERT_NOT_NULL(test, res);
|
KUNIT_ASSERT_NOT_NULL(test, res);
|
||||||
kunit_add_action_or_reset(test, remove_free_resource, res);
|
resource_test_add_action_or_abort(test, remove_free_resource, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void resource_test_insert_resource(struct kunit *test, struct resource *parent,
|
static void resource_test_insert_resource(struct kunit *test, struct resource *parent,
|
||||||
@ -202,11 +212,11 @@ static void resource_test_insert_resource(struct kunit *test, struct resource *p
|
|||||||
res->end = start + size - 1;
|
res->end = start + size - 1;
|
||||||
res->flags = flags;
|
res->flags = flags;
|
||||||
if (insert_resource(parent, res)) {
|
if (insert_resource(parent, res)) {
|
||||||
kfree(res);
|
resource_test_add_action_or_abort(test, kfree_wrapper, res);
|
||||||
KUNIT_FAIL_AND_ABORT(test, "Fail to insert resource %pR\n", res);
|
KUNIT_FAIL_AND_ABORT(test, "Fail to insert resource %pR\n", res);
|
||||||
}
|
}
|
||||||
|
|
||||||
kunit_add_action_or_reset(test, remove_free_resource, res);
|
resource_test_add_action_or_abort(test, remove_free_resource, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void resource_test_region_intersects(struct kunit *test)
|
static void resource_test_region_intersects(struct kunit *test)
|
||||||
@ -220,7 +230,7 @@ static void resource_test_region_intersects(struct kunit *test)
|
|||||||
"test resources");
|
"test resources");
|
||||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent);
|
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent);
|
||||||
start = parent->start;
|
start = parent->start;
|
||||||
kunit_add_action_or_reset(test, remove_free_resource, parent);
|
resource_test_add_action_or_abort(test, remove_free_resource, parent);
|
||||||
|
|
||||||
resource_test_request_region(test, parent, start + RES_TEST_RAM0_OFFSET,
|
resource_test_request_region(test, parent, start + RES_TEST_RAM0_OFFSET,
|
||||||
RES_TEST_RAM0_SIZE, "Test System RAM 0", flags);
|
RES_TEST_RAM0_SIZE, "Test System RAM 0", flags);
|
||||||
|
Loading…
Reference in New Issue
Block a user