Live Patching
 help / color / mirror / Atom feed
From: raschupkin.ri@gmail.com
To: live-patching@vger.kernel.org, joe.lawrence@redhat.com,
	pmladek@suse.com, mbenes@suse.cz, jikos@kernel.org,
	jpoimboe@kernel.org
Cc: Roman Rashchupkin <raschupkin.ri@gmail.com>
Subject: [PATCH 2/2] selftests/livepatch: Add tests for kprefcount_t support
Date: Sun, 14 Jul 2024 21:59:34 +0200	[thread overview]
Message-ID: <20240714195958.692313-3-raschupkin.ri@gmail.com> (raw)
In-Reply-To: <20240714195958.692313-1-raschupkin.ri@gmail.com>

From: Roman Rashchupkin <raschupkin.ri@gmail.com>

Signed-off-by: Roman Rashchupkin <raschupkin.ri@gmail.com>
---
 tools/testing/selftests/livepatch/Makefile    |   3 +-
 .../selftests/livepatch/test-kprefcount.sh    |  16 +++
 .../selftests/livepatch/test_modules/Makefile |   4 +-
 .../test_modules/test_klp_kprefcount.c        | 120 ++++++++++++++++++
 .../test_modules/test_klp_refcount.c          |  65 ++++++++++
 5 files changed, 206 insertions(+), 2 deletions(-)
 create mode 100755 tools/testing/selftests/livepatch/test-kprefcount.sh
 create mode 100644 tools/testing/selftests/livepatch/test_modules/test_klp_kprefcount.c
 create mode 100644 tools/testing/selftests/livepatch/test_modules/test_klp_refcount.c

diff --git a/tools/testing/selftests/livepatch/Makefile b/tools/testing/selftests/livepatch/Makefile
index 35418a4790be..48926ebc77f2 100644
--- a/tools/testing/selftests/livepatch/Makefile
+++ b/tools/testing/selftests/livepatch/Makefile
@@ -10,7 +10,8 @@ TEST_PROGS := \
 	test-state.sh \
 	test-ftrace.sh \
 	test-sysfs.sh \
-	test-syscall.sh
+	test-syscall.sh \
+	test-kprefcount.sh
 
 TEST_FILES := settings
 
diff --git a/tools/testing/selftests/livepatch/test-kprefcount.sh b/tools/testing/selftests/livepatch/test-kprefcount.sh
new file mode 100755
index 000000000000..8ea6c18f59dd
--- /dev/null
+++ b/tools/testing/selftests/livepatch/test-kprefcount.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+insmod test_modules/test_klp_refcount.ko
+insmod test_modules/test_klp_kprefcount.ko
+livepatch_enabled=/sys/kernel/livepatch/test_klp_kprefcount/enabled
+while [ ! -e $livepatch_enabled -o $(cat $livepatch_enabled) -eq 0 ]; do
+	sleep 0.01;
+done
+echo 0 > $livepatch_enabled
+while [ $(cat $livepatch_enabled) -eq 1 ]; do
+	sleep 0.01;
+done
+while [ -e $livepatch_enabled ]; do
+	sleep 0.01;
+done
+rmmod test_klp_kprefcount
+rmmod test_klp_refcount
diff --git a/tools/testing/selftests/livepatch/test_modules/Makefile b/tools/testing/selftests/livepatch/test_modules/Makefile
index e6e638c4bcba..c26797372e0d 100644
--- a/tools/testing/selftests/livepatch/test_modules/Makefile
+++ b/tools/testing/selftests/livepatch/test_modules/Makefile
@@ -11,7 +11,9 @@ obj-m += test_klp_atomic_replace.o \
 	test_klp_state2.o \
 	test_klp_state3.o \
 	test_klp_shadow_vars.o \
-	test_klp_syscall.o
+	test_klp_syscall.o \
+	test_klp_refcount.o \
+	test_klp_kprefcount.o
 
 # Ensure that KDIR exists, otherwise skip the compilation
 modules:
