Commit 047a8a0a authored by Daniel Latypov's avatar Daniel Latypov Committed by Shuah Khan
Browse files

kunit: make kunit_kfree() only work on pointers from kunit_malloc() and friends



kunit_kfree() exists to clean up allocations from kunit_kmalloc() and
friends early instead of waiting for this to happen automatically at the
end of the test.

But it can be used on *anything* registered with the kunit resource API.

E.g. the last 2 statements are equivalent:
  struct kunit_resource *res = something();
  kfree(res->data);
  kunit_put_resource(res);

The problem is that there could be multiple resources that point to the
same `data`.

E.g. you can have a named resource acting as a pseudo-global variable in
a test. If you point it to data allocated with kunit_kmalloc(), then
calling `kunit_kfree(ptr)` has the chance to delete either the named
resource or to kfree `ptr`.
Which one it does depends on the order the resources are registered as
kunit_kfree() will delete resources in LIFO order.

So this patch restricts kunit_kfree() to only working on resources
created by kunit_kmalloc(). Calling it is therefore guaranteed to free
the memory, not do anything else.

Note: kunit_resource_instance_match() wasn't used outside of KUnit, so
it should be safe to remove from the public interface. It's also
generally dangerous, as shown above, and shouldn't be used.

Signed-off-by: default avatarDaniel Latypov <dlatypov@google.com>
Reviewed-by: default avatarDavid Gow <davidgow@google.com>
Reviewed-by: default avatarBrendan Higgins <brendanhiggins@google.com>
Signed-off-by: default avatarShuah Khan <skhan@linuxfoundation.org>
parent 4db4598b
Loading
Loading
Loading
Loading
+0 −16
Original line number Diff line number Diff line
@@ -300,22 +300,6 @@ typedef bool (*kunit_resource_match_t)(struct kunit *test,
				       struct kunit_resource *res,
				       void *match_data);

/**
 * kunit_resource_instance_match() - Match a resource with the same instance.
 * @test: Test case to which the resource belongs.
 * @res: The resource.
 * @match_data: The resource pointer to match against.
 *
 * An instance of kunit_resource_match_t that matches a resource whose
 * allocation matches @match_data.
 */
static inline bool kunit_resource_instance_match(struct kunit *test,
						 struct kunit_resource *res,
						 void *match_data)
{
	return res->data == match_data;
}

/**
 * kunit_resource_name_match() - Match a resource with the same name.
 * @test: Test case to which the resource belongs.
+7 −0
Original line number Diff line number Diff line
@@ -161,6 +161,13 @@ static void kunit_resource_test_alloc_resource(struct kunit *test)
	kunit_put_resource(res);
}

static inline bool kunit_resource_instance_match(struct kunit *test,
						 struct kunit_resource *res,
						 void *match_data)
{
	return res->data == match_data;
}

/*
 * Note: tests below use kunit_alloc_and_get_resource(), so as a consequence
 * they have a reference to the associated resource that they must release
+8 −2
Original line number Diff line number Diff line
@@ -713,12 +713,18 @@ void *kunit_kmalloc_array(struct kunit *test, size_t n, size_t size, gfp_t gfp)
}
EXPORT_SYMBOL_GPL(kunit_kmalloc_array);

static inline bool kunit_kfree_match(struct kunit *test,
				     struct kunit_resource *res, void *match_data)
{
	/* Only match resources allocated with kunit_kmalloc() and friends. */
	return res->free == kunit_kmalloc_array_free && res->data == match_data;
}

void kunit_kfree(struct kunit *test, const void *ptr)
{
	struct kunit_resource *res;

	res = kunit_find_resource(test, kunit_resource_instance_match,
				  (void *)ptr);
	res = kunit_find_resource(test, kunit_kfree_match, (void *)ptr);

	/*
	 * Removing the resource from the list of resources drops the