Hi there,
The first patch moves the current livepatch tests to selftests, allowing it be better suited to contain more complex tests, like using userspace C code to use the livepatched kernel code. As a bonus it allows to use "gen_tar" to export the livepatch selftests, rebuild the modules by running make in selftests/livepatch directory and simplifies the process of creating and debugging new selftests.
It keeps the ability to execute the tests by running the shell scripts, like "test-livepatch.sh", but beware that the kernel modules might not be up-to-date.
The second patch includes a new test to exercise the functionality to livepatch a heavy hammered function. The test uses getpid in this case.
I tested the changes by running the tests within the kernel source tree and running from the gen_tar extracted directory.
Marcos Paulo de Souza (2): livepatch: Move tests from lib/livepatch to selftests/livepatch selftests: livepatch: Test livepatching a heavily called syscall
arch/s390/configs/debug_defconfig | 1 - arch/s390/configs/defconfig | 1 - lib/Kconfig.debug | 22 ------- lib/Makefile | 2 - lib/livepatch/Makefile | 14 ----- tools/testing/selftests/livepatch/Makefile | 35 ++++++++++- tools/testing/selftests/livepatch/README | 5 +- tools/testing/selftests/livepatch/config | 1 - .../testing/selftests/livepatch/functions.sh | 34 ++++------- .../selftests/livepatch/test-callbacks.sh | 50 ++++++++-------- .../selftests/livepatch/test-ftrace.sh | 6 +- .../selftests/livepatch/test-livepatch.sh | 10 ++-- .../selftests/livepatch/test-shadow-vars.sh | 2 +- .../testing/selftests/livepatch/test-state.sh | 18 +++--- .../selftests/livepatch/test-syscall.sh | 46 ++++++++++++++ .../test_binaries/test_klp-call_getpid.c | 48 +++++++++++++++ .../selftests/livepatch/test_modules/Makefile | 25 ++++++++ .../test_modules}/test_klp_atomic_replace.c | 0 .../test_modules}/test_klp_callbacks_busy.c | 0 .../test_modules}/test_klp_callbacks_demo.c | 0 .../test_modules}/test_klp_callbacks_demo2.c | 0 .../test_modules}/test_klp_callbacks_mod.c | 0 .../test_modules}/test_klp_livepatch.c | 0 .../test_modules}/test_klp_shadow_vars.c | 0 .../livepatch/test_modules}/test_klp_state.c | 0 .../livepatch/test_modules}/test_klp_state2.c | 0 .../livepatch/test_modules}/test_klp_state3.c | 0 .../livepatch/test_modules/test_klp_syscall.c | 60 +++++++++++++++++++ 28 files changed, 269 insertions(+), 111 deletions(-) delete mode 100644 lib/livepatch/Makefile create mode 100755 tools/testing/selftests/livepatch/test-syscall.sh create mode 100644 tools/testing/selftests/livepatch/test_binaries/test_klp-call_getpid.c create mode 100644 tools/testing/selftests/livepatch/test_modules/Makefile rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_atomic_replace.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_callbacks_busy.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_callbacks_demo.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_callbacks_demo2.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_callbacks_mod.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_livepatch.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_shadow_vars.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_state.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_state2.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_state3.c (100%) create mode 100644 tools/testing/selftests/livepatch/test_modules/test_klp_syscall.c
It allows writing more complex tests, for example, an userspace C code that would use the livepatched kernel code. As a bonus it allows to use "gen_tar" to export the livepatch selftests, rebuild the modules by running make in selftests/livepatch directory and simplifies the process of creating and debugging new selftests.
It keeps the ability to execute the tests by running the shell scripts, like "test-livepatch.sh", but beware that the kernel modules might not be up-to-date.
Remove 'modprobe --dry-run' call as the modules will be built before running the tests. Also remove the TEST_LIVEPATCH Kconfig since the modules won't be build based on a Kconfig.
Adjust functions.sh to call insmod and fix the check_result strings to reflect the change.
Signed-off-by: Marcos Paulo de Souza mpdesouza@suse.com --- arch/s390/configs/debug_defconfig | 1 - arch/s390/configs/defconfig | 1 - lib/Kconfig.debug | 22 -------- lib/Makefile | 2 - lib/livepatch/Makefile | 14 ------ tools/testing/selftests/livepatch/Makefile | 27 +++++++++- tools/testing/selftests/livepatch/README | 5 +- tools/testing/selftests/livepatch/config | 1 - .../testing/selftests/livepatch/functions.sh | 34 +++++-------- .../selftests/livepatch/test-callbacks.sh | 50 +++++++++---------- .../selftests/livepatch/test-ftrace.sh | 6 +-- .../selftests/livepatch/test-livepatch.sh | 10 ++-- .../selftests/livepatch/test-shadow-vars.sh | 2 +- .../testing/selftests/livepatch/test-state.sh | 18 +++---- .../selftests/livepatch/test_modules/Makefile | 24 +++++++++ .../test_modules}/test_klp_atomic_replace.c | 0 .../test_modules}/test_klp_callbacks_busy.c | 0 .../test_modules}/test_klp_callbacks_demo.c | 0 .../test_modules}/test_klp_callbacks_demo2.c | 0 .../test_modules}/test_klp_callbacks_mod.c | 0 .../test_modules}/test_klp_livepatch.c | 0 .../test_modules}/test_klp_shadow_vars.c | 0 .../livepatch/test_modules}/test_klp_state.c | 0 .../livepatch/test_modules}/test_klp_state2.c | 0 .../livepatch/test_modules}/test_klp_state3.c | 0 25 files changed, 107 insertions(+), 110 deletions(-) delete mode 100644 lib/livepatch/Makefile create mode 100644 tools/testing/selftests/livepatch/test_modules/Makefile rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_atomic_replace.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_callbacks_busy.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_callbacks_demo.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_callbacks_demo2.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_callbacks_mod.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_livepatch.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_shadow_vars.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_state.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_state2.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_state3.c (100%)
diff --git a/arch/s390/configs/debug_defconfig b/arch/s390/configs/debug_defconfig index 498bed9b261b..c97e1b5399b2 100644 --- a/arch/s390/configs/debug_defconfig +++ b/arch/s390/configs/debug_defconfig @@ -876,4 +876,3 @@ CONFIG_ATOMIC64_SELFTEST=y CONFIG_STRING_SELFTEST=y CONFIG_TEST_BITOPS=m CONFIG_TEST_BPF=m -CONFIG_TEST_LIVEPATCH=m diff --git a/arch/s390/configs/defconfig b/arch/s390/configs/defconfig index 61e36b999f67..57d653714f55 100644 --- a/arch/s390/configs/defconfig +++ b/arch/s390/configs/defconfig @@ -807,4 +807,3 @@ CONFIG_KPROBES_SANITY_TEST=m CONFIG_PERCPU_TEST=m CONFIG_ATOMIC64_SELFTEST=y CONFIG_TEST_BPF=m -CONFIG_TEST_LIVEPATCH=m diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 14b89aa37c5c..9f7ec929e1f2 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2562,28 +2562,6 @@ config TEST_MEMCAT_P
If unsure, say N.
-config TEST_LIVEPATCH - tristate "Test livepatching" - default n - depends on DYNAMIC_DEBUG - depends on LIVEPATCH - depends on m - help - Test kernel livepatching features for correctness. The tests will - load test modules that will be livepatched in various scenarios. - - To run all the livepatching tests: - - make -C tools/testing/selftests TARGETS=livepatch run_tests - - Alternatively, individual tests may be invoked: - - tools/testing/selftests/livepatch/test-callbacks.sh - tools/testing/selftests/livepatch/test-livepatch.sh - tools/testing/selftests/livepatch/test-shadow-vars.sh - - If unsure, say N. - config TEST_OBJAGG tristate "Perform selftest on object aggreration manager" default n diff --git a/lib/Makefile b/lib/Makefile index 300f569c626b..d7322e07c6b5 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -128,8 +128,6 @@ endif obj-$(CONFIG_TEST_FPU) += test_fpu.o CFLAGS_test_fpu.o += $(FPU_CFLAGS)
-obj-$(CONFIG_TEST_LIVEPATCH) += livepatch/ - obj-$(CONFIG_KUNIT) += kunit/
ifeq ($(CONFIG_DEBUG_KOBJECT),y) diff --git a/lib/livepatch/Makefile b/lib/livepatch/Makefile deleted file mode 100644 index dcc912b3478f..000000000000 --- a/lib/livepatch/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Makefile for livepatch test code. - -obj-$(CONFIG_TEST_LIVEPATCH) += test_klp_atomic_replace.o \ - test_klp_callbacks_demo.o \ - test_klp_callbacks_demo2.o \ - test_klp_callbacks_busy.o \ - test_klp_callbacks_mod.o \ - test_klp_livepatch.o \ - test_klp_shadow_vars.o \ - test_klp_state.o \ - test_klp_state2.o \ - test_klp_state3.o diff --git a/tools/testing/selftests/livepatch/Makefile b/tools/testing/selftests/livepatch/Makefile index 1acc9e1fa3fb..5ef492b87bb1 100644 --- a/tools/testing/selftests/livepatch/Makefile +++ b/tools/testing/selftests/livepatch/Makefile @@ -1,5 +1,20 @@ # SPDX-License-Identifier: GPL-2.0
+TEST_FILES := settings \ + test_modules + +# We need the test_modules dir in order to make gen_tar and install to work +TEST_GEN_PROGS_EXTENDED := test_modules/test_klp_atomic_replace.ko \ + test_modules/test_klp_callbacks_busy.ko \ + test_modules/test_klp_callbacks_demo.ko \ + test_modules/test_klp_callbacks_demo2.ko \ + test_modules/test_klp_callbacks_mod.ko \ + test_modules/test_klp_livepatch.ko \ + test_modules/test_klp_state.ko \ + test_modules/test_klp_state2.ko \ + test_modules/test_klp_state3.ko \ + test_modules/test_klp_shadow_vars.ko + TEST_PROGS_EXTENDED := functions.sh TEST_PROGS := \ test-livepatch.sh \ @@ -8,6 +23,16 @@ TEST_PROGS := \ test-state.sh \ test-ftrace.sh
-TEST_FILES := settings +# override lib.mk's default rules +OVERRIDE_TARGETS := 1 +override define CLEAN + rm -f $(TEST_GEN_PROGS_EXTENDED) + make -C test_modules clean +endef
include ../lib.mk + +# Here we remove the test_modules path from the module.ko to match the Makefile +# rule in test_modules directory +%.ko: + make -C test_modules $(notdir $@) diff --git a/tools/testing/selftests/livepatch/README b/tools/testing/selftests/livepatch/README index 0942dd5826f8..33d0b016d8a0 100644 --- a/tools/testing/selftests/livepatch/README +++ b/tools/testing/selftests/livepatch/README @@ -13,10 +13,7 @@ the message buffer for only the duration of each individual test.) Config ------
-Set these config options and their prerequisites: - -CONFIG_LIVEPATCH=y -CONFIG_TEST_LIVEPATCH=m +Set CONFIG_LIVEPATCH=y option and it's prerequisite.
Running the tests diff --git a/tools/testing/selftests/livepatch/config b/tools/testing/selftests/livepatch/config index ad23100cb27c..e88bf518a23a 100644 --- a/tools/testing/selftests/livepatch/config +++ b/tools/testing/selftests/livepatch/config @@ -1,3 +1,2 @@ CONFIG_LIVEPATCH=y CONFIG_DYNAMIC_DEBUG=y -CONFIG_TEST_LIVEPATCH=m diff --git a/tools/testing/selftests/livepatch/functions.sh b/tools/testing/selftests/livepatch/functions.sh index 846c7ed71556..130e0f7a245b 100644 --- a/tools/testing/selftests/livepatch/functions.sh +++ b/tools/testing/selftests/livepatch/functions.sh @@ -110,16 +110,14 @@ function loop_until() { done }
-function assert_mod() { - local mod="$1" - - modprobe --dry-run "$mod" &>/dev/null -} - function is_livepatch_mod() { local mod="$1"
- if [[ $(modinfo "$mod" | awk '/^livepatch:/{print $NF}') == "Y" ]]; then + if [[ ! -f "test_modules/$mod.ko" ]]; then + die "Can't find "test_modules/$mod.ko", try "make"" + fi + + if [[ $(modinfo "test_modules/$mod.ko" | awk '/^livepatch:/{print $NF}') == "Y" ]]; then return 0 fi
@@ -129,9 +127,9 @@ function is_livepatch_mod() { function __load_mod() { local mod="$1"; shift
- local msg="% modprobe $mod $*" + local msg="% insmod test_modules/$mod.ko $*" log "${msg%% }" - ret=$(modprobe "$mod" "$@" 2>&1) + ret=$(insmod "test_modules/$mod.ko" "$@" 2>&1) if [[ "$ret" != "" ]]; then die "$ret" fi @@ -144,13 +142,10 @@ function __load_mod() {
# load_mod(modname, params) - load a kernel module # modname - module name to load -# params - module parameters to pass to modprobe +# params - module parameters to pass to insmod function load_mod() { local mod="$1"; shift
- assert_mod "$mod" || - skip "unable to load module ${mod}, verify CONFIG_TEST_LIVEPATCH=m and run self-tests as root" - is_livepatch_mod "$mod" && die "use load_lp() to load the livepatch module $mod"
@@ -160,13 +155,10 @@ function load_mod() { # load_lp_nowait(modname, params) - load a kernel module with a livepatch # but do not wait on until the transition finishes # modname - module name to load -# params - module parameters to pass to modprobe +# params - module parameters to pass to insmod function load_lp_nowait() { local mod="$1"; shift
- assert_mod "$mod" || - skip "unable to load module ${mod}, verify CONFIG_TEST_LIVEPATCH=m and run self-tests as root" - is_livepatch_mod "$mod" || die "module $mod is not a livepatch"
@@ -179,7 +171,7 @@ function load_lp_nowait() {
# load_lp(modname, params) - load a kernel module with a livepatch # modname - module name to load -# params - module parameters to pass to modprobe +# params - module parameters to pass to insmod function load_lp() { local mod="$1"; shift
@@ -192,13 +184,13 @@ function load_lp() {
# load_failing_mod(modname, params) - load a kernel module, expect to fail # modname - module name to load -# params - module parameters to pass to modprobe +# params - module parameters to pass to insmod function load_failing_mod() { local mod="$1"; shift
- local msg="% modprobe $mod $*" + local msg="% insmod test_modules/$mod.ko $*" log "${msg%% }" - ret=$(modprobe "$mod" "$@" 2>&1) + ret=$(insmod "test_modules/$mod.ko" "$@" 2>&1) if [[ "$ret" == "" ]]; then die "$mod unexpectedly loaded" fi diff --git a/tools/testing/selftests/livepatch/test-callbacks.sh b/tools/testing/selftests/livepatch/test-callbacks.sh index 90b26dbb2626..32b150e25b10 100755 --- a/tools/testing/selftests/livepatch/test-callbacks.sh +++ b/tools/testing/selftests/livepatch/test-callbacks.sh @@ -34,9 +34,9 @@ disable_lp $MOD_LIVEPATCH unload_lp $MOD_LIVEPATCH unload_mod $MOD_TARGET
-check_result "% modprobe $MOD_TARGET +check_result "% insmod test_modules/$MOD_TARGET.ko $MOD_TARGET: ${MOD_TARGET}_init -% modprobe $MOD_LIVEPATCH +% insmod test_modules/$MOD_LIVEPATCH.ko livepatch: enabling patch '$MOD_LIVEPATCH' livepatch: '$MOD_LIVEPATCH': initializing patching transition $MOD_LIVEPATCH: pre_patch_callback: vmlinux @@ -81,7 +81,7 @@ disable_lp $MOD_LIVEPATCH unload_lp $MOD_LIVEPATCH unload_mod $MOD_TARGET
-check_result "% modprobe $MOD_LIVEPATCH +check_result "% insmod test_modules/$MOD_LIVEPATCH.ko livepatch: enabling patch '$MOD_LIVEPATCH' livepatch: '$MOD_LIVEPATCH': initializing patching transition $MOD_LIVEPATCH: pre_patch_callback: vmlinux @@ -89,7 +89,7 @@ livepatch: '$MOD_LIVEPATCH': starting patching transition livepatch: '$MOD_LIVEPATCH': completing patching transition $MOD_LIVEPATCH: post_patch_callback: vmlinux livepatch: '$MOD_LIVEPATCH': patching complete -% modprobe $MOD_TARGET +% insmod test_modules/$MOD_TARGET.ko livepatch: applying patch '$MOD_LIVEPATCH' to loading module '$MOD_TARGET' $MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init $MOD_LIVEPATCH: post_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init @@ -129,9 +129,9 @@ unload_mod $MOD_TARGET disable_lp $MOD_LIVEPATCH unload_lp $MOD_LIVEPATCH
-check_result "% modprobe $MOD_TARGET +check_result "% insmod test_modules/$MOD_TARGET.ko $MOD_TARGET: ${MOD_TARGET}_init -% modprobe $MOD_LIVEPATCH +% insmod test_modules/$MOD_LIVEPATCH.ko livepatch: enabling patch '$MOD_LIVEPATCH' livepatch: '$MOD_LIVEPATCH': initializing patching transition $MOD_LIVEPATCH: pre_patch_callback: vmlinux @@ -177,7 +177,7 @@ unload_mod $MOD_TARGET disable_lp $MOD_LIVEPATCH unload_lp $MOD_LIVEPATCH
-check_result "% modprobe $MOD_LIVEPATCH +check_result "% insmod test_modules/$MOD_LIVEPATCH.ko livepatch: enabling patch '$MOD_LIVEPATCH' livepatch: '$MOD_LIVEPATCH': initializing patching transition $MOD_LIVEPATCH: pre_patch_callback: vmlinux @@ -185,7 +185,7 @@ livepatch: '$MOD_LIVEPATCH': starting patching transition livepatch: '$MOD_LIVEPATCH': completing patching transition $MOD_LIVEPATCH: post_patch_callback: vmlinux livepatch: '$MOD_LIVEPATCH': patching complete -% modprobe $MOD_TARGET +% insmod test_modules/$MOD_TARGET.ko livepatch: applying patch '$MOD_LIVEPATCH' to loading module '$MOD_TARGET' $MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init $MOD_LIVEPATCH: post_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init @@ -219,7 +219,7 @@ load_lp $MOD_LIVEPATCH disable_lp $MOD_LIVEPATCH unload_lp $MOD_LIVEPATCH
-check_result "% modprobe $MOD_LIVEPATCH +check_result "% insmod test_modules/$MOD_LIVEPATCH.ko livepatch: enabling patch '$MOD_LIVEPATCH' livepatch: '$MOD_LIVEPATCH': initializing patching transition $MOD_LIVEPATCH: pre_patch_callback: vmlinux @@ -254,9 +254,9 @@ load_mod $MOD_TARGET load_failing_mod $MOD_LIVEPATCH pre_patch_ret=-19 unload_mod $MOD_TARGET
-check_result "% modprobe $MOD_TARGET +check_result "% insmod test_modules/$MOD_TARGET.ko $MOD_TARGET: ${MOD_TARGET}_init -% modprobe $MOD_LIVEPATCH pre_patch_ret=-19 +% insmod test_modules/$MOD_LIVEPATCH.ko pre_patch_ret=-19 livepatch: enabling patch '$MOD_LIVEPATCH' livepatch: '$MOD_LIVEPATCH': initializing patching transition test_klp_callbacks_demo: pre_patch_callback: vmlinux @@ -265,7 +265,7 @@ livepatch: failed to enable patch '$MOD_LIVEPATCH' livepatch: '$MOD_LIVEPATCH': canceling patching transition, going to unpatch livepatch: '$MOD_LIVEPATCH': completing unpatching transition livepatch: '$MOD_LIVEPATCH': unpatching complete -modprobe: ERROR: could not insert '$MOD_LIVEPATCH': No such device +insmod: ERROR: could not insert module test_modules/$MOD_LIVEPATCH.ko: No such device % rmmod $MOD_TARGET $MOD_TARGET: ${MOD_TARGET}_exit"
@@ -295,7 +295,7 @@ load_failing_mod $MOD_TARGET disable_lp $MOD_LIVEPATCH unload_lp $MOD_LIVEPATCH
-check_result "% modprobe $MOD_LIVEPATCH +check_result "% insmod test_modules/$MOD_LIVEPATCH.ko livepatch: enabling patch '$MOD_LIVEPATCH' livepatch: '$MOD_LIVEPATCH': initializing patching transition $MOD_LIVEPATCH: pre_patch_callback: vmlinux @@ -304,12 +304,12 @@ livepatch: '$MOD_LIVEPATCH': completing patching transition $MOD_LIVEPATCH: post_patch_callback: vmlinux livepatch: '$MOD_LIVEPATCH': patching complete % echo -19 > /sys/module/$MOD_LIVEPATCH/parameters/pre_patch_ret -% modprobe $MOD_TARGET +% insmod test_modules/$MOD_TARGET.ko livepatch: applying patch '$MOD_LIVEPATCH' to loading module '$MOD_TARGET' $MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init livepatch: pre-patch callback failed for object '$MOD_TARGET' livepatch: patch '$MOD_LIVEPATCH' failed for module '$MOD_TARGET', refusing to load module '$MOD_TARGET' -modprobe: ERROR: could not insert '$MOD_TARGET': No such device +insmod: ERROR: could not insert module test_modules/$MOD_TARGET.ko: No such device % echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled livepatch: '$MOD_LIVEPATCH': initializing unpatching transition $MOD_LIVEPATCH: pre_unpatch_callback: vmlinux @@ -340,11 +340,11 @@ disable_lp $MOD_LIVEPATCH unload_lp $MOD_LIVEPATCH unload_mod $MOD_TARGET_BUSY
-check_result "% modprobe $MOD_TARGET_BUSY block_transition=N +check_result "% insmod test_modules/$MOD_TARGET_BUSY.ko block_transition=N $MOD_TARGET_BUSY: ${MOD_TARGET_BUSY}_init $MOD_TARGET_BUSY: busymod_work_func enter $MOD_TARGET_BUSY: busymod_work_func exit -% modprobe $MOD_LIVEPATCH +% insmod test_modules/$MOD_LIVEPATCH.ko livepatch: enabling patch '$MOD_LIVEPATCH' livepatch: '$MOD_LIVEPATCH': initializing patching transition $MOD_LIVEPATCH: pre_patch_callback: vmlinux @@ -354,7 +354,7 @@ livepatch: '$MOD_LIVEPATCH': completing patching transition $MOD_LIVEPATCH: post_patch_callback: vmlinux $MOD_LIVEPATCH: post_patch_callback: $MOD_TARGET_BUSY -> [MODULE_STATE_LIVE] Normal state livepatch: '$MOD_LIVEPATCH': patching complete -% modprobe $MOD_TARGET +% insmod test_modules/$MOD_TARGET.ko livepatch: applying patch '$MOD_LIVEPATCH' to loading module '$MOD_TARGET' $MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init $MOD_LIVEPATCH: post_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init @@ -421,16 +421,16 @@ disable_lp $MOD_LIVEPATCH unload_lp $MOD_LIVEPATCH unload_mod $MOD_TARGET_BUSY
-check_result "% modprobe $MOD_TARGET_BUSY block_transition=Y +check_result "% insmod test_modules/$MOD_TARGET_BUSY.ko block_transition=Y $MOD_TARGET_BUSY: ${MOD_TARGET_BUSY}_init $MOD_TARGET_BUSY: busymod_work_func enter -% modprobe $MOD_LIVEPATCH +% insmod test_modules/$MOD_LIVEPATCH.ko livepatch: enabling patch '$MOD_LIVEPATCH' livepatch: '$MOD_LIVEPATCH': initializing patching transition $MOD_LIVEPATCH: pre_patch_callback: vmlinux $MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET_BUSY -> [MODULE_STATE_LIVE] Normal state livepatch: '$MOD_LIVEPATCH': starting patching transition -% modprobe $MOD_TARGET +% insmod test_modules/$MOD_TARGET.ko livepatch: applying patch '$MOD_LIVEPATCH' to loading module '$MOD_TARGET' $MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init $MOD_TARGET: ${MOD_TARGET}_init @@ -467,7 +467,7 @@ disable_lp $MOD_LIVEPATCH unload_lp $MOD_LIVEPATCH2 unload_lp $MOD_LIVEPATCH
-check_result "% modprobe $MOD_LIVEPATCH +check_result "% insmod test_modules/$MOD_LIVEPATCH.ko livepatch: enabling patch '$MOD_LIVEPATCH' livepatch: '$MOD_LIVEPATCH': initializing patching transition $MOD_LIVEPATCH: pre_patch_callback: vmlinux @@ -475,7 +475,7 @@ livepatch: '$MOD_LIVEPATCH': starting patching transition livepatch: '$MOD_LIVEPATCH': completing patching transition $MOD_LIVEPATCH: post_patch_callback: vmlinux livepatch: '$MOD_LIVEPATCH': patching complete -% modprobe $MOD_LIVEPATCH2 +% insmod test_modules/$MOD_LIVEPATCH2.ko livepatch: enabling patch '$MOD_LIVEPATCH2' livepatch: '$MOD_LIVEPATCH2': initializing patching transition $MOD_LIVEPATCH2: pre_patch_callback: vmlinux @@ -523,7 +523,7 @@ disable_lp $MOD_LIVEPATCH2 unload_lp $MOD_LIVEPATCH2 unload_lp $MOD_LIVEPATCH
-check_result "% modprobe $MOD_LIVEPATCH +check_result "% insmod test_modules/$MOD_LIVEPATCH.ko livepatch: enabling patch '$MOD_LIVEPATCH' livepatch: '$MOD_LIVEPATCH': initializing patching transition $MOD_LIVEPATCH: pre_patch_callback: vmlinux @@ -531,7 +531,7 @@ livepatch: '$MOD_LIVEPATCH': starting patching transition livepatch: '$MOD_LIVEPATCH': completing patching transition $MOD_LIVEPATCH: post_patch_callback: vmlinux livepatch: '$MOD_LIVEPATCH': patching complete -% modprobe $MOD_LIVEPATCH2 replace=1 +% insmod test_modules/$MOD_LIVEPATCH2.ko replace=1 livepatch: enabling patch '$MOD_LIVEPATCH2' livepatch: '$MOD_LIVEPATCH2': initializing patching transition $MOD_LIVEPATCH2: pre_patch_callback: vmlinux diff --git a/tools/testing/selftests/livepatch/test-ftrace.sh b/tools/testing/selftests/livepatch/test-ftrace.sh index 552e165512f4..08ab42c64013 100755 --- a/tools/testing/selftests/livepatch/test-ftrace.sh +++ b/tools/testing/selftests/livepatch/test-ftrace.sh @@ -34,7 +34,7 @@ disable_lp $MOD_LIVEPATCH unload_lp $MOD_LIVEPATCH
check_result "livepatch: kernel.ftrace_enabled = 0 -% modprobe $MOD_LIVEPATCH +% insmod test_modules/$MOD_LIVEPATCH.ko livepatch: enabling patch '$MOD_LIVEPATCH' livepatch: '$MOD_LIVEPATCH': initializing patching transition livepatch: failed to register ftrace handler for function 'cmdline_proc_show' (-16) @@ -43,9 +43,9 @@ livepatch: failed to enable patch '$MOD_LIVEPATCH' livepatch: '$MOD_LIVEPATCH': canceling patching transition, going to unpatch livepatch: '$MOD_LIVEPATCH': completing unpatching transition livepatch: '$MOD_LIVEPATCH': unpatching complete -modprobe: ERROR: could not insert '$MOD_LIVEPATCH': Device or resource busy +insmod: ERROR: could not insert module test_modules/$MOD_LIVEPATCH.ko: Device or resource busy livepatch: kernel.ftrace_enabled = 1 -% modprobe $MOD_LIVEPATCH +% insmod test_modules/$MOD_LIVEPATCH.ko livepatch: enabling patch '$MOD_LIVEPATCH' livepatch: '$MOD_LIVEPATCH': initializing patching transition livepatch: '$MOD_LIVEPATCH': starting patching transition diff --git a/tools/testing/selftests/livepatch/test-livepatch.sh b/tools/testing/selftests/livepatch/test-livepatch.sh index 5fe79ac34be1..e3455a6b1158 100755 --- a/tools/testing/selftests/livepatch/test-livepatch.sh +++ b/tools/testing/selftests/livepatch/test-livepatch.sh @@ -31,7 +31,7 @@ if [[ "$(cat /proc/cmdline)" == "$MOD_LIVEPATCH: this has been live patched" ]] die "livepatch kselftest(s) failed" fi
-check_result "% modprobe $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 @@ -75,14 +75,14 @@ unload_lp $MOD_LIVEPATCH grep 'live patched' /proc/cmdline > /dev/kmsg grep 'live patched' /proc/meminfo > /dev/kmsg
-check_result "% modprobe $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 $MOD_LIVEPATCH: this has been live patched -% modprobe $MOD_REPLACE replace=0 +% insmod test_modules/$MOD_REPLACE.ko replace=0 livepatch: enabling patch '$MOD_REPLACE' livepatch: '$MOD_REPLACE': initializing patching transition livepatch: '$MOD_REPLACE': starting patching transition @@ -135,14 +135,14 @@ unload_lp $MOD_REPLACE grep 'live patched' /proc/cmdline > /dev/kmsg grep 'live patched' /proc/meminfo > /dev/kmsg
-check_result "% modprobe $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 $MOD_LIVEPATCH: this has been live patched -% modprobe $MOD_REPLACE replace=1 +% insmod test_modules/$MOD_REPLACE.ko replace=1 livepatch: enabling patch '$MOD_REPLACE' livepatch: '$MOD_REPLACE': initializing patching transition livepatch: '$MOD_REPLACE': starting patching transition diff --git a/tools/testing/selftests/livepatch/test-shadow-vars.sh b/tools/testing/selftests/livepatch/test-shadow-vars.sh index e04cb354f56b..1218c155bffe 100755 --- a/tools/testing/selftests/livepatch/test-shadow-vars.sh +++ b/tools/testing/selftests/livepatch/test-shadow-vars.sh @@ -16,7 +16,7 @@ start_test "basic shadow variable API" load_mod $MOD_TEST unload_mod $MOD_TEST
-check_result "% modprobe $MOD_TEST +check_result "% insmod test_modules/$MOD_TEST.ko $MOD_TEST: klp_shadow_get(obj=PTR1, id=0x1234) = PTR0 $MOD_TEST: got expected NULL result $MOD_TEST: shadow_ctor: PTR3 -> PTR2 diff --git a/tools/testing/selftests/livepatch/test-state.sh b/tools/testing/selftests/livepatch/test-state.sh index 38656721c958..10a52ac06185 100755 --- a/tools/testing/selftests/livepatch/test-state.sh +++ b/tools/testing/selftests/livepatch/test-state.sh @@ -19,7 +19,7 @@ load_lp $MOD_LIVEPATCH disable_lp $MOD_LIVEPATCH unload_lp $MOD_LIVEPATCH
-check_result "% modprobe $MOD_LIVEPATCH +check_result "% insmod test_modules/$MOD_LIVEPATCH.ko livepatch: enabling patch '$MOD_LIVEPATCH' livepatch: '$MOD_LIVEPATCH': initializing patching transition $MOD_LIVEPATCH: pre_patch_callback: vmlinux @@ -51,7 +51,7 @@ unload_lp $MOD_LIVEPATCH disable_lp $MOD_LIVEPATCH2 unload_lp $MOD_LIVEPATCH2
-check_result "% modprobe $MOD_LIVEPATCH +check_result "% insmod test_modules/$MOD_LIVEPATCH.ko livepatch: enabling patch '$MOD_LIVEPATCH' livepatch: '$MOD_LIVEPATCH': initializing patching transition $MOD_LIVEPATCH: pre_patch_callback: vmlinux @@ -61,7 +61,7 @@ livepatch: '$MOD_LIVEPATCH': completing patching transition $MOD_LIVEPATCH: post_patch_callback: vmlinux $MOD_LIVEPATCH: fix_console_loglevel: fixing console_loglevel livepatch: '$MOD_LIVEPATCH': patching complete -% modprobe $MOD_LIVEPATCH2 +% insmod test_modules/$MOD_LIVEPATCH2.ko livepatch: enabling patch '$MOD_LIVEPATCH2' livepatch: '$MOD_LIVEPATCH2': initializing patching transition $MOD_LIVEPATCH2: pre_patch_callback: vmlinux @@ -96,7 +96,7 @@ disable_lp $MOD_LIVEPATCH2 unload_lp $MOD_LIVEPATCH2 unload_lp $MOD_LIVEPATCH3
-check_result "% modprobe $MOD_LIVEPATCH2 +check_result "% insmod test_modules/$MOD_LIVEPATCH2.ko livepatch: enabling patch '$MOD_LIVEPATCH2' livepatch: '$MOD_LIVEPATCH2': initializing patching transition $MOD_LIVEPATCH2: pre_patch_callback: vmlinux @@ -106,7 +106,7 @@ livepatch: '$MOD_LIVEPATCH2': completing patching transition $MOD_LIVEPATCH2: post_patch_callback: vmlinux $MOD_LIVEPATCH2: fix_console_loglevel: fixing console_loglevel livepatch: '$MOD_LIVEPATCH2': patching complete -% modprobe $MOD_LIVEPATCH3 +% insmod test_modules/$MOD_LIVEPATCH3.ko livepatch: enabling patch '$MOD_LIVEPATCH3' livepatch: '$MOD_LIVEPATCH3': initializing patching transition $MOD_LIVEPATCH3: pre_patch_callback: vmlinux @@ -117,7 +117,7 @@ $MOD_LIVEPATCH3: post_patch_callback: vmlinux $MOD_LIVEPATCH3: fix_console_loglevel: taking over the console_loglevel change livepatch: '$MOD_LIVEPATCH3': patching complete % rmmod $MOD_LIVEPATCH2 -% modprobe $MOD_LIVEPATCH2 +% insmod test_modules/$MOD_LIVEPATCH2.ko livepatch: enabling patch '$MOD_LIVEPATCH2' livepatch: '$MOD_LIVEPATCH2': initializing patching transition $MOD_LIVEPATCH2: pre_patch_callback: vmlinux @@ -149,7 +149,7 @@ load_failing_mod $MOD_LIVEPATCH disable_lp $MOD_LIVEPATCH2 unload_lp $MOD_LIVEPATCH2
-check_result "% modprobe $MOD_LIVEPATCH2 +check_result "% insmod test_modules/$MOD_LIVEPATCH2.ko livepatch: enabling patch '$MOD_LIVEPATCH2' livepatch: '$MOD_LIVEPATCH2': initializing patching transition $MOD_LIVEPATCH2: pre_patch_callback: vmlinux @@ -159,9 +159,9 @@ livepatch: '$MOD_LIVEPATCH2': completing patching transition $MOD_LIVEPATCH2: post_patch_callback: vmlinux $MOD_LIVEPATCH2: fix_console_loglevel: fixing console_loglevel livepatch: '$MOD_LIVEPATCH2': patching complete -% modprobe $MOD_LIVEPATCH +% insmod test_modules/$MOD_LIVEPATCH.ko livepatch: Livepatch patch ($MOD_LIVEPATCH) is not compatible with the already installed livepatches. -modprobe: ERROR: could not insert '$MOD_LIVEPATCH': Invalid argument +insmod: ERROR: could not insert module test_modules/$MOD_LIVEPATCH.ko: Invalid parameters % echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH2/enabled livepatch: '$MOD_LIVEPATCH2': initializing unpatching transition $MOD_LIVEPATCH2: pre_unpatch_callback: vmlinux diff --git a/tools/testing/selftests/livepatch/test_modules/Makefile b/tools/testing/selftests/livepatch/test_modules/Makefile new file mode 100644 index 000000000000..375180bc1b16 --- /dev/null +++ b/tools/testing/selftests/livepatch/test_modules/Makefile @@ -0,0 +1,24 @@ +TESTMODS_DIR := $(realpath $(dir $(abspath $(lastword $(MAKEFILE_LIST))))) + +ifdef building_out_of_srctree +KDIR ?= /lib/modules/$(shell uname -r)/build +else +KDIR ?= $(abspath $(TESTMODS_DIR)/../../../../..) +endif + +obj-m += test_klp_atomic_replace.o \ + test_klp_callbacks_busy.o \ + test_klp_callbacks_demo.o \ + test_klp_callbacks_demo2.o \ + test_klp_callbacks_mod.o \ + test_klp_livepatch.o \ + test_klp_state.o \ + test_klp_state2.o \ + test_klp_state3.o \ + test_klp_shadow_vars.o + +%.ko: + make -C $(KDIR) M=$(TESTMODS_DIR) $@ + +clean: + make -C $(KDIR) M=$(TESTMODS_DIR) clean diff --git a/lib/livepatch/test_klp_atomic_replace.c b/tools/testing/selftests/livepatch/test_modules/test_klp_atomic_replace.c similarity index 100% rename from lib/livepatch/test_klp_atomic_replace.c rename to tools/testing/selftests/livepatch/test_modules/test_klp_atomic_replace.c diff --git a/lib/livepatch/test_klp_callbacks_busy.c b/tools/testing/selftests/livepatch/test_modules/test_klp_callbacks_busy.c similarity index 100% rename from lib/livepatch/test_klp_callbacks_busy.c rename to tools/testing/selftests/livepatch/test_modules/test_klp_callbacks_busy.c diff --git a/lib/livepatch/test_klp_callbacks_demo.c b/tools/testing/selftests/livepatch/test_modules/test_klp_callbacks_demo.c similarity index 100% rename from lib/livepatch/test_klp_callbacks_demo.c rename to tools/testing/selftests/livepatch/test_modules/test_klp_callbacks_demo.c diff --git a/lib/livepatch/test_klp_callbacks_demo2.c b/tools/testing/selftests/livepatch/test_modules/test_klp_callbacks_demo2.c similarity index 100% rename from lib/livepatch/test_klp_callbacks_demo2.c rename to tools/testing/selftests/livepatch/test_modules/test_klp_callbacks_demo2.c diff --git a/lib/livepatch/test_klp_callbacks_mod.c b/tools/testing/selftests/livepatch/test_modules/test_klp_callbacks_mod.c similarity index 100% rename from lib/livepatch/test_klp_callbacks_mod.c rename to tools/testing/selftests/livepatch/test_modules/test_klp_callbacks_mod.c diff --git a/lib/livepatch/test_klp_livepatch.c b/tools/testing/selftests/livepatch/test_modules/test_klp_livepatch.c similarity index 100% rename from lib/livepatch/test_klp_livepatch.c rename to tools/testing/selftests/livepatch/test_modules/test_klp_livepatch.c diff --git a/lib/livepatch/test_klp_shadow_vars.c b/tools/testing/selftests/livepatch/test_modules/test_klp_shadow_vars.c similarity index 100% rename from lib/livepatch/test_klp_shadow_vars.c rename to tools/testing/selftests/livepatch/test_modules/test_klp_shadow_vars.c diff --git a/lib/livepatch/test_klp_state.c b/tools/testing/selftests/livepatch/test_modules/test_klp_state.c similarity index 100% rename from lib/livepatch/test_klp_state.c rename to tools/testing/selftests/livepatch/test_modules/test_klp_state.c diff --git a/lib/livepatch/test_klp_state2.c b/tools/testing/selftests/livepatch/test_modules/test_klp_state2.c similarity index 100% rename from lib/livepatch/test_klp_state2.c rename to tools/testing/selftests/livepatch/test_modules/test_klp_state2.c diff --git a/lib/livepatch/test_klp_state3.c b/tools/testing/selftests/livepatch/test_modules/test_klp_state3.c similarity index 100% rename from lib/livepatch/test_klp_state3.c rename to tools/testing/selftests/livepatch/test_modules/test_klp_state3.c
Syscalls are called a tricky way. Test that it is possible and works.
This new test creates one userspace process per online cpu calling getpid continuously and tries to livepatch the getpid function.
Signed-off-by: Marcos Paulo de Souza mpdesouza@suse.com --- tools/testing/selftests/livepatch/Makefile | 12 +++- .../selftests/livepatch/test-syscall.sh | 46 ++++++++++++++ .../test_binaries/test_klp-call_getpid.c | 48 +++++++++++++++ .../selftests/livepatch/test_modules/Makefile | 3 +- .../livepatch/test_modules/test_klp_syscall.c | 60 +++++++++++++++++++ 5 files changed, 165 insertions(+), 4 deletions(-) create mode 100755 tools/testing/selftests/livepatch/test-syscall.sh create mode 100644 tools/testing/selftests/livepatch/test_binaries/test_klp-call_getpid.c create mode 100644 tools/testing/selftests/livepatch/test_modules/test_klp_syscall.c
diff --git a/tools/testing/selftests/livepatch/Makefile b/tools/testing/selftests/livepatch/Makefile index 5ef492b87bb1..35014197184e 100644 --- a/tools/testing/selftests/livepatch/Makefile +++ b/tools/testing/selftests/livepatch/Makefile @@ -1,10 +1,14 @@ # SPDX-License-Identifier: GPL-2.0 +include ../../../build/Build.include +include ../../../scripts/Makefile.arch +include ../../../scripts/Makefile.include
TEST_FILES := settings \ test_modules
# We need the test_modules dir in order to make gen_tar and install to work -TEST_GEN_PROGS_EXTENDED := test_modules/test_klp_atomic_replace.ko \ +TEST_GEN_PROGS_EXTENDED := test_binaries/test_klp-call_getpid \ + test_modules/test_klp_atomic_replace.ko \ test_modules/test_klp_callbacks_busy.ko \ test_modules/test_klp_callbacks_demo.ko \ test_modules/test_klp_callbacks_demo2.ko \ @@ -13,7 +17,8 @@ TEST_GEN_PROGS_EXTENDED := test_modules/test_klp_atomic_replace.ko \ test_modules/test_klp_state.ko \ test_modules/test_klp_state2.ko \ test_modules/test_klp_state3.ko \ - test_modules/test_klp_shadow_vars.ko + test_modules/test_klp_shadow_vars.ko \ + test_modules/test_klp_syscall.ko
TEST_PROGS_EXTENDED := functions.sh TEST_PROGS := \ @@ -21,7 +26,8 @@ TEST_PROGS := \ test-callbacks.sh \ test-shadow-vars.sh \ test-state.sh \ - test-ftrace.sh + test-ftrace.sh \ + test-syscall.sh
# override lib.mk's default rules OVERRIDE_TARGETS := 1 diff --git a/tools/testing/selftests/livepatch/test-syscall.sh b/tools/testing/selftests/livepatch/test-syscall.sh new file mode 100755 index 000000000000..f1d49e6ce2ee --- /dev/null +++ b/tools/testing/selftests/livepatch/test-syscall.sh @@ -0,0 +1,46 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022 SUSE +# Author: Marcos Paulo de Souza mpdesouza@suse.com + +. $(dirname $0)/functions.sh + +MOD_SYSCALL=test_klp_syscall + +setup_config + +# - Start _NRPROC processes calling getpid and load a livepatch to patch the +# getpid syscall + +start_test "patch getpid syscall while being heavily hammered" + +declare -a pids +for i in $(seq 1 $(getconf _NPROCESSORS_ONLN)); do + ./test_klp-call_getpid & + pids[${#pids[*]}]="$!" +done + +load_lp $MOD_SYSCALL +# Success, getpid syscall was livepatched + +for pid in ${pids[@]}; do + kill $pid || true +done + +disable_lp $MOD_SYSCALL +unload_lp $MOD_SYSCALL + +check_result "% insmod test_modules/$MOD_SYSCALL.ko +livepatch: enabling patch '$MOD_SYSCALL' +livepatch: '$MOD_SYSCALL': initializing patching transition +livepatch: '$MOD_SYSCALL': starting patching transition +livepatch: '$MOD_SYSCALL': completing patching transition +livepatch: '$MOD_SYSCALL': patching complete +% echo 0 > /sys/kernel/livepatch/$MOD_SYSCALL/enabled +livepatch: '$MOD_SYSCALL': initializing unpatching transition +livepatch: '$MOD_SYSCALL': starting unpatching transition +livepatch: '$MOD_SYSCALL': completing unpatching transition +livepatch: '$MOD_SYSCALL': unpatching complete +% rmmod $MOD_SYSCALL" + +exit 0 diff --git a/tools/testing/selftests/livepatch/test_binaries/test_klp-call_getpid.c b/tools/testing/selftests/livepatch/test_binaries/test_klp-call_getpid.c new file mode 100644 index 000000000000..be9d3110687d --- /dev/null +++ b/tools/testing/selftests/livepatch/test_binaries/test_klp-call_getpid.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2017 SUSE + * Author: Libor Pechacek lpechacek@suse.cz + */ + +#include <stdio.h> +#include <unistd.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <signal.h> + +static int run = 1; +static int sig_int; + +void hup_handler(int signum) +{ + run = 0; +} + +void int_handler(int signum) +{ + run = 0; + sig_int = 1; +} + +int main(int argc, char *argv[]) +{ + pid_t orig_pid, pid; + long count = 0; + + signal(SIGHUP, &hup_handler); + signal(SIGINT, &int_handler); + + orig_pid = syscall(SYS_getpid); + + while(run) { + pid = syscall(SYS_getpid); + if (pid != orig_pid) + return 1; + count++; + } + + if (sig_int) + printf("%d iterations done\n", count); + + return 0; +} diff --git a/tools/testing/selftests/livepatch/test_modules/Makefile b/tools/testing/selftests/livepatch/test_modules/Makefile index 375180bc1b16..288c65ccd080 100644 --- a/tools/testing/selftests/livepatch/test_modules/Makefile +++ b/tools/testing/selftests/livepatch/test_modules/Makefile @@ -15,7 +15,8 @@ obj-m += test_klp_atomic_replace.o \ test_klp_state.o \ test_klp_state2.o \ test_klp_state3.o \ - test_klp_shadow_vars.o + test_klp_shadow_vars.o \ + test_klp_syscall.o
%.ko: make -C $(KDIR) M=$(TESTMODS_DIR) $@ diff --git a/tools/testing/selftests/livepatch/test_modules/test_klp_syscall.c b/tools/testing/selftests/livepatch/test_modules/test_klp_syscall.c new file mode 100644 index 000000000000..e170accfb10c --- /dev/null +++ b/tools/testing/selftests/livepatch/test_modules/test_klp_syscall.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2017-2022 SUSE + * Authors: Libor Pechacek lpechacek@suse.cz + * Nicolai Stange nstange@suse.de + * Marcos Paulo de Souza mpdesouza@suse.com + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/livepatch.h> + +#if defined(__x86_64__) +#define FN_PREFIX __x64_ +#elif defined(__s390x__) +#define FN_PREFIX __s390x_ +#elif defined(__PPC64__) +#define FN_PREFIX __ppc64_ +#else +#error "livepatch not supported" +#endif + +asmlinkage long lp_sys_getpid(void) +{ + return task_tgid_vnr(current); +} + +static struct klp_func vmlinux_funcs[] = { + { + .old_name = __stringify(FN_PREFIX) "sys_getpid", + .new_func = lp_sys_getpid, + }, {} +}; + +static struct klp_object objs[] = { + { + /* name being NULL means vmlinux */ + .funcs = vmlinux_funcs, + }, {} +}; + +static struct klp_patch patch = { + .mod = THIS_MODULE, + .objs = objs, +}; + +static int livepatch_init(void) +{ + return klp_enable_patch(&patch); +} + +static void livepatch_exit(void) +{ +} + +module_init(livepatch_init); +module_exit(livepatch_exit); +MODULE_LICENSE("GPL"); +MODULE_INFO(livepatch, "Y");
On 6/3/22 8:32 AM, Marcos Paulo de Souza wrote:
It allows writing more complex tests, for example, an userspace C code that would use the livepatched kernel code. As a bonus it allows to use "gen_tar" to export the livepatch selftests, rebuild the modules by running make in selftests/livepatch directory and simplifies the process of creating and debugging new selftests.
It keeps the ability to execute the tests by running the shell scripts, like "test-livepatch.sh", but beware that the kernel modules might not be up-to-date.
Remove 'modprobe --dry-run' call as the modules will be built before running the tests. Also remove the TEST_LIVEPATCH Kconfig since the modules won't be build based on a Kconfig.
Adjust functions.sh to call insmod and fix the check_result strings to reflect the change.
Signed-off-by: Marcos Paulo de Souza mpdesouza@suse.com
arch/s390/configs/debug_defconfig | 1 - arch/s390/configs/defconfig | 1 - lib/Kconfig.debug | 22 -------- lib/Makefile | 2 - lib/livepatch/Makefile | 14 ------ tools/testing/selftests/livepatch/Makefile | 27 +++++++++- tools/testing/selftests/livepatch/README | 5 +- tools/testing/selftests/livepatch/config | 1 - .../testing/selftests/livepatch/functions.sh | 34 +++++-------- .../selftests/livepatch/test-callbacks.sh | 50 +++++++++---------- .../selftests/livepatch/test-ftrace.sh | 6 +-- .../selftests/livepatch/test-livepatch.sh | 10 ++-- .../selftests/livepatch/test-shadow-vars.sh | 2 +- .../testing/selftests/livepatch/test-state.sh | 18 +++---- .../selftests/livepatch/test_modules/Makefile | 24 +++++++++ .../test_modules}/test_klp_atomic_replace.c | 0 .../test_modules}/test_klp_callbacks_busy.c | 0 .../test_modules}/test_klp_callbacks_demo.c | 0 .../test_modules}/test_klp_callbacks_demo2.c | 0 .../test_modules}/test_klp_callbacks_mod.c | 0 .../test_modules}/test_klp_livepatch.c | 0 .../test_modules}/test_klp_shadow_vars.c | 0 .../livepatch/test_modules}/test_klp_state.c | 0 .../livepatch/test_modules}/test_klp_state2.c | 0 .../livepatch/test_modules}/test_klp_state3.c | 0 25 files changed, 107 insertions(+), 110 deletions(-) delete mode 100644 lib/livepatch/Makefile create mode 100644 tools/testing/selftests/livepatch/test_modules/Makefile rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_atomic_replace.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_callbacks_busy.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_callbacks_demo.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_callbacks_demo2.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_callbacks_mod.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_livepatch.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_shadow_vars.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_state.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_state2.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_state3.c (100%)
Looks good to me.
Reviewed-by: Shuah Khan skhan@linuxfoundation.org
thanks, -- Shuah
On 6/9/22 2:00 PM, Shuah Khan wrote:
On 6/3/22 8:32 AM, Marcos Paulo de Souza wrote:
It allows writing more complex tests, for example, an userspace C code that would use the livepatched kernel code. As a bonus it allows to use "gen_tar" to export the livepatch selftests, rebuild the modules by running make in selftests/livepatch directory and simplifies the process of creating and debugging new selftests.
It keeps the ability to execute the tests by running the shell scripts, like "test-livepatch.sh", but beware that the kernel modules might not be up-to-date.
Remove 'modprobe --dry-run' call as the modules will be built before running the tests. Also remove the TEST_LIVEPATCH Kconfig since the modules won't be build based on a Kconfig.
Adjust functions.sh to call insmod and fix the check_result strings to reflect the change.
Signed-off-by: Marcos Paulo de Souza mpdesouza@suse.com
arch/s390/configs/debug_defconfig | 1 - arch/s390/configs/defconfig | 1 - lib/Kconfig.debug | 22 -------- lib/Makefile | 2 - lib/livepatch/Makefile | 14 ------ tools/testing/selftests/livepatch/Makefile | 27 +++++++++- tools/testing/selftests/livepatch/README | 5 +- tools/testing/selftests/livepatch/config | 1 - .../testing/selftests/livepatch/functions.sh | 34 +++++-------- .../selftests/livepatch/test-callbacks.sh | 50 +++++++++---------- .../selftests/livepatch/test-ftrace.sh | 6 +-- .../selftests/livepatch/test-livepatch.sh | 10 ++-- .../selftests/livepatch/test-shadow-vars.sh | 2 +- .../testing/selftests/livepatch/test-state.sh | 18 +++---- .../selftests/livepatch/test_modules/Makefile | 24 +++++++++ .../test_modules}/test_klp_atomic_replace.c | 0 .../test_modules}/test_klp_callbacks_busy.c | 0 .../test_modules}/test_klp_callbacks_demo.c | 0 .../test_modules}/test_klp_callbacks_demo2.c | 0 .../test_modules}/test_klp_callbacks_mod.c | 0 .../test_modules}/test_klp_livepatch.c | 0 .../test_modules}/test_klp_shadow_vars.c | 0 .../livepatch/test_modules}/test_klp_state.c | 0 .../livepatch/test_modules}/test_klp_state2.c | 0 .../livepatch/test_modules}/test_klp_state3.c | 0 25 files changed, 107 insertions(+), 110 deletions(-) delete mode 100644 lib/livepatch/Makefile create mode 100644 tools/testing/selftests/livepatch/test_modules/Makefile rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_atomic_replace.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_callbacks_busy.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_callbacks_demo.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_callbacks_demo2.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_callbacks_mod.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_livepatch.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_shadow_vars.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_state.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_state2.c (100%) rename {lib/livepatch => tools/testing/selftests/livepatch/test_modules}/test_klp_state3.c (100%)
Looks good to me.
Reviewed-by: Shuah Khan skhan@linuxfoundation.org
Looks like this patch is moving modules under selftests. We keep modules under lib.
I have to look at this more closely - so for now I am not okay with this change.
thanks, -- Shuah
On 6/3/22 8:32 AM, Marcos Paulo de Souza wrote:
Hi there,
The first patch moves the current livepatch tests to selftests, allowing it be better suited to contain more complex tests, like using userspace C code to use the livepatched kernel code. As a bonus it allows to use "gen_tar" to export the livepatch selftests, rebuild the modules by running make in selftests/livepatch directory and simplifies the process of creating and debugging new selftests.
In general selftests don't include modules. We keep test modules under lib. One of the reasons is that modules have dependencies on the kernel and should be built when kernel is built.
I don't fully buy the argument that moving modules under selftest would simplify the process.
It keeps the ability to execute the tests by running the shell scripts, like "test-livepatch.sh", but beware that the kernel modules might not be up-to-date.
I am not what you mean by this.
The second patch includes a new test to exercise the functionality to livepatch a heavy hammered function. The test uses getpid in this case.
I tested the changes by running the tests within the kernel source tree and running from the gen_tar extracted directory.
I would like to understand the negatives of continuing to keep modules under lib?
thanks, -- Shuah
On 6/9/22 4:16 PM, Shuah Khan wrote:
On 6/3/22 8:32 AM, Marcos Paulo de Souza wrote:
Hi there,
The first patch moves the current livepatch tests to selftests, allowing it be better suited to contain more complex tests, like using userspace C code to use the livepatched kernel code. As a bonus it allows to use "gen_tar" to export the livepatch selftests, rebuild the modules by running make in selftests/livepatch directory and simplifies the process of creating and debugging new selftests.
In general selftests don't include modules. We keep test modules under lib. One of the reasons is that modules have dependencies on the kernel and should be built when kernel is built.
I don't fully buy the argument that moving modules under selftest would simplify the process.
Hi Shuah,
I see that there is tools/testing/selftests/bpf/bpf_testmod/ which claims to be a "conceptually out-of-tree module". Would similarly moving livepatch test modules under tools/ give us flexibility to write them build for multiple kernel versions? Then one could theoretically build and run the latest, greatest selftests against older kernels (assuming the associate script/module/kernel supports the idea)?
Regards,
On Thu, Jun 09, 2022 at 02:16:34PM -0600, Shuah Khan wrote:
On 6/3/22 8:32 AM, Marcos Paulo de Souza wrote:
Hi there,
The first patch moves the current livepatch tests to selftests, allowing it be better suited to contain more complex tests, like using userspace C code to use the livepatched kernel code. As a bonus it allows to use "gen_tar" to export the livepatch selftests, rebuild the modules by running make in selftests/livepatch directory and simplifies the process of creating and debugging new selftests.
In general selftests don't include modules. We keep test modules under lib. One of the reasons is that modules have dependencies on the kernel and should be built when kernel is built.
I don't fully buy the argument that moving modules under selftest would simplify the process.
As mentioned by Joe in other reply, epbf also contains a kernel module.
It keeps the ability to execute the tests by running the shell scripts, like "test-livepatch.sh", but beware that the kernel modules might not be up-to-date.
I am not what you mean by this.
The plan is to upstream some tests that SUSE is using: https://github.com/lpechacek/qa_test_klp/
The current patchset implement the tc_3 from the above repository.
The second patch includes a new test to exercise the functionality to livepatch a heavy hammered function. The test uses getpid in this case.
I tested the changes by running the tests within the kernel source tree and running from the gen_tar extracted directory.
I would like to understand the negatives of continuing to keep modules under lib?
Along with the ability to test different kernel versions by exporting the tests, the plan is to have a template kernel module, for building them on the fly. Such approach would benefit porting more tests from this repository.
One example is the testcase 5, which applies successive livepatches one after another, just changing it's name. The current patchset makes this move easier in the future.
thanks, -- Shuah
On Fri 2022-06-10 09:06:16, Joe Lawrence wrote:
On 6/9/22 4:16 PM, Shuah Khan wrote:
On 6/3/22 8:32 AM, Marcos Paulo de Souza wrote:
Hi there,
The first patch moves the current livepatch tests to selftests, allowing it be better suited to contain more complex tests, like using userspace C code to use the livepatched kernel code. As a bonus it allows to use "gen_tar" to export the livepatch selftests, rebuild the modules by running make in selftests/livepatch directory and simplifies the process of creating and debugging new selftests.
In general selftests don't include modules. We keep test modules under lib. One of the reasons is that modules have dependencies on the kernel and should be built when kernel is built.
I don't fully buy the argument that moving modules under selftest would simplify the process.
Hi Shuah,
I see that there is tools/testing/selftests/bpf/bpf_testmod/ which claims to be a "conceptually out-of-tree module". Would similarly moving livepatch test modules under tools/ give us flexibility to write them build for multiple kernel versions? Then one could theoretically build and run the latest, greatest selftests against older kernels (assuming the associate script/module/kernel supports the idea)?
+1
Another motivation is that the new selftest also needs an executable binary. It would be nice to handle both modules and binaries the same way.
Honestly, lib/* is a mess. It mixes real functionality and test modules. The relation between the modules and tools/testing/* is far from clear. IMHO, it would be more clean to have the related stuff together.
Of course, we could not move all test modules from lib/* easily. Some of them might be used on its own or even as built-in tests. But preventing the move looks like a step in the wrong direction to me.
Best Regards, Petr
On 6/10/22 8:48 AM, Petr Mladek wrote:
On Fri 2022-06-10 09:06:16, Joe Lawrence wrote:
On 6/9/22 4:16 PM, Shuah Khan wrote:
On 6/3/22 8:32 AM, Marcos Paulo de Souza wrote:
Hi there,
The first patch moves the current livepatch tests to selftests, allowing it be better suited to contain more complex tests, like using userspace C code to use the livepatched kernel code. As a bonus it allows to use "gen_tar" to export the livepatch selftests, rebuild the modules by running make in selftests/livepatch directory and simplifies the process of creating and debugging new selftests.
In general selftests don't include modules. We keep test modules under lib. One of the reasons is that modules have dependencies on the kernel and should be built when kernel is built.
I don't fully buy the argument that moving modules under selftest would simplify the process.
Hi Shuah,
I see that there is tools/testing/selftests/bpf/bpf_testmod/ which claims to be a "conceptually out-of-tree module". Would similarly moving livepatch test modules under tools/ give us flexibility to write them build for multiple kernel versions? Then one could theoretically build and run the latest, greatest selftests against older kernels (assuming the associate script/module/kernel supports the idea)?
+1
Another motivation is that the new selftest also needs an executable binary. It would be nice to handle both modules and binaries the same way.
Honestly, lib/* is a mess. It mixes real functionality and test modules. The relation between the modules and tools/testing/* is far from clear. IMHO, it would be more clean to have the related stuff together.
Of course, we could not move all test modules from lib/* easily. Some of them might be used on its own or even as built-in tests. But preventing the move looks like a step in the wrong direction to me.
As such bpf_testmod is the only one that is currently under kselftests. I don't have an objection to it from technical stand point. My concern is more from the standpoint of people writing modules that can't be built out of tree. We would add another requirement to kselftest that the out of tree modules should build successfully.
As long as that concern is addressed and also test gracefully fails if the module fails to build, we can move on that direction. I would hesitate to extend this to modules dependent on hardware and architecture features such as cpufreq test drivers for example.
thanks, -- Shuah
On Fri, Jun 03, 2022 at 11:32:42AM -0300, Marcos Paulo de Souza wrote:
Syscalls are called a tricky way. Test that it is possible and works.
"Tricky" may be accurate, but short on details. If the full story is too much for the commit log, maybe just handwave about the __SYSCALL_DEFINEx preprocessor wrappers, etc. :)
This new test creates one userspace process per online cpu calling getpid continuously and tries to livepatch the getpid function.
Signed-off-by: Marcos Paulo de Souza mpdesouza@suse.com
tools/testing/selftests/livepatch/Makefile | 12 +++- .../selftests/livepatch/test-syscall.sh | 46 ++++++++++++++ .../test_binaries/test_klp-call_getpid.c | 48 +++++++++++++++ .../selftests/livepatch/test_modules/Makefile | 3 +- .../livepatch/test_modules/test_klp_syscall.c | 60 +++++++++++++++++++ 5 files changed, 165 insertions(+), 4 deletions(-) create mode 100755 tools/testing/selftests/livepatch/test-syscall.sh create mode 100644 tools/testing/selftests/livepatch/test_binaries/test_klp-call_getpid.c create mode 100644 tools/testing/selftests/livepatch/test_modules/test_klp_syscall.c
diff --git a/tools/testing/selftests/livepatch/Makefile b/tools/testing/selftests/livepatch/Makefile index 5ef492b87bb1..35014197184e 100644 --- a/tools/testing/selftests/livepatch/Makefile +++ b/tools/testing/selftests/livepatch/Makefile @@ -1,10 +1,14 @@ # SPDX-License-Identifier: GPL-2.0 +include ../../../build/Build.include +include ../../../scripts/Makefile.arch +include ../../../scripts/Makefile.include TEST_FILES := settings \ test_modules # We need the test_modules dir in order to make gen_tar and install to work -TEST_GEN_PROGS_EXTENDED := test_modules/test_klp_atomic_replace.ko \ +TEST_GEN_PROGS_EXTENDED := test_binaries/test_klp-call_getpid \
test_modules/test_klp_atomic_replace.ko \ test_modules/test_klp_callbacks_busy.ko \ test_modules/test_klp_callbacks_demo.ko \ test_modules/test_klp_callbacks_demo2.ko \
@@ -13,7 +17,8 @@ TEST_GEN_PROGS_EXTENDED := test_modules/test_klp_atomic_replace.ko \ test_modules/test_klp_state.ko \ test_modules/test_klp_state2.ko \ test_modules/test_klp_state3.ko \
test_modules/test_klp_shadow_vars.ko
test_modules/test_klp_shadow_vars.ko \
test_modules/test_klp_syscall.ko
TEST_PROGS_EXTENDED := functions.sh TEST_PROGS := \ @@ -21,7 +26,8 @@ TEST_PROGS := \ test-callbacks.sh \ test-shadow-vars.sh \ test-state.sh \
- test-ftrace.sh
- test-ftrace.sh \
- test-syscall.sh
# override lib.mk's default rules OVERRIDE_TARGETS := 1 diff --git a/tools/testing/selftests/livepatch/test-syscall.sh b/tools/testing/selftests/livepatch/test-syscall.sh new file mode 100755 index 000000000000..f1d49e6ce2ee --- /dev/null +++ b/tools/testing/selftests/livepatch/test-syscall.sh @@ -0,0 +1,46 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022 SUSE +# Author: Marcos Paulo de Souza mpdesouza@suse.com
+. $(dirname $0)/functions.sh
+MOD_SYSCALL=test_klp_syscall
+setup_config
+# - Start _NRPROC processes calling getpid and load a livepatch to patch the +# getpid syscall
+start_test "patch getpid syscall while being heavily hammered"
+declare -a pids +for i in $(seq 1 $(getconf _NPROCESSORS_ONLN)); do
- ./test_klp-call_getpid &
- pids[${#pids[*]}]="$!"
^^^^^^^^^^^ This looks fancy, would it be more approachable to use something like this:
for i in $(seq 0 $(( $(getconf _NPROCESSORS_ONLN) - 1 )) ); do ./test_klp-call_getpid & pids[$i]="$!" done
or is there some strange race condition that requires using the method in the patch?
+done
+load_lp $MOD_SYSCALL +# Success, getpid syscall was livepatched
I don't think we need this comment as success is implied, otherwise load_lp would have pulled the die() ripcord.
+for pid in ${pids[@]}; do
- kill $pid || true
+done
+disable_lp $MOD_SYSCALL +unload_lp $MOD_SYSCALL
+check_result "% insmod test_modules/$MOD_SYSCALL.ko +livepatch: enabling patch '$MOD_SYSCALL' +livepatch: '$MOD_SYSCALL': initializing patching transition +livepatch: '$MOD_SYSCALL': starting patching transition +livepatch: '$MOD_SYSCALL': completing patching transition +livepatch: '$MOD_SYSCALL': patching complete +% echo 0 > /sys/kernel/livepatch/$MOD_SYSCALL/enabled +livepatch: '$MOD_SYSCALL': initializing unpatching transition +livepatch: '$MOD_SYSCALL': starting unpatching transition +livepatch: '$MOD_SYSCALL': completing unpatching transition +livepatch: '$MOD_SYSCALL': unpatching complete +% rmmod $MOD_SYSCALL"
+exit 0 diff --git a/tools/testing/selftests/livepatch/test_binaries/test_klp-call_getpid.c b/tools/testing/selftests/livepatch/test_binaries/test_klp-call_getpid.c new file mode 100644 index 000000000000..be9d3110687d --- /dev/null +++ b/tools/testing/selftests/livepatch/test_binaries/test_klp-call_getpid.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0 +/*
- Copyright (C) 2017 SUSE
- Author: Libor Pechacek lpechacek@suse.cz
- */
+#include <stdio.h> +#include <unistd.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <signal.h>
+static int run = 1; +static int sig_int;
+void hup_handler(int signum) +{
- run = 0;
+}
+void int_handler(int signum) +{
- run = 0;
- sig_int = 1;
+}
+int main(int argc, char *argv[]) +{
- pid_t orig_pid, pid;
- long count = 0;
- signal(SIGHUP, &hup_handler);
- signal(SIGINT, &int_handler);
- orig_pid = syscall(SYS_getpid);
- while(run) {
nit: could do s/run/stop/g and flip the assignment and check here so it matches the sig_int flag, ie, 0 by default and 1 on HUP / INT.
pid = syscall(SYS_getpid);
if (pid != orig_pid)
return 1;
count++;
- }
- if (sig_int)
printf("%d iterations done\n", count);
nit: %ld for long
- return 0;
+} diff --git a/tools/testing/selftests/livepatch/test_modules/Makefile b/tools/testing/selftests/livepatch/test_modules/Makefile index 375180bc1b16..288c65ccd080 100644 --- a/tools/testing/selftests/livepatch/test_modules/Makefile +++ b/tools/testing/selftests/livepatch/test_modules/Makefile @@ -15,7 +15,8 @@ obj-m += test_klp_atomic_replace.o \ test_klp_state.o \ test_klp_state2.o \ test_klp_state3.o \
- test_klp_shadow_vars.o
- test_klp_shadow_vars.o \
- test_klp_syscall.o
%.ko: make -C $(KDIR) M=$(TESTMODS_DIR) $@ diff --git a/tools/testing/selftests/livepatch/test_modules/test_klp_syscall.c b/tools/testing/selftests/livepatch/test_modules/test_klp_syscall.c new file mode 100644 index 000000000000..e170accfb10c --- /dev/null +++ b/tools/testing/selftests/livepatch/test_modules/test_klp_syscall.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0 +/*
- Copyright (C) 2017-2022 SUSE
- Authors: Libor Pechacek lpechacek@suse.cz
Nicolai Stange <nstange@suse.de>
Marcos Paulo de Souza <mpdesouza@suse.com>
- */
+#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/livepatch.h>
+#if defined(__x86_64__) +#define FN_PREFIX __x64_ +#elif defined(__s390x__) +#define FN_PREFIX __s390x_ +#elif defined(__PPC64__) +#define FN_PREFIX __ppc64_ +#else +#error "livepatch not supported"
What about 32-bit powerpc [1]? Would this cause the selftests to fail on that hardware?
[1] https://lore.kernel.org/live-patching/cover.1640017960.git.christophe.leroy@...
+#endif
+asmlinkage long lp_sys_getpid(void) +{
- return task_tgid_vnr(current);
+}
+static struct klp_func vmlinux_funcs[] = {
- {
.old_name = __stringify(FN_PREFIX) "sys_getpid",
.new_func = lp_sys_getpid,
- }, {}
+};
+static struct klp_object objs[] = {
- {
/* name being NULL means vmlinux */
.funcs = vmlinux_funcs,
- }, {}
+};
+static struct klp_patch patch = {
- .mod = THIS_MODULE,
- .objs = objs,
+};
+static int livepatch_init(void) +{
- return klp_enable_patch(&patch);
+}
+static void livepatch_exit(void) +{ +}
+module_init(livepatch_init); +module_exit(livepatch_exit); +MODULE_LICENSE("GPL");
+MODULE_INFO(livepatch, "Y");
2.35.3
Hi Marcos,
A few comments and small nits found inline above.
First, the test is pretty straightforward and a reasonable one to run, particularly putting the system under some load while patching.
What do you think about the following tweaks:
test_klp_syscall: - only calls the new syscall behavior for a list of known PIDs - PID list supplied via module parameter - when calling new syscall, PID is removed from list, PIDs-left-to-patch counter (exposed to sysfs) decremented
test-syscall.sh: - loads test_klp_syscall with test_klp-call_getpid PIDs that it spawned - before killing the test_klp-call_getpid PIDs, checks that test_klp_syscall's sysfs PIDs-left-to-patch counter == 0
I think this would ensure a few things:
1. Restrict the getpid syscall change to only callers expecting new behavior 2. Force test_klp_syscall to patch each test_klp-call_getpid 3. Force all test_klp-call_getpid to hang around long enough for (2)
Maybe this is too defensive, but I think could be handled without adding too much complexity.
Regards,
-- Joe
linux-kselftest-mirror@lists.linaro.org