diff --git a/tools/testing/selftests/livepatch/test_modules/test_klp_kprefcount.c b/tools/testing/selftests/livepatch/test_modules/test_klp_kprefcount.c
new file mode 100644
index 000000000000..063f286ebcec
--- /dev/null
+++ b/tools/testing/selftests/livepatch/test_modules/test_klp_kprefcount.c
@@ -0,0 +1,120 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/livepatch.h>
+#include <linux/livepatch_refcount.h>
+
+extern refcount_t test_refcount;
+extern int TEST_LIVEPATCH_KPREFCOUNT;
+
+#define ITER 100
+#define NREF 10
+#define KP_NREF 10
+static struct ref_holder {
+	unsigned char v;
+} kp_ref_holders[KP_NREF] = { 0 };
+kprefcount_t *kp_test_ref = 0;
+
+static int livepatch_refcount_test_iter(void)
+{
+	int k, i;
+	for (k=0; k<ITER; k++) {
+		for (i=0; i<KP_NREF; i++)
+			refcount_inc(&test_refcount);
+		for (i=0; i<KP_NREF; i++)
+			if (kprefcount_dec_and_test(kp_test_ref, 0, 1)) {
+				pr_alert("livepatch refcount underflow\n");
+				return -1;
+			}
+	}
+	TEST_LIVEPATCH_KPREFCOUNT = 0;
+	return 0;
+}
+
+struct delayed_work kp_work_refcount;
+static void kp_test_refcount(struct work_struct *work)
+{
+	int i, k;
+	for (k=0; k<ITER; k++) {
+		for (i=0; i<KP_NREF; i++)
+			kprefcount_dec(kp_test_ref, &kp_ref_holders[i].v, 1);
+		// Intentional refcounter underflow for additional testing
+		for (i=0; i<KP_NREF-1; i++)
+			kprefcount_inc(kp_test_ref, &kp_ref_holders[i].v, 1);
+	}
+}
+
+static void kp_post_patch_callback(struct klp_object *klp_obj)
+{
+	schedule_delayed_work(&kp_work_refcount, 0);
+}
+
+static void kp_pre_unpatch_callback(struct klp_object *klp_obj)
+{
+	cancel_delayed_work_sync(&kp_work_refcount);
+}
+
+static struct klp_func funcs[] = {
+	{
+		.old_name = "refcount_test_iter",
+		.new_func = livepatch_refcount_test_iter,
+	}, { }
+};
+
+static struct klp_object objs[] = {
+	{
+		.name = "test_klp_refcount",
+		.funcs = funcs,
+		.callbacks = {
+			.post_patch = kp_post_patch_callback,
+			.pre_unpatch = kp_pre_unpatch_callback,
+		},
+	}, { }
+};
+
+static struct klp_patch patch = {
+	.mod = THIS_MODULE,
+	.objs = objs,
+};
+
+struct delayed_work work_refcount;
+
+static void do_test_refcount(struct work_struct *work)
+{
+	int i;
+	for (i=0; i<NREF; i++) {
+		if (refcount_read(&test_refcount) <= 1)
+			pr_info("LIVEPATCH refcount test done.\n");
+			return;
+		refcount_dec(&test_refcount);
+		if (refcount_read(&test_refcount) < 0)
+			pr_alert("post-livepatch refcount underflow\n");
+	}
+	for (i=0; i<NREF; i++)
+		refcount_inc(&test_refcount);
+}
+
+static int refcount_test_init(void)
+{
+	int ret;
+	kp_test_ref = kprefcount_alloc(&test_refcount, GFP_KERNEL);
+	if (!kp_test_ref) {
+		pr_alert("kprefcount_livepatch: memory allocation_failed");
+		return -1;
+	}
+	ret = klp_enable_patch(&patch);
+	INIT_DELAYED_WORK(&kp_work_refcount, kp_test_refcount);
+	return 0;
+}
+
+static void refcount_test_exit(void)
+{
+}
+
+module_init(refcount_test_init);
+module_exit(refcount_test_exit);
+MODULE_INFO(livepatch, "Y");
+MODULE_AUTHOR("Roman Rashchupkin <raschupkin.ri@gmail.com>");
+MODULE_DESCRIPTION("Livepatch test: kprefcount");
+MODULE_LICENSE("GPL");
diff --git a/tools/testing/selftests/livepatch/test_modules/test_klp_refcount.c b/tools/testing/selftests/livepatch/test_modules/test_klp_refcount.c
new file mode 100644
index 000000000000..bd9c57e63476
--- /dev/null
+++ b/tools/testing/selftests/livepatch/test_modules/test_klp_refcount.c
@@ -0,0 +1,65 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/livepatch.h>
+#include <linux/livepatch_refcount.h>
+
+#define ITER 100
+#define NREF 10
+int TEST_LIVEPATCH_KPREFCOUNT = 1;
+EXPORT_SYMBOL(TEST_LIVEPATCH_KPREFCOUNT);
+refcount_t test_refcount = REFCOUNT_INIT(1);
+EXPORT_SYMBOL(test_refcount);
+
+int refcount_test_iter(void)
+{
+	int i;
+	for (i=0; i<NREF; i++)
+		refcount_inc(&test_refcount);
+	for (i=0; i<NREF; i++)
+		if (refcount_dec_and_test(&test_refcount))
+			return -1;
+	return 0;
+}
+
+int refcount_test(void)
+{
+	int i;
+	for (i=0; i<ITER; i++) {
+		if (refcount_test_iter())
+			return -1;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(refcount_test);
+
+struct delayed_work kp_test_work;
+void start_refcount_test(struct work_struct *work)
+{
+	if (!TEST_LIVEPATCH_KPREFCOUNT)
+		return;
+	if (refcount_test()) {
+		pr_alert(KERN_ERR "refcount_test: error.\n");
+		return;
+	}
+	schedule_delayed_work(&kp_test_work, msecs_to_jiffies(50));
+}
+
+static int refcount_test_init(void)
+{
+	INIT_DELAYED_WORK(&kp_test_work, start_refcount_test);
+	schedule_delayed_work(&kp_test_work, msecs_to_jiffies(50));
+	return 0;
+}
+
+static void refcount_test_exit(void)
+{
+	cancel_delayed_work_sync(&kp_test_work);
+}
+
+module_init(refcount_test_init);
+module_exit(refcount_test_exit);
+MODULE_AUTHOR("Roman Rashchupkin <raschupkin.ri@gmail.com>");
+MODULE_DESCRIPTION("Livepatch test: refcount");
+MODULE_LICENSE("GPL");
-- 
2.43.0


  parent reply	other threads:[~2024-07-14 20:00 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-07-14 19:59 raschupkin.ri
2024-07-14 19:59 ` [PATCH 1/2] [PATCH] livepatch: support of modifying refcount_t without underflow after unpatch raschupkin.ri
2024-07-14 22:07   ` Jeff Johnson
2024-07-14 19:59 ` raschupkin.ri [this message]
2024-07-15 20:20 ` Joe Lawrence
2024-07-15 22:45   ` Re: Roman Rashchupkin
2024-07-16  9:28   ` Re: Nicolai Stange
     [not found]   ` <66963d60.170a0220.70a9a.8866SMTPIN_ADDED_BROKEN@mx.google.com>
2024-07-16  9:53     ` Re: Roman Rashchupkin
2024-07-25 14:52       ` Re: Joe Lawrence
2024-07-16 17:33 ` Re: Song Liu

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=20240714195958.692313-3-raschupkin.ri@gmail.com \
    --to=raschupkin.ri@gmail.com \
    --cc=jikos@kernel.org \
    --cc=joe.lawrence@redhat.com \
    --cc=jpoimboe@kernel.org \
    --cc=live-patching@vger.kernel.org \
    --cc=mbenes@suse.cz \
    --cc=pmladek@suse.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox