aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorKees Cook2023-04-07 12:27:14 -0700
committerKees Cook2024-02-29 13:38:02 -0800
commit4ce615e798a752d4431fcc52960478906dec2f0e (patch)
treed76038c7680c29c84a99c9c02dd327e0788e685a /lib
parent1a78f8cb5daac77405e449f5305ad72c01818a46 (diff)
fortify: Provide KUnit counters for failure testing
The standard C string APIs were not designed to have a failure mode; they were expected to always succeed without memory safety issues. Normally, CONFIG_FORTIFY_SOURCE will use fortify_panic() to stop processing, as truncating a read or write may provide an even worse system state. However, this creates a problem for testing under things like KUnit, which needs a way to survive failures. When building with CONFIG_KUNIT, provide a failure path for all users of fortify_panic, and track whether the failure was a read overflow or a write overflow, for KUnit tests to examine. Inspired by similar logic in the slab tests. Signed-off-by: Kees Cook <keescook@chromium.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/fortify_kunit.c41
-rw-r--r--lib/string_helpers.c2
2 files changed, 43 insertions, 0 deletions
diff --git a/lib/fortify_kunit.c b/lib/fortify_kunit.c
index 7a88b5dd3d27..4ba7d02fdd78 100644
--- a/lib/fortify_kunit.c
+++ b/lib/fortify_kunit.c
@@ -15,8 +15,17 @@
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+/* Redefine fortify_panic() to track failures. */
+void fortify_add_kunit_error(int write);
+#define fortify_panic(func, write, retfail) do { \
+ __fortify_report(FORTIFY_REASON(func, write)); \
+ fortify_add_kunit_error(write); \
+ return (retfail); \
+} while (0)
+
#include <kunit/device.h>
#include <kunit/test.h>
+#include <kunit/test-bug.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/string.h>
@@ -27,10 +36,34 @@
# define __compiletime_strlen __builtin_strlen
#endif
+static struct kunit_resource read_resource;
+static struct kunit_resource write_resource;
+static int fortify_read_overflows;
+static int fortify_write_overflows;
+
static const char array_of_10[] = "this is 10";
static const char *ptr_of_11 = "this is 11!";
static char array_unknown[] = "compiler thinks I might change";
+void fortify_add_kunit_error(int write)
+{
+ struct kunit_resource *resource;
+ struct kunit *current_test;
+
+ current_test = kunit_get_current_test();
+ if (!current_test)
+ return;
+
+ resource = kunit_find_named_resource(current_test,
+ write ? "fortify_write_overflows"
+ : "fortify_read_overflows");
+ if (!resource)
+ return;
+
+ (*(int *)resource->data)++;
+ kunit_put_resource(resource);
+}
+
static void known_sizes_test(struct kunit *test)
{
KUNIT_EXPECT_EQ(test, __compiletime_strlen("88888888"), 8);
@@ -318,6 +351,14 @@ static int fortify_test_init(struct kunit *test)
if (!IS_ENABLED(CONFIG_FORTIFY_SOURCE))
kunit_skip(test, "Not built with CONFIG_FORTIFY_SOURCE=y");
+ fortify_read_overflows = 0;
+ kunit_add_named_resource(test, NULL, NULL, &read_resource,
+ "fortify_read_overflows",
+ &fortify_read_overflows);
+ fortify_write_overflows = 0;
+ kunit_add_named_resource(test, NULL, NULL, &write_resource,
+ "fortify_write_overflows",
+ &fortify_write_overflows);
return 0;
}
diff --git a/lib/string_helpers.c b/lib/string_helpers.c
index 9291dc74ae01..5e53d42e32bb 100644
--- a/lib/string_helpers.c
+++ b/lib/string_helpers.c
@@ -18,6 +18,8 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/string_helpers.h>
+#include <kunit/test.h>
+#include <kunit/test-bug.h>
/**
* string_get_size - get the size in the specified units