Skip to content

Commit 448c0f8

Browse files
committed
Merge branch 'for-7.1/module-function-test' into for-linus
2 parents 920e500 + 57000fe commit 448c0f8

4 files changed

Lines changed: 194 additions & 0 deletions

File tree

tools/testing/selftests/livepatch/test-livepatch.sh

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ MOD_LIVEPATCH1=test_klp_livepatch
88
MOD_LIVEPATCH2=test_klp_syscall
99
MOD_LIVEPATCH3=test_klp_callbacks_demo
1010
MOD_REPLACE=test_klp_atomic_replace
11+
MOD_TARGET=test_klp_mod_target
12+
MOD_TARGET_PATCH=test_klp_mod_patch
1113

1214
setup_config
1315

@@ -196,4 +198,102 @@ livepatch: '$MOD_REPLACE': unpatching complete
196198
% rmmod $MOD_REPLACE"
197199

198200

201+
# - load a target module that provides /proc/test_klp_mod_target with
202+
# original output
203+
# - load a livepatch that patches the target module's show function
204+
# - verify the proc entry returns livepatched output
205+
# - disable and unload the livepatch
206+
# - verify the proc entry returns original output again
207+
# - unload the target module
208+
209+
start_test "module function patching"
210+
211+
load_mod $MOD_TARGET
212+
213+
if [[ "$(cat /proc/$MOD_TARGET)" != "$MOD_TARGET: original output" ]] ; then
214+
echo -e "FAIL\n\n"
215+
die "livepatch kselftest(s) failed"
216+
fi
217+
218+
load_lp $MOD_TARGET_PATCH
219+
220+
if [[ "$(cat /proc/$MOD_TARGET)" != "$MOD_TARGET_PATCH: this has been live patched" ]] ; then
221+
echo -e "FAIL\n\n"
222+
die "livepatch kselftest(s) failed"
223+
fi
224+
225+
disable_lp $MOD_TARGET_PATCH
226+
unload_lp $MOD_TARGET_PATCH
227+
228+
if [[ "$(cat /proc/$MOD_TARGET)" != "$MOD_TARGET: original output" ]] ; then
229+
echo -e "FAIL\n\n"
230+
die "livepatch kselftest(s) failed"
231+
fi
232+
233+
unload_mod $MOD_TARGET
234+
235+
check_result "% insmod test_modules/$MOD_TARGET.ko
236+
$MOD_TARGET: test_klp_mod_target_init
237+
% insmod test_modules/$MOD_TARGET_PATCH.ko
238+
livepatch: enabling patch '$MOD_TARGET_PATCH'
239+
livepatch: '$MOD_TARGET_PATCH': initializing patching transition
240+
livepatch: '$MOD_TARGET_PATCH': starting patching transition
241+
livepatch: '$MOD_TARGET_PATCH': completing patching transition
242+
livepatch: '$MOD_TARGET_PATCH': patching complete
243+
% echo 0 > $SYSFS_KLP_DIR/$MOD_TARGET_PATCH/enabled
244+
livepatch: '$MOD_TARGET_PATCH': initializing unpatching transition
245+
livepatch: '$MOD_TARGET_PATCH': starting unpatching transition
246+
livepatch: '$MOD_TARGET_PATCH': completing unpatching transition
247+
livepatch: '$MOD_TARGET_PATCH': unpatching complete
248+
% rmmod $MOD_TARGET_PATCH
249+
% rmmod $MOD_TARGET
250+
$MOD_TARGET: test_klp_mod_target_exit"
251+
252+
253+
# - load a livepatch that targets a not-yet-loaded module
254+
# - load the target module: klp_module_coming patches it immediately
255+
# - verify the proc entry returns livepatched output
256+
# - disable and unload the livepatch
257+
# - verify the proc entry returns original output again
258+
# - unload the target module
259+
260+
start_test "module function patching (livepatch first)"
261+
262+
load_lp $MOD_TARGET_PATCH
263+
load_mod $MOD_TARGET
264+
265+
if [[ "$(cat /proc/$MOD_TARGET)" != "$MOD_TARGET_PATCH: this has been live patched" ]] ; then
266+
echo -e "FAIL\n\n"
267+
die "livepatch kselftest(s) failed"
268+
fi
269+
270+
disable_lp $MOD_TARGET_PATCH
271+
unload_lp $MOD_TARGET_PATCH
272+
273+
if [[ "$(cat /proc/$MOD_TARGET)" != "$MOD_TARGET: original output" ]] ; then
274+
echo -e "FAIL\n\n"
275+
die "livepatch kselftest(s) failed"
276+
fi
277+
278+
unload_mod $MOD_TARGET
279+
280+
check_result "% insmod test_modules/$MOD_TARGET_PATCH.ko
281+
livepatch: enabling patch '$MOD_TARGET_PATCH'
282+
livepatch: '$MOD_TARGET_PATCH': initializing patching transition
283+
livepatch: '$MOD_TARGET_PATCH': starting patching transition
284+
livepatch: '$MOD_TARGET_PATCH': completing patching transition
285+
livepatch: '$MOD_TARGET_PATCH': patching complete
286+
% insmod test_modules/$MOD_TARGET.ko
287+
livepatch: applying patch '$MOD_TARGET_PATCH' to loading module '$MOD_TARGET'
288+
$MOD_TARGET: test_klp_mod_target_init
289+
% echo 0 > $SYSFS_KLP_DIR/$MOD_TARGET_PATCH/enabled
290+
livepatch: '$MOD_TARGET_PATCH': initializing unpatching transition
291+
livepatch: '$MOD_TARGET_PATCH': starting unpatching transition
292+
livepatch: '$MOD_TARGET_PATCH': completing unpatching transition
293+
livepatch: '$MOD_TARGET_PATCH': unpatching complete
294+
% rmmod $MOD_TARGET_PATCH
295+
% rmmod $MOD_TARGET
296+
$MOD_TARGET: test_klp_mod_target_exit"
297+
298+
199299
exit 0

tools/testing/selftests/livepatch/test_modules/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ obj-m += test_klp_atomic_replace.o \
88
test_klp_callbacks_mod.o \
99
test_klp_kprobe.o \
1010
test_klp_livepatch.o \
11+
test_klp_mod_patch.o \
12+
test_klp_mod_target.o \
1113
test_klp_shadow_vars.o \
1214
test_klp_state.o \
1315
test_klp_state2.o \
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// Copyright (C) 2026 Pablo Hugen <phugen@redhat.com>
3+
4+
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
5+
6+
#include <linux/module.h>
7+
#include <linux/kernel.h>
8+
#include <linux/livepatch.h>
9+
#include <linux/seq_file.h>
10+
11+
static int livepatch_mod_target_show(struct seq_file *m, void *v)
12+
{
13+
seq_printf(m, "%s: %s\n", THIS_MODULE->name,
14+
"this has been live patched");
15+
return 0;
16+
}
17+
18+
static struct klp_func funcs[] = {
19+
{
20+
.old_name = "test_klp_mod_target_show",
21+
.new_func = livepatch_mod_target_show,
22+
},
23+
{},
24+
};
25+
26+
static struct klp_object objs[] = {
27+
{
28+
.name = "test_klp_mod_target",
29+
.funcs = funcs,
30+
},
31+
{},
32+
};
33+
34+
static struct klp_patch patch = {
35+
.mod = THIS_MODULE,
36+
.objs = objs,
37+
};
38+
39+
static int test_klp_mod_patch_init(void)
40+
{
41+
return klp_enable_patch(&patch);
42+
}
43+
44+
static void test_klp_mod_patch_exit(void)
45+
{
46+
}
47+
48+
module_init(test_klp_mod_patch_init);
49+
module_exit(test_klp_mod_patch_exit);
50+
MODULE_LICENSE("GPL");
51+
MODULE_INFO(livepatch, "Y");
52+
MODULE_AUTHOR("Pablo Hugen <phugen@redhat.com>");
53+
MODULE_DESCRIPTION("Livepatch test: patch for module-provided function");
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// Copyright (C) 2026 Pablo Hugen <phugen@redhat.com>
3+
4+
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
5+
6+
#include <linux/module.h>
7+
#include <linux/kernel.h>
8+
#include <linux/proc_fs.h>
9+
#include <linux/seq_file.h>
10+
11+
static struct proc_dir_entry *pde;
12+
13+
static noinline int test_klp_mod_target_show(struct seq_file *m, void *v)
14+
{
15+
seq_printf(m, "%s: %s\n", THIS_MODULE->name, "original output");
16+
return 0;
17+
}
18+
19+
static int test_klp_mod_target_init(void)
20+
{
21+
pr_info("%s\n", __func__);
22+
pde = proc_create_single("test_klp_mod_target", 0, NULL,
23+
test_klp_mod_target_show);
24+
if (!pde)
25+
return -ENOMEM;
26+
return 0;
27+
}
28+
29+
static void test_klp_mod_target_exit(void)
30+
{
31+
pr_info("%s\n", __func__);
32+
proc_remove(pde);
33+
}
34+
35+
module_init(test_klp_mod_target_init);
36+
module_exit(test_klp_mod_target_exit);
37+
MODULE_LICENSE("GPL");
38+
MODULE_AUTHOR("Pablo Hugen <phugen@redhat.com>");
39+
MODULE_DESCRIPTION("Livepatch test: target module with proc entry");

0 commit comments

Comments
 (0)