All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kees Cook <keescook@chromium.org>
To: linux-hardening@vger.kernel.org
Cc: Kees Cook <keescook@chromium.org>,
	David Gow <davidgow@google.com>,
	linux-kernel@vger.kernel.org
Subject: [PATCH] kunit/fortify: Validate __alloc_size attribute results
Date: Tue, 18 Oct 2022 01:27:41 -0700	[thread overview]
Message-ID: <20221018082559.never.406-kees@kernel.org> (raw)

Validate the effect of the __alloc_size attribute on allocators. If the
compiler doesn't support __builtin_dynamic_object_size(), skip the test.

Cc: linux-hardening@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
To pass this depends on the following patches:
https://lore.kernel.org/lkml/20221018073430.never.551-kees@kernel.org/
https://lore.kernel.org/lkml/20221018082232.never.213-kees@kernel.org/
To not be skipped, either GCC 12 or Clang is needed.
---
 lib/fortify_kunit.c | 92 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 92 insertions(+)

diff --git a/lib/fortify_kunit.c b/lib/fortify_kunit.c
index 409af07f340a..5076ba11adfd 100644
--- a/lib/fortify_kunit.c
+++ b/lib/fortify_kunit.c
@@ -16,7 +16,10 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <kunit/test.h>
+#include <linux/device.h>
 #include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
 
 static const char array_of_10[] = "this is 10";
 static const char *ptr_of_11 = "this is 11!";
@@ -60,9 +63,98 @@ static void control_flow_split_test(struct kunit *test)
 	KUNIT_EXPECT_EQ(test, want_minus_one(pick), SIZE_MAX);
 }
 
+#define check_alloc(alloc, free)	do {				\
+	size_t expected = size;						\
+	void *p = alloc;						\
+	KUNIT_EXPECT_TRUE_MSG(test, p != NULL, #alloc " failed?!\n");	\
+	KUNIT_EXPECT_EQ_MSG(test, __builtin_dynamic_object_size(p, 1),	\
+		expected,						\
+		"__alloc_size() not working with " #alloc "\n");	\
+	free;								\
+} while (0)
+
+static volatile size_t unknown_size = 50;
+
+static void alloc_size_test(struct kunit *test)
+{
+#if !__has_builtin(__builtin_dynamic_object_size)
+	kunit_skip(test, "Compiler is missing __builtin_dynamic_object_size() support\n");
+#else
+	const char device_name[] = "fortify-test";
+	struct device *dev;
+	gfp_t gfp = GFP_KERNEL | __GFP_NOWARN;
+	size_t size = unknown_size, prev_size;
+	void *orig;
+
+	/* kmalloc()-family */
+	check_alloc(kmalloc(size++, gfp),			kfree(p));
+	check_alloc(kmalloc_node(size++, gfp, NUMA_NO_NODE),	kfree(p));
+	check_alloc(kzalloc(size++, gfp),			kfree(p));
+	check_alloc(kzalloc_node(size++, gfp, NUMA_NO_NODE),	kfree(p));
+	check_alloc(kcalloc(1, size++, gfp),			kfree(p));
+	check_alloc(kcalloc_node(1, size++, gfp, NUMA_NO_NODE),	kfree(p));
+	check_alloc(kmalloc_array(1, size++, gfp),		kfree(p));
+	check_alloc(kmalloc_array_node(1, size++, gfp, NUMA_NO_NODE), kfree(p));
+	check_alloc(__kmalloc(size++, gfp),			kfree(p));
+	check_alloc(__kmalloc_node(size++, gfp, NUMA_NO_NODE),	kfree(p));
+
+	/* kmemdup() */
+	prev_size = size;
+	size = 11;
+	check_alloc(kmemdup("hello there", size, gfp),		kfree(p));
+	size = prev_size + 1;
+
+	/* krealloc()-family */
+	orig = kmalloc(size++, gfp);
+	check_alloc(krealloc(orig, size++, gfp),		kfree(p));
+	orig = kmalloc(size++, gfp);
+	check_alloc(krealloc_array(orig, 1, size++, gfp),	kfree(p));
+
+	/* vmalloc()-family */
+	check_alloc(vmalloc(size++),				vfree(p));
+	check_alloc(vzalloc(size++),				vfree(p));
+	check_alloc(__vmalloc(size++, gfp),			vfree(p));
+
+	/* kvalloc()-family */
+	check_alloc(kvmalloc(size++, gfp),			kvfree(p));
+	check_alloc(kvmalloc_node(size++, gfp, NUMA_NO_NODE),	kvfree(p));
+	check_alloc(kvzalloc(size++, gfp),			kvfree(p));
+	check_alloc(kvzalloc_node(size++, gfp, NUMA_NO_NODE),	kvfree(p));
+	check_alloc(kvcalloc(1, size++, gfp),			kvfree(p));
+	check_alloc(kvmalloc_array(1, size++, gfp),		kvfree(p));
+
+	/* kvrealloc() */
+	prev_size = size++;
+	orig = kvmalloc(prev_size, gfp);
+	check_alloc(kvrealloc(orig, prev_size, size++, gfp),	kfree(p));
+
+	/* Create dummy device for devm_kmalloc()-family tests. */
+	dev = root_device_register(device_name);
+	KUNIT_ASSERT_FALSE_MSG(test, IS_ERR(dev),
+			       "Cannot register test device\n");
+
+	/* devm_kmalloc()-family */
+	check_alloc(devm_kmalloc(dev, size++, gfp),		devm_kfree(dev, p));
+	check_alloc(devm_kzalloc(dev, size++, gfp),		devm_kfree(dev, p));
+
+	/* devm_kmemdup() */
+	prev_size = size;
+	size = 4;
+	check_alloc(devm_kmemdup(dev, "Ohai", size, gfp),	devm_kfree(dev, p));
+	size = prev_size + 1;
+
+	/* devm_kremalloc() */
+	orig = devm_kmalloc(dev, size++, gfp);
+	check_alloc(devm_krealloc(dev, orig, size++, gfp),	devm_kfree(dev, p));
+
+	device_unregister(dev);
+#endif
+}
+
 static struct kunit_case fortify_test_cases[] = {
 	KUNIT_CASE(known_sizes_test),
 	KUNIT_CASE(control_flow_split_test),
+	KUNIT_CASE(alloc_size_test),
 	{}
 };
 
-- 
2.34.1


             reply	other threads:[~2022-10-18  8:28 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-18  8:27 Kees Cook [this message]
2022-10-19  3:35 ` [PATCH] kunit/fortify: Validate __alloc_size attribute results David Gow
2022-10-19  5:45   ` Kees Cook
2022-10-19  6:29     ` David Gow
2022-11-01 22:04       ` Kees Cook

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221018082559.never.406-kees@kernel.org \
    --to=keescook@chromium.org \
    --cc=davidgow@google.com \
    --cc=linux-hardening@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.