From: Pablo Hugen <phugen@redhat.com>
To: live-patching@vger.kernel.org, linux-kselftest@vger.kernel.org,
linux-kernel@vger.kernel.org
Cc: jpoimboe@kernel.org, jikos@kernel.org, mbenes@suse.cz,
pmladek@suse.com, joe.lawrence@redhat.com, shuah@kernel.org,
Pablo Alessandro Santos Hugen <phugen@redhat.com>
Subject: [PATCH] selftests/livepatch: add test for module function patching
Date: Fri, 20 Mar 2026 17:11:17 -0300 [thread overview]
Message-ID: <20260320201135.1203992-1-phugen@redhat.com> (raw)
From: Pablo Alessandro Santos Hugen <phugen@redhat.com>
Add a target module and livepatch pair that verify module function
patching via a proc entry. Two test cases cover both the
klp_enable_patch path (target loaded before livepatch) and the
klp_module_coming path (livepatch loaded before target).
Signed-off-by: Pablo Alessandro Santos Hugen <phugen@redhat.com>
---
.../selftests/livepatch/test-livepatch.sh | 100 ++++++++++++++++++
.../selftests/livepatch/test_modules/Makefile | 2 +
.../test_modules/test_klp_mod_patch.c | 53 ++++++++++
.../test_modules/test_klp_mod_target.c | 39 +++++++
4 files changed, 194 insertions(+)
create mode 100644 tools/testing/selftests/livepatch/test_modules/test_klp_mod_patch.c
create mode 100644 tools/testing/selftests/livepatch/test_modules/test_klp_mod_target.c
diff --git a/tools/testing/selftests/livepatch/test-livepatch.sh b/tools/testing/selftests/livepatch/test-livepatch.sh
index 6673023d2b66..c44c5341a2f1 100755
--- a/tools/testing/selftests/livepatch/test-livepatch.sh
+++ b/tools/testing/selftests/livepatch/test-livepatch.sh
@@ -8,6 +8,8 @@ MOD_LIVEPATCH1=test_klp_livepatch
MOD_LIVEPATCH2=test_klp_syscall
MOD_LIVEPATCH3=test_klp_callbacks_demo
MOD_REPLACE=test_klp_atomic_replace
+MOD_TARGET=test_klp_mod_target
+MOD_TARGET_PATCH=test_klp_mod_patch
setup_config
@@ -196,4 +198,102 @@ livepatch: '$MOD_REPLACE': unpatching complete
% rmmod $MOD_REPLACE"
+# - load a target module that provides /proc/test_klp_mod_target with
+# original output
+# - load a livepatch that patches the target module's show function
+# - verify the proc entry returns livepatched output
+# - disable and unload the livepatch
+# - verify the proc entry returns original output again
+# - unload the target module
+
+start_test "module function patching"
+
+load_mod $MOD_TARGET
+
+if [[ "$(cat /proc/$MOD_TARGET)" != "$MOD_TARGET: original output" ]] ; then
+ echo -e "FAIL\n\n"
+ die "livepatch kselftest(s) failed"
+fi
+
+load_lp $MOD_TARGET_PATCH
+
+if [[ "$(cat /proc/$MOD_TARGET)" != "$MOD_TARGET_PATCH: this has been live patched" ]] ; then
+ echo -e "FAIL\n\n"
+ die "livepatch kselftest(s) failed"
+fi
+
+disable_lp $MOD_TARGET_PATCH
+unload_lp $MOD_TARGET_PATCH
+
+if [[ "$(cat /proc/$MOD_TARGET)" != "$MOD_TARGET: original output" ]] ; then
+ echo -e "FAIL\n\n"
+ die "livepatch kselftest(s) failed"
+fi
+
+unload_mod $MOD_TARGET
+
+check_result "% insmod test_modules/$MOD_TARGET.ko
+$MOD_TARGET: test_klp_mod_target_init
+% insmod test_modules/$MOD_TARGET_PATCH.ko
+livepatch: enabling patch '$MOD_TARGET_PATCH'
+livepatch: '$MOD_TARGET_PATCH': initializing patching transition
+livepatch: '$MOD_TARGET_PATCH': starting patching transition
+livepatch: '$MOD_TARGET_PATCH': completing patching transition
+livepatch: '$MOD_TARGET_PATCH': patching complete
+% echo 0 > $SYSFS_KLP_DIR/$MOD_TARGET_PATCH/enabled
+livepatch: '$MOD_TARGET_PATCH': initializing unpatching transition
+livepatch: '$MOD_TARGET_PATCH': starting unpatching transition
+livepatch: '$MOD_TARGET_PATCH': completing unpatching transition
+livepatch: '$MOD_TARGET_PATCH': unpatching complete
+% rmmod $MOD_TARGET_PATCH
+% rmmod $MOD_TARGET
+$MOD_TARGET: test_klp_mod_target_exit"
+
+
+# - load a livepatch that targets a not-yet-loaded module
+# - load the target module: klp_module_coming patches it immediately
+# - verify the proc entry returns livepatched output
+# - disable and unload the livepatch
+# - verify the proc entry returns original output again
+# - unload the target module
+
+start_test "module function patching (livepatch first)"
+
+load_lp $MOD_TARGET_PATCH
+load_mod $MOD_TARGET
+
+if [[ "$(cat /proc/$MOD_TARGET)" != "$MOD_TARGET_PATCH: this has been live patched" ]] ; then
+ echo -e "FAIL\n\n"
+ die "livepatch kselftest(s) failed"
+fi
+
+disable_lp $MOD_TARGET_PATCH
+unload_lp $MOD_TARGET_PATCH
+
+if [[ "$(cat /proc/$MOD_TARGET)" != "$MOD_TARGET: original output" ]] ; then
+ echo -e "FAIL\n\n"
+ die "livepatch kselftest(s) failed"
+fi
+
+unload_mod $MOD_TARGET
+
+check_result "% insmod test_modules/$MOD_TARGET_PATCH.ko
+livepatch: enabling patch '$MOD_TARGET_PATCH'
+livepatch: '$MOD_TARGET_PATCH': initializing patching transition
+livepatch: '$MOD_TARGET_PATCH': starting patching transition
+livepatch: '$MOD_TARGET_PATCH': completing patching transition
+livepatch: '$MOD_TARGET_PATCH': patching complete
+% insmod test_modules/$MOD_TARGET.ko
+livepatch: applying patch '$MOD_TARGET_PATCH' to loading module '$MOD_TARGET'
+$MOD_TARGET: test_klp_mod_target_init
+% echo 0 > $SYSFS_KLP_DIR/$MOD_TARGET_PATCH/enabled
+livepatch: '$MOD_TARGET_PATCH': initializing unpatching transition
+livepatch: '$MOD_TARGET_PATCH': starting unpatching transition
+livepatch: '$MOD_TARGET_PATCH': completing unpatching transition
+livepatch: '$MOD_TARGET_PATCH': unpatching complete
+% rmmod $MOD_TARGET_PATCH
+% rmmod $MOD_TARGET
+$MOD_TARGET: test_klp_mod_target_exit"
+
+
exit 0
diff --git a/tools/testing/selftests/livepatch/test_modules/Makefile b/tools/testing/selftests/livepatch/test_modules/Makefile
index 939230e571f5..a13d398585dc 100644
--- a/tools/testing/selftests/livepatch/test_modules/Makefile
+++ b/tools/testing/selftests/livepatch/test_modules/Makefile
@@ -8,6 +8,8 @@ obj-m += test_klp_atomic_replace.o \
test_klp_callbacks_mod.o \
test_klp_kprobe.o \
test_klp_livepatch.o \
+ test_klp_mod_patch.o \
+ test_klp_mod_target.o \
test_klp_shadow_vars.o \
test_klp_state.o \
test_klp_state2.o \
diff --git a/tools/testing/selftests/livepatch/test_modules/test_klp_mod_patch.c b/tools/testing/selftests/livepatch/test_modules/test_klp_mod_patch.c
new file mode 100644
index 000000000000..6725b4720365
--- /dev/null
+++ b/tools/testing/selftests/livepatch/test_modules/test_klp_mod_patch.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2026 Pablo Hugen <phugen@redhat.com>
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/livepatch.h>
+#include <linux/seq_file.h>
+
+static int livepatch_mod_target_show(struct seq_file *m, void *v)
+{
+ seq_printf(m, "%s: %s\n", THIS_MODULE->name,
+ "this has been live patched");
+ return 0;
+}
+
+static struct klp_func funcs[] = {
+ {
+ .old_name = "test_klp_mod_target_show",
+ .new_func = livepatch_mod_target_show,
+ },
+ {},
+};
+
+static struct klp_object objs[] = {
+ {
+ .name = "test_klp_mod_target",
+ .funcs = funcs,
+ },
+ {},
+};
+
+static struct klp_patch patch = {
+ .mod = THIS_MODULE,
+ .objs = objs,
+};
+
+static int test_klp_mod_patch_init(void)
+{
+ return klp_enable_patch(&patch);
+}
+
+static void test_klp_mod_patch_exit(void)
+{
+}
+
+module_init(test_klp_mod_patch_init);
+module_exit(test_klp_mod_patch_exit);
+MODULE_LICENSE("GPL");
+MODULE_INFO(livepatch, "Y");
+MODULE_AUTHOR("Pablo Hugen <phugen@redhat.com>");
+MODULE_DESCRIPTION("Livepatch test: patch for module-provided function");
diff --git a/tools/testing/selftests/livepatch/test_modules/test_klp_mod_target.c b/tools/testing/selftests/livepatch/test_modules/test_klp_mod_target.c
new file mode 100644
index 000000000000..9643984d2402
--- /dev/null
+++ b/tools/testing/selftests/livepatch/test_modules/test_klp_mod_target.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2026 Pablo Hugen <phugen@redhat.com>
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+static struct proc_dir_entry *pde;
+
+static noinline int test_klp_mod_target_show(struct seq_file *m, void *v)
+{
+ seq_printf(m, "%s: %s\n", THIS_MODULE->name, "original output");
+ return 0;
+}
+
+static int test_klp_mod_target_init(void)
+{
+ pr_info("%s\n", __func__);
+ pde = proc_create_single("test_klp_mod_target", 0, NULL,
+ test_klp_mod_target_show);
+ if (!pde)
+ return -ENOMEM;
+ return 0;
+}
+
+static void test_klp_mod_target_exit(void)
+{
+ pr_info("%s\n", __func__);
+ proc_remove(pde);
+}
+
+module_init(test_klp_mod_target_init);
+module_exit(test_klp_mod_target_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Pablo Hugen <phugen@redhat.com>");
+MODULE_DESCRIPTION("Livepatch test: target module with proc entry");
--
2.53.0
next reply other threads:[~2026-03-20 20:14 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-20 20:11 Pablo Hugen [this message]
2026-03-24 14:22 ` [PATCH] selftests/livepatch: add test for module function patching Miroslav Benes
2026-03-24 14:45 ` Joe Lawrence
2026-03-25 8:45 ` Miroslav Benes
2026-03-31 20:52 ` Pablo Hugen
2026-03-26 14:34 ` Petr Mladek
2026-03-26 20:41 ` Joe Lawrence
2026-03-27 10:46 ` Miroslav Benes
2026-03-31 21:10 ` Pablo Hugen
2026-03-30 13:43 ` Petr Mladek
2026-03-30 13:48 ` speaker-test-module: " Petr Mladek
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=20260320201135.1203992-1-phugen@redhat.com \
--to=phugen@redhat.com \
--cc=jikos@kernel.org \
--cc=joe.lawrence@redhat.com \
--cc=jpoimboe@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=live-patching@vger.kernel.org \
--cc=mbenes@suse.cz \
--cc=pmladek@suse.com \
--cc=shuah@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.