livepatching changes for 7.1

-----BEGIN PGP SIGNATURE-----
 
 iQJPBAABCAA5FiEESH4wyp42V4tXvYsjUqAMR0iAlPIFAmngn2gbFIAAAAAABAAO
 bWFudTIsMi41KzEuMTIsMiwyAAoJEFKgDEdIgJTy/NsQAKAVn3c9G6RTFaU+cVZ6
 gtcrXd7LR4MW7mgPcK1407tyJN803b92yqk9Ob+Ase2JmqF/M4kNnWk0eLrIYHQ2
 5of4QcoH3p0GoM0CkXsY1IUfSYcBLzb1d+Yjc/sA0PWsYJul/74PPkmflouORi+t
 rwbNXhlUJOFZd32lHvL5CA8wWlk9MundcNconIy2knVbFJodSS7irlakfXQwiQaF
 vyZ9DOt2AtHO8jDuaMhuj7e+Gm44luDarv+YRXASlFUUhb+OBAfb8m+jGQJAvZmc
 ZjKBEt8nFdHH7BbRBm8VizP4dbN7U0lE2gMg5qnqFcyeD6iTmv4A+PstO/rKvg1F
 n7Jwwtu7Nc0J43NF0wdIJrRUR8y9UdTIlKJWXBHYSOOg51oFm7EWjCgkVXoVsZzf
 l244IFz8oboTY/zmcCDOjlhTS/RAubbcjiH5Xg/1c3/weoIPOB2Q55HLgVy2Pul8
 1lBFkrcVEWG4IWHsAXqsGk1mD4h9u4adbFYG7bj+B5ok/bTZMzTtZ4MAg2dUInP0
 H1VTqh72Hw1KcdVwDiMRJKpTpf6r84/ulQWpVBf+1mfLUPdFnhUQHsy334aRKXjY
 cLzp/fGuFc6FL5e28jEDCvaJNpkCpRfgykT8xuEtqCO1gvQZ/nFYgoCm0ENs3Dcz
 VBg+5E0ELVjGm9HcEZ+TUSRi
 =KJTH
 -----END PGP SIGNATURE-----

Merge tag 'livepatching-for-7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/livepatching/livepatching

Pull livepatching updates from Petr Mladek:

 - Add two new selftests

* tag 'livepatching-for-7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/livepatching/livepatching:
  selftests/livepatch: add test for module function patching
  selftests: livepatch: test-ftrace: livepatch a traced function
This commit is contained in:
Linus Torvalds 2026-04-16 08:13:27 -07:00
commit d3d9443f8b
5 changed files with 230 additions and 0 deletions

View File

@ -95,4 +95,40 @@ livepatch: '$MOD_LIVEPATCH': completing unpatching transition
livepatch: '$MOD_LIVEPATCH': unpatching complete
% rmmod $MOD_LIVEPATCH"
# - trace a function
# - verify livepatch can load targgeting on the same traced function
# - check if the livepatch is in effect
# - reset trace and unload livepatch
start_test "livepatch a traced function and check that the live patch remains in effect"
FUNCTION_NAME="cmdline_proc_show"
trace_function "$FUNCTION_NAME"
load_lp $MOD_LIVEPATCH
if [[ "$(cat /proc/cmdline)" == "$MOD_LIVEPATCH: this has been live patched" ]] ; then
log "livepatch: ok"
fi
check_traced_functions "$FUNCTION_NAME"
disable_lp $MOD_LIVEPATCH
unload_lp $MOD_LIVEPATCH
check_result "% insmod test_modules/$MOD_LIVEPATCH.ko
livepatch: enabling patch '$MOD_LIVEPATCH'
livepatch: '$MOD_LIVEPATCH': initializing patching transition
livepatch: '$MOD_LIVEPATCH': starting patching transition
livepatch: '$MOD_LIVEPATCH': completing patching transition
livepatch: '$MOD_LIVEPATCH': patching complete
livepatch: ok
% echo 0 > $SYSFS_KLP_DIR/$MOD_LIVEPATCH/enabled
livepatch: '$MOD_LIVEPATCH': initializing unpatching transition
livepatch: '$MOD_LIVEPATCH': starting unpatching transition
livepatch: '$MOD_LIVEPATCH': completing unpatching transition
livepatch: '$MOD_LIVEPATCH': unpatching complete
% rmmod $MOD_LIVEPATCH"
exit 0

View File

@ -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

View File

@ -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 \

View File

@ -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");

View File

@ -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");