aboutsummaryrefslogtreecommitdiffstats
path: root/tools/testing/selftests/livepatch
diff options
context:
space:
mode:
authorJoe Lawrence <joe.lawrence@redhat.com>2019-01-09 07:43:29 -0500
committerJiri Kosina <jkosina@suse.cz>2019-01-11 14:51:24 -0500
commita2818ee4dce575b299d8a7f46b393bc2b02ef1f4 (patch)
tree0f616177ebf9e8d2f00023f8db89a89374e65c94 /tools/testing/selftests/livepatch
parentd67a53720966f2ef5be5c8f238d13512b8260868 (diff)
selftests/livepatch: introduce tests
Add a few livepatch modules and simple target modules that the included regression suite can run tests against: - basic livepatching (multiple patches, atomic replace) - pre/post (un)patch callbacks - shadow variable API Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com> Signed-off-by: Petr Mladek <pmladek@suse.com> Tested-by: Miroslav Benes <mbenes@suse.cz> Tested-by: Alice Ferrazzi <alice.ferrazzi@gmail.com> Acked-by: Joe Lawrence <joe.lawrence@redhat.com> Acked-by: Josh Poimboeuf <jpoimboe@redhat.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'tools/testing/selftests/livepatch')
-rw-r--r--tools/testing/selftests/livepatch/Makefile8
-rw-r--r--tools/testing/selftests/livepatch/README43
-rw-r--r--tools/testing/selftests/livepatch/config1
-rw-r--r--tools/testing/selftests/livepatch/functions.sh203
-rwxr-xr-xtools/testing/selftests/livepatch/test-callbacks.sh587
-rwxr-xr-xtools/testing/selftests/livepatch/test-livepatch.sh168
-rwxr-xr-xtools/testing/selftests/livepatch/test-shadow-vars.sh60
7 files changed, 1070 insertions, 0 deletions
diff --git a/tools/testing/selftests/livepatch/Makefile b/tools/testing/selftests/livepatch/Makefile
new file mode 100644
index 000000000000..af4aee79bebb
--- /dev/null
+++ b/tools/testing/selftests/livepatch/Makefile
@@ -0,0 +1,8 @@
1# SPDX-License-Identifier: GPL-2.0
2
3TEST_GEN_PROGS := \
4 test-livepatch.sh \
5 test-callbacks.sh \
6 test-shadow-vars.sh
7
8include ../lib.mk
diff --git a/tools/testing/selftests/livepatch/README b/tools/testing/selftests/livepatch/README
new file mode 100644
index 000000000000..b73cd0e2dd51
--- /dev/null
+++ b/tools/testing/selftests/livepatch/README
@@ -0,0 +1,43 @@
1====================
2Livepatch Self Tests
3====================
4
5This is a small set of sanity tests for the kernel livepatching.
6
7The test suite loads and unloads several test kernel modules to verify
8livepatch behavior. Debug information is logged to the kernel's message
9buffer and parsed for expected messages. (Note: the tests will clear
10the message buffer between individual tests.)
11
12
13Config
14------
15
16Set these config options and their prerequisites:
17
18CONFIG_LIVEPATCH=y
19CONFIG_TEST_LIVEPATCH=m
20
21
22Running the tests
23-----------------
24
25Test kernel modules are built as part of lib/ (make modules) and need to
26be installed (make modules_install) as the test scripts will modprobe
27them.
28
29To run the livepatch selftests, from the top of the kernel source tree:
30
31 % make -C tools/testing/selftests TARGETS=livepatch run_tests
32
33
34Adding tests
35------------
36
37See the common functions.sh file for the existing collection of utility
38functions, most importantly set_dynamic_debug() and check_result(). The
39latter function greps the kernel's ring buffer for "livepatch:" and
40"test_klp" strings, so tests be sure to include one of those strings for
41result comparison. Other utility functions include general module
42loading and livepatch loading helpers (waiting for patch transitions,
43sysfs entries, etc.)
diff --git a/tools/testing/selftests/livepatch/config b/tools/testing/selftests/livepatch/config
new file mode 100644
index 000000000000..0dd7700464a8
--- /dev/null
+++ b/tools/testing/selftests/livepatch/config
@@ -0,0 +1 @@
CONFIG_TEST_LIVEPATCH=m
diff --git a/tools/testing/selftests/livepatch/functions.sh b/tools/testing/selftests/livepatch/functions.sh
new file mode 100644
index 000000000000..c7b9fb45d7c9
--- /dev/null
+++ b/tools/testing/selftests/livepatch/functions.sh
@@ -0,0 +1,203 @@
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3# Copyright (C) 2018 Joe Lawrence <joe.lawrence@redhat.com>
4
5# Shell functions for the rest of the scripts.
6
7MAX_RETRIES=600
8RETRY_INTERVAL=".1" # seconds
9
10# log(msg) - write message to kernel log
11# msg - insightful words
12function log() {
13 echo "$1" > /dev/kmsg
14}
15
16# die(msg) - game over, man
17# msg - dying words
18function die() {
19 log "ERROR: $1"
20 echo "ERROR: $1" >&2
21 exit 1
22}
23
24# set_dynamic_debug() - setup kernel dynamic debug
25# TODO - push and pop this config?
26function set_dynamic_debug() {
27 cat << EOF > /sys/kernel/debug/dynamic_debug/control
28file kernel/livepatch/* +p
29func klp_try_switch_task -p
30EOF
31}
32
33# loop_until(cmd) - loop a command until it is successful or $MAX_RETRIES,
34# sleep $RETRY_INTERVAL between attempts
35# cmd - command and its arguments to run
36function loop_until() {
37 local cmd="$*"
38 local i=0
39 while true; do
40 eval "$cmd" && return 0
41 [[ $((i++)) -eq $MAX_RETRIES ]] && return 1
42 sleep $RETRY_INTERVAL
43 done
44}
45
46function is_livepatch_mod() {
47 local mod="$1"
48
49 if [[ $(modinfo "$mod" | awk '/^livepatch:/{print $NF}') == "Y" ]]; then
50 return 0
51 fi
52
53 return 1
54}
55
56function __load_mod() {
57 local mod="$1"; shift
58 local args="$*"
59
60 local msg="% modprobe $mod $args"
61 log "${msg%% }"
62 ret=$(modprobe "$mod" "$args" 2>&1)
63 if [[ "$ret" != "" ]]; then
64 die "$ret"
65 fi
66
67 # Wait for module in sysfs ...
68 loop_until '[[ -e "/sys/module/$mod" ]]' ||
69 die "failed to load module $mod"
70}
71
72
73# load_mod(modname, params) - load a kernel module
74# modname - module name to load
75# params - module parameters to pass to modprobe
76function load_mod() {
77 local mod="$1"; shift
78 local args="$*"
79
80 is_livepatch_mod "$mod" &&
81 die "use load_lp() to load the livepatch module $mod"
82
83 __load_mod "$mod" "$args"
84}
85
86# load_lp_nowait(modname, params) - load a kernel module with a livepatch
87# but do not wait on until the transition finishes
88# modname - module name to load
89# params - module parameters to pass to modprobe
90function load_lp_nowait() {
91 local mod="$1"; shift
92 local args="$*"
93
94 is_livepatch_mod "$mod" ||
95 die "module $mod is not a livepatch"
96
97 __load_mod "$mod" "$args"
98
99 # Wait for livepatch in sysfs ...
100 loop_until '[[ -e "/sys/kernel/livepatch/$mod" ]]' ||
101 die "failed to load module $mod (sysfs)"
102}
103
104# load_lp(modname, params) - load a kernel module with a livepatch
105# modname - module name to load
106# params - module parameters to pass to modprobe
107function load_lp() {
108 local mod="$1"; shift
109 local args="$*"
110
111 load_lp_nowait "$mod" "$args"
112
113 # Wait until the transition finishes ...
114 loop_until 'grep -q '^0$' /sys/kernel/livepatch/$mod/transition' ||
115 die "failed to complete transition"
116}
117
118# load_failing_mod(modname, params) - load a kernel module, expect to fail
119# modname - module name to load
120# params - module parameters to pass to modprobe
121function load_failing_mod() {
122 local mod="$1"; shift
123 local args="$*"
124
125 local msg="% modprobe $mod $args"
126 log "${msg%% }"
127 ret=$(modprobe "$mod" "$args" 2>&1)
128 if [[ "$ret" == "" ]]; then
129 die "$mod unexpectedly loaded"
130 fi
131 log "$ret"
132}
133
134# unload_mod(modname) - unload a kernel module
135# modname - module name to unload
136function unload_mod() {
137 local mod="$1"
138
139 # Wait for module reference count to clear ...
140 loop_until '[[ $(cat "/sys/module/$mod/refcnt") == "0" ]]' ||
141 die "failed to unload module $mod (refcnt)"
142
143 log "% rmmod $mod"
144 ret=$(rmmod "$mod" 2>&1)
145 if [[ "$ret" != "" ]]; then
146 die "$ret"
147 fi
148
149 # Wait for module in sysfs ...
150 loop_until '[[ ! -e "/sys/module/$mod" ]]' ||
151 die "failed to unload module $mod (/sys/module)"
152}
153
154# unload_lp(modname) - unload a kernel module with a livepatch
155# modname - module name to unload
156function unload_lp() {
157 unload_mod "$1"
158}
159
160# disable_lp(modname) - disable a livepatch
161# modname - module name to unload
162function disable_lp() {
163 local mod="$1"
164
165 log "% echo 0 > /sys/kernel/livepatch/$mod/enabled"
166 echo 0 > /sys/kernel/livepatch/"$mod"/enabled
167
168 # Wait until the transition finishes and the livepatch gets
169 # removed from sysfs...
170 loop_until '[[ ! -e "/sys/kernel/livepatch/$mod" ]]' ||
171 die "failed to disable livepatch $mod"
172}
173
174# set_pre_patch_ret(modname, pre_patch_ret)
175# modname - module name to set
176# pre_patch_ret - new pre_patch_ret value
177function set_pre_patch_ret {
178 local mod="$1"; shift
179 local ret="$1"
180
181 log "% echo $ret > /sys/module/$mod/parameters/pre_patch_ret"
182 echo "$ret" > /sys/module/"$mod"/parameters/pre_patch_ret
183
184 # Wait for sysfs value to hold ...
185 loop_until '[[ $(cat "/sys/module/$mod/parameters/pre_patch_ret") == "$ret" ]]' ||
186 die "failed to set pre_patch_ret parameter for $mod module"
187}
188
189# check_result() - verify dmesg output
190# TODO - better filter, out of order msgs, etc?
191function check_result {
192 local expect="$*"
193 local result
194
195 result=$(dmesg | grep -v 'tainting' | grep -e 'livepatch:' -e 'test_klp' | sed 's/^\[[ 0-9.]*\] //')
196
197 if [[ "$expect" == "$result" ]] ; then
198 echo "ok"
199 else
200 echo -e "not ok\n\n$(diff -upr --label expected --label result <(echo "$expect") <(echo "$result"))\n"
201 die "livepatch kselftest(s) failed"
202 fi
203}
diff --git a/tools/testing/selftests/livepatch/test-callbacks.sh b/tools/testing/selftests/livepatch/test-callbacks.sh
new file mode 100755
index 000000000000..e97a9dcb73c7
--- /dev/null
+++ b/tools/testing/selftests/livepatch/test-callbacks.sh
@@ -0,0 +1,587 @@
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3# Copyright (C) 2018 Joe Lawrence <joe.lawrence@redhat.com>
4
5. $(dirname $0)/functions.sh
6
7MOD_LIVEPATCH=test_klp_callbacks_demo
8MOD_LIVEPATCH2=test_klp_callbacks_demo2
9MOD_TARGET=test_klp_callbacks_mod
10MOD_TARGET_BUSY=test_klp_callbacks_busy
11
12set_dynamic_debug
13
14
15# TEST: target module before livepatch
16#
17# Test a combination of loading a kernel module and a livepatch that
18# patches a function in the first module. Load the target module
19# before the livepatch module. Unload them in the same order.
20#
21# - On livepatch enable, before the livepatch transition starts,
22# pre-patch callbacks are executed for vmlinux and $MOD_TARGET (those
23# klp_objects currently loaded). After klp_objects are patched
24# according to the klp_patch, their post-patch callbacks run and the
25# transition completes.
26#
27# - Similarly, on livepatch disable, pre-patch callbacks run before the
28# unpatching transition starts. klp_objects are reverted, post-patch
29# callbacks execute and the transition completes.
30
31echo -n "TEST: target module before livepatch ... "
32dmesg -C
33
34load_mod $MOD_TARGET
35load_lp $MOD_LIVEPATCH
36disable_lp $MOD_LIVEPATCH
37unload_lp $MOD_LIVEPATCH
38unload_mod $MOD_TARGET
39
40check_result "% modprobe $MOD_TARGET
41$MOD_TARGET: ${MOD_TARGET}_init
42% modprobe $MOD_LIVEPATCH
43livepatch: enabling patch '$MOD_LIVEPATCH'
44livepatch: '$MOD_LIVEPATCH': initializing patching transition
45$MOD_LIVEPATCH: pre_patch_callback: vmlinux
46$MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET -> [MODULE_STATE_LIVE] Normal state
47livepatch: '$MOD_LIVEPATCH': starting patching transition
48livepatch: '$MOD_LIVEPATCH': completing patching transition
49$MOD_LIVEPATCH: post_patch_callback: vmlinux
50$MOD_LIVEPATCH: post_patch_callback: $MOD_TARGET -> [MODULE_STATE_LIVE] Normal state
51livepatch: '$MOD_LIVEPATCH': patching complete
52% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
53livepatch: '$MOD_LIVEPATCH': initializing unpatching transition
54$MOD_LIVEPATCH: pre_unpatch_callback: vmlinux
55$MOD_LIVEPATCH: pre_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_LIVE] Normal state
56livepatch: '$MOD_LIVEPATCH': starting unpatching transition
57livepatch: '$MOD_LIVEPATCH': completing unpatching transition
58$MOD_LIVEPATCH: post_unpatch_callback: vmlinux
59$MOD_LIVEPATCH: post_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_LIVE] Normal state
60livepatch: '$MOD_LIVEPATCH': unpatching complete
61% rmmod $MOD_LIVEPATCH
62% rmmod $MOD_TARGET
63$MOD_TARGET: ${MOD_TARGET}_exit"
64
65
66# TEST: module_coming notifier
67#
68# This test is similar to the previous test, but (un)load the livepatch
69# module before the target kernel module. This tests the livepatch
70# core's module_coming handler.
71#
72# - On livepatch enable, only pre/post-patch callbacks are executed for
73# currently loaded klp_objects, in this case, vmlinux.
74#
75# - When a targeted module is subsequently loaded, only its
76# pre/post-patch callbacks are executed.
77#
78# - On livepatch disable, all currently loaded klp_objects' (vmlinux and
79# $MOD_TARGET) pre/post-unpatch callbacks are executed.
80
81echo -n "TEST: module_coming notifier ... "
82dmesg -C
83
84load_lp $MOD_LIVEPATCH
85load_mod $MOD_TARGET
86disable_lp $MOD_LIVEPATCH
87unload_lp $MOD_LIVEPATCH
88unload_mod $MOD_TARGET
89
90check_result "% modprobe $MOD_LIVEPATCH
91livepatch: enabling patch '$MOD_LIVEPATCH'
92livepatch: '$MOD_LIVEPATCH': initializing patching transition
93$MOD_LIVEPATCH: pre_patch_callback: vmlinux
94livepatch: '$MOD_LIVEPATCH': starting patching transition
95livepatch: '$MOD_LIVEPATCH': completing patching transition
96$MOD_LIVEPATCH: post_patch_callback: vmlinux
97livepatch: '$MOD_LIVEPATCH': patching complete
98% modprobe $MOD_TARGET
99livepatch: applying patch '$MOD_LIVEPATCH' to loading module '$MOD_TARGET'
100$MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init
101$MOD_LIVEPATCH: post_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init
102$MOD_TARGET: ${MOD_TARGET}_init
103% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
104livepatch: '$MOD_LIVEPATCH': initializing unpatching transition
105$MOD_LIVEPATCH: pre_unpatch_callback: vmlinux
106$MOD_LIVEPATCH: pre_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_LIVE] Normal state
107livepatch: '$MOD_LIVEPATCH': starting unpatching transition
108livepatch: '$MOD_LIVEPATCH': completing unpatching transition
109$MOD_LIVEPATCH: post_unpatch_callback: vmlinux
110$MOD_LIVEPATCH: post_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_LIVE] Normal state
111livepatch: '$MOD_LIVEPATCH': unpatching complete
112% rmmod $MOD_LIVEPATCH
113% rmmod $MOD_TARGET
114$MOD_TARGET: ${MOD_TARGET}_exit"
115
116
117# TEST: module_going notifier
118#
119# Test loading the livepatch after a targeted kernel module, then unload
120# the kernel module before disabling the livepatch. This tests the
121# livepatch core's module_going handler.
122#
123# - First load a target module, then the livepatch.
124#
125# - When a target module is unloaded, the livepatch is only reverted
126# from that klp_object ($MOD_TARGET). As such, only its pre and
127# post-unpatch callbacks are executed when this occurs.
128#
129# - When the livepatch is disabled, pre and post-unpatch callbacks are
130# run for the remaining klp_object, vmlinux.
131
132echo -n "TEST: module_going notifier ... "
133dmesg -C
134
135load_mod $MOD_TARGET
136load_lp $MOD_LIVEPATCH
137unload_mod $MOD_TARGET
138disable_lp $MOD_LIVEPATCH
139unload_lp $MOD_LIVEPATCH
140
141check_result "% modprobe $MOD_TARGET
142$MOD_TARGET: ${MOD_TARGET}_init
143% modprobe $MOD_LIVEPATCH
144livepatch: enabling patch '$MOD_LIVEPATCH'
145livepatch: '$MOD_LIVEPATCH': initializing patching transition
146$MOD_LIVEPATCH: pre_patch_callback: vmlinux
147$MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET -> [MODULE_STATE_LIVE] Normal state
148livepatch: '$MOD_LIVEPATCH': starting patching transition
149livepatch: '$MOD_LIVEPATCH': completing patching transition
150$MOD_LIVEPATCH: post_patch_callback: vmlinux
151$MOD_LIVEPATCH: post_patch_callback: $MOD_TARGET -> [MODULE_STATE_LIVE] Normal state
152livepatch: '$MOD_LIVEPATCH': patching complete
153% rmmod $MOD_TARGET
154$MOD_TARGET: ${MOD_TARGET}_exit
155$MOD_LIVEPATCH: pre_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_GOING] Going away
156livepatch: reverting patch '$MOD_LIVEPATCH' on unloading module '$MOD_TARGET'
157$MOD_LIVEPATCH: post_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_GOING] Going away
158% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
159livepatch: '$MOD_LIVEPATCH': initializing unpatching transition
160$MOD_LIVEPATCH: pre_unpatch_callback: vmlinux
161livepatch: '$MOD_LIVEPATCH': starting unpatching transition
162livepatch: '$MOD_LIVEPATCH': completing unpatching transition
163$MOD_LIVEPATCH: post_unpatch_callback: vmlinux
164livepatch: '$MOD_LIVEPATCH': unpatching complete
165% rmmod $MOD_LIVEPATCH"
166
167
168# TEST: module_coming and module_going notifiers
169#
170# This test is similar to the previous test, however the livepatch is
171# loaded first. This tests the livepatch core's module_coming and
172# module_going handlers.
173#
174# - First load the livepatch.
175#
176# - When a targeted kernel module is subsequently loaded, only its
177# pre/post-patch callbacks are executed.
178#
179# - When the target module is unloaded, the livepatch is only reverted
180# from the $MOD_TARGET klp_object. As such, only pre and
181# post-unpatch callbacks are executed when this occurs.
182
183echo -n "TEST: module_coming and module_going notifiers ... "
184dmesg -C
185
186load_lp $MOD_LIVEPATCH
187load_mod $MOD_TARGET
188unload_mod $MOD_TARGET
189disable_lp $MOD_LIVEPATCH
190unload_lp $MOD_LIVEPATCH
191
192check_result "% modprobe $MOD_LIVEPATCH
193livepatch: enabling patch '$MOD_LIVEPATCH'
194livepatch: '$MOD_LIVEPATCH': initializing patching transition
195$MOD_LIVEPATCH: pre_patch_callback: vmlinux
196livepatch: '$MOD_LIVEPATCH': starting patching transition
197livepatch: '$MOD_LIVEPATCH': completing patching transition
198$MOD_LIVEPATCH: post_patch_callback: vmlinux
199livepatch: '$MOD_LIVEPATCH': patching complete
200% modprobe $MOD_TARGET
201livepatch: applying patch '$MOD_LIVEPATCH' to loading module '$MOD_TARGET'
202$MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init
203$MOD_LIVEPATCH: post_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init
204$MOD_TARGET: ${MOD_TARGET}_init
205% rmmod $MOD_TARGET
206$MOD_TARGET: ${MOD_TARGET}_exit
207$MOD_LIVEPATCH: pre_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_GOING] Going away
208livepatch: reverting patch '$MOD_LIVEPATCH' on unloading module '$MOD_TARGET'
209$MOD_LIVEPATCH: post_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_GOING] Going away
210% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
211livepatch: '$MOD_LIVEPATCH': initializing unpatching transition
212$MOD_LIVEPATCH: pre_unpatch_callback: vmlinux
213livepatch: '$MOD_LIVEPATCH': starting unpatching transition
214livepatch: '$MOD_LIVEPATCH': completing unpatching transition
215$MOD_LIVEPATCH: post_unpatch_callback: vmlinux
216livepatch: '$MOD_LIVEPATCH': unpatching complete
217% rmmod $MOD_LIVEPATCH"
218
219
220# TEST: target module not present
221#
222# A simple test of loading a livepatch without one of its patch target
223# klp_objects ever loaded ($MOD_TARGET).
224#
225# - Load the livepatch.
226#
227# - As expected, only pre/post-(un)patch handlers are executed for
228# vmlinux.
229
230echo -n "TEST: target module not present ... "
231dmesg -C
232
233load_lp $MOD_LIVEPATCH
234disable_lp $MOD_LIVEPATCH
235unload_lp $MOD_LIVEPATCH
236
237check_result "% modprobe $MOD_LIVEPATCH
238livepatch: enabling patch '$MOD_LIVEPATCH'
239livepatch: '$MOD_LIVEPATCH': initializing patching transition
240$MOD_LIVEPATCH: pre_patch_callback: vmlinux
241livepatch: '$MOD_LIVEPATCH': starting patching transition
242livepatch: '$MOD_LIVEPATCH': completing patching transition
243$MOD_LIVEPATCH: post_patch_callback: vmlinux
244livepatch: '$MOD_LIVEPATCH': patching complete
245% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
246livepatch: '$MOD_LIVEPATCH': initializing unpatching transition
247$MOD_LIVEPATCH: pre_unpatch_callback: vmlinux
248livepatch: '$MOD_LIVEPATCH': starting unpatching transition
249livepatch: '$MOD_LIVEPATCH': completing unpatching transition
250$MOD_LIVEPATCH: post_unpatch_callback: vmlinux
251livepatch: '$MOD_LIVEPATCH': unpatching complete
252% rmmod $MOD_LIVEPATCH"
253
254
255# TEST: pre-patch callback -ENODEV
256#
257# Test a scenario where a vmlinux pre-patch callback returns a non-zero
258# status (ie, failure).
259#
260# - First load a target module.
261#
262# - Load the livepatch module, setting its 'pre_patch_ret' value to -19
263# (-ENODEV). When its vmlinux pre-patch callback executes, this
264# status code will propagate back to the module-loading subsystem.
265# The result is that the insmod command refuses to load the livepatch
266# module.
267
268echo -n "TEST: pre-patch callback -ENODEV ... "
269dmesg -C
270
271load_mod $MOD_TARGET
272load_failing_mod $MOD_LIVEPATCH pre_patch_ret=-19
273unload_mod $MOD_TARGET
274
275check_result "% modprobe $MOD_TARGET
276$MOD_TARGET: ${MOD_TARGET}_init
277% modprobe $MOD_LIVEPATCH pre_patch_ret=-19
278livepatch: enabling patch '$MOD_LIVEPATCH'
279livepatch: '$MOD_LIVEPATCH': initializing patching transition
280test_klp_callbacks_demo: pre_patch_callback: vmlinux
281livepatch: pre-patch callback failed for object 'vmlinux'
282livepatch: failed to enable patch '$MOD_LIVEPATCH'
283livepatch: '$MOD_LIVEPATCH': canceling patching transition, going to unpatch
284livepatch: '$MOD_LIVEPATCH': completing unpatching transition
285livepatch: '$MOD_LIVEPATCH': unpatching complete
286modprobe: ERROR: could not insert '$MOD_LIVEPATCH': No such device
287% rmmod $MOD_TARGET
288$MOD_TARGET: ${MOD_TARGET}_exit"
289
290
291# TEST: module_coming + pre-patch callback -ENODEV
292#
293# Similar to the previous test, setup a livepatch such that its vmlinux
294# pre-patch callback returns success. However, when a targeted kernel
295# module is later loaded, have the livepatch return a failing status
296# code.
297#
298# - Load the livepatch, vmlinux pre-patch callback succeeds.
299#
300# - Set a trap so subsequent pre-patch callbacks to this livepatch will
301# return -ENODEV.
302#
303# - The livepatch pre-patch callback for subsequently loaded target
304# modules will return failure, so the module loader refuses to load
305# the kernel module. No post-patch or pre/post-unpatch callbacks are
306# executed for this klp_object.
307#
308# - Pre/post-unpatch callbacks are run for the vmlinux klp_object.
309
310echo -n "TEST: module_coming + pre-patch callback -ENODEV ... "
311dmesg -C
312
313load_lp $MOD_LIVEPATCH
314set_pre_patch_ret $MOD_LIVEPATCH -19
315load_failing_mod $MOD_TARGET
316disable_lp $MOD_LIVEPATCH
317unload_lp $MOD_LIVEPATCH
318
319check_result "% modprobe $MOD_LIVEPATCH
320livepatch: enabling patch '$MOD_LIVEPATCH'
321livepatch: '$MOD_LIVEPATCH': initializing patching transition
322$MOD_LIVEPATCH: pre_patch_callback: vmlinux
323livepatch: '$MOD_LIVEPATCH': starting patching transition
324livepatch: '$MOD_LIVEPATCH': completing patching transition
325$MOD_LIVEPATCH: post_patch_callback: vmlinux
326livepatch: '$MOD_LIVEPATCH': patching complete
327% echo -19 > /sys/module/$MOD_LIVEPATCH/parameters/pre_patch_ret
328% modprobe $MOD_TARGET
329livepatch: applying patch '$MOD_LIVEPATCH' to loading module '$MOD_TARGET'
330$MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init
331livepatch: pre-patch callback failed for object '$MOD_TARGET'
332livepatch: patch '$MOD_LIVEPATCH' failed for module '$MOD_TARGET', refusing to load module '$MOD_TARGET'
333modprobe: ERROR: could not insert '$MOD_TARGET': No such device
334% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
335livepatch: '$MOD_LIVEPATCH': initializing unpatching transition
336$MOD_LIVEPATCH: pre_unpatch_callback: vmlinux
337livepatch: '$MOD_LIVEPATCH': starting unpatching transition
338livepatch: '$MOD_LIVEPATCH': completing unpatching transition
339$MOD_LIVEPATCH: post_unpatch_callback: vmlinux
340livepatch: '$MOD_LIVEPATCH': unpatching complete
341% rmmod $MOD_LIVEPATCH"
342
343
344# TEST: multiple target modules
345#
346# Test loading multiple targeted kernel modules. This test-case is
347# mainly for comparing with the next test-case.
348#
349# - Load a target "busy" kernel module which kicks off a worker function
350# that immediately exits.
351#
352# - Proceed with loading the livepatch and another ordinary target
353# module. Post-patch callbacks are executed and the transition
354# completes quickly.
355
356echo -n "TEST: multiple target modules ... "
357dmesg -C
358
359load_mod $MOD_TARGET_BUSY sleep_secs=0
360# give $MOD_TARGET_BUSY::busymod_work_func() a chance to run
361sleep 5
362load_lp $MOD_LIVEPATCH
363load_mod $MOD_TARGET
364unload_mod $MOD_TARGET
365disable_lp $MOD_LIVEPATCH
366unload_lp $MOD_LIVEPATCH
367unload_mod $MOD_TARGET_BUSY
368
369check_result "% modprobe $MOD_TARGET_BUSY sleep_secs=0
370$MOD_TARGET_BUSY: ${MOD_TARGET_BUSY}_init
371$MOD_TARGET_BUSY: busymod_work_func, sleeping 0 seconds ...
372$MOD_TARGET_BUSY: busymod_work_func exit
373% modprobe $MOD_LIVEPATCH
374livepatch: enabling patch '$MOD_LIVEPATCH'
375livepatch: '$MOD_LIVEPATCH': initializing patching transition
376$MOD_LIVEPATCH: pre_patch_callback: vmlinux
377$MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET_BUSY -> [MODULE_STATE_LIVE] Normal state
378livepatch: '$MOD_LIVEPATCH': starting patching transition
379livepatch: '$MOD_LIVEPATCH': completing patching transition
380$MOD_LIVEPATCH: post_patch_callback: vmlinux
381$MOD_LIVEPATCH: post_patch_callback: $MOD_TARGET_BUSY -> [MODULE_STATE_LIVE] Normal state
382livepatch: '$MOD_LIVEPATCH': patching complete
383% modprobe $MOD_TARGET
384livepatch: applying patch '$MOD_LIVEPATCH' to loading module '$MOD_TARGET'
385$MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init
386$MOD_LIVEPATCH: post_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init
387$MOD_TARGET: ${MOD_TARGET}_init
388% rmmod $MOD_TARGET
389$MOD_TARGET: ${MOD_TARGET}_exit
390$MOD_LIVEPATCH: pre_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_GOING] Going away
391livepatch: reverting patch '$MOD_LIVEPATCH' on unloading module '$MOD_TARGET'
392$MOD_LIVEPATCH: post_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_GOING] Going away
393% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
394livepatch: '$MOD_LIVEPATCH': initializing unpatching transition
395$MOD_LIVEPATCH: pre_unpatch_callback: vmlinux
396$MOD_LIVEPATCH: pre_unpatch_callback: $MOD_TARGET_BUSY -> [MODULE_STATE_LIVE] Normal state
397livepatch: '$MOD_LIVEPATCH': starting unpatching transition
398livepatch: '$MOD_LIVEPATCH': completing unpatching transition
399$MOD_LIVEPATCH: post_unpatch_callback: vmlinux
400$MOD_LIVEPATCH: post_unpatch_callback: $MOD_TARGET_BUSY -> [MODULE_STATE_LIVE] Normal state
401livepatch: '$MOD_LIVEPATCH': unpatching complete
402% rmmod $MOD_LIVEPATCH
403% rmmod $MOD_TARGET_BUSY
404$MOD_TARGET_BUSY: ${MOD_TARGET_BUSY}_exit"
405
406
407
408# TEST: busy target module
409#
410# A similar test as the previous one, but force the "busy" kernel module
411# to do longer work.
412#
413# The livepatching core will refuse to patch a task that is currently
414# executing a to-be-patched function -- the consistency model stalls the
415# current patch transition until this safety-check is met. Test a
416# scenario where one of a livepatch's target klp_objects sits on such a
417# function for a long time. Meanwhile, load and unload other target
418# kernel modules while the livepatch transition is in progress.
419#
420# - Load the "busy" kernel module, this time make it do 10 seconds worth
421# of work.
422#
423# - Meanwhile, the livepatch is loaded. Notice that the patch
424# transition does not complete as the targeted "busy" module is
425# sitting on a to-be-patched function.
426#
427# - Load a second target module (this one is an ordinary idle kernel
428# module). Note that *no* post-patch callbacks will be executed while
429# the livepatch is still in transition.
430#
431# - Request an unload of the simple kernel module. The patch is still
432# transitioning, so its pre-unpatch callbacks are skipped.
433#
434# - Finally the livepatch is disabled. Since none of the patch's
435# klp_object's post-patch callbacks executed, the remaining
436# klp_object's pre-unpatch callbacks are skipped.
437
438echo -n "TEST: busy target module ... "
439dmesg -C
440
441load_mod $MOD_TARGET_BUSY sleep_secs=10
442load_lp_nowait $MOD_LIVEPATCH
443# Don't wait for transition, load $MOD_TARGET while the transition
444# is still stalled in $MOD_TARGET_BUSY::busymod_work_func()
445sleep 5
446load_mod $MOD_TARGET
447unload_mod $MOD_TARGET
448disable_lp $MOD_LIVEPATCH
449unload_lp $MOD_LIVEPATCH
450unload_mod $MOD_TARGET_BUSY
451
452check_result "% modprobe $MOD_TARGET_BUSY sleep_secs=10
453$MOD_TARGET_BUSY: ${MOD_TARGET_BUSY}_init
454$MOD_TARGET_BUSY: busymod_work_func, sleeping 10 seconds ...
455% modprobe $MOD_LIVEPATCH
456livepatch: enabling patch '$MOD_LIVEPATCH'
457livepatch: '$MOD_LIVEPATCH': initializing patching transition
458$MOD_LIVEPATCH: pre_patch_callback: vmlinux
459$MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET_BUSY -> [MODULE_STATE_LIVE] Normal state
460livepatch: '$MOD_LIVEPATCH': starting patching transition
461% modprobe $MOD_TARGET
462livepatch: applying patch '$MOD_LIVEPATCH' to loading module '$MOD_TARGET'
463$MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init
464$MOD_TARGET: ${MOD_TARGET}_init
465% rmmod $MOD_TARGET
466$MOD_TARGET: ${MOD_TARGET}_exit
467livepatch: reverting patch '$MOD_LIVEPATCH' on unloading module '$MOD_TARGET'
468$MOD_LIVEPATCH: post_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_GOING] Going away
469% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
470livepatch: '$MOD_LIVEPATCH': reversing transition from patching to unpatching
471livepatch: '$MOD_LIVEPATCH': starting unpatching transition
472livepatch: '$MOD_LIVEPATCH': completing unpatching transition
473$MOD_LIVEPATCH: post_unpatch_callback: vmlinux
474$MOD_LIVEPATCH: post_unpatch_callback: $MOD_TARGET_BUSY -> [MODULE_STATE_LIVE] Normal state
475livepatch: '$MOD_LIVEPATCH': unpatching complete
476% rmmod $MOD_LIVEPATCH
477% rmmod $MOD_TARGET_BUSY
478$MOD_TARGET_BUSY: busymod_work_func exit
479$MOD_TARGET_BUSY: ${MOD_TARGET_BUSY}_exit"
480
481
482# TEST: multiple livepatches
483#
484# Test loading multiple livepatches. This test-case is mainly for comparing
485# with the next test-case.
486#
487# - Load and unload two livepatches, pre and post (un)patch callbacks
488# execute as each patch progresses through its (un)patching
489# transition.
490
491echo -n "TEST: multiple livepatches ... "
492dmesg -C
493
494load_lp $MOD_LIVEPATCH
495load_lp $MOD_LIVEPATCH2
496disable_lp $MOD_LIVEPATCH2
497disable_lp $MOD_LIVEPATCH
498unload_lp $MOD_LIVEPATCH2
499unload_lp $MOD_LIVEPATCH
500
501check_result "% modprobe $MOD_LIVEPATCH
502livepatch: enabling patch '$MOD_LIVEPATCH'
503livepatch: '$MOD_LIVEPATCH': initializing patching transition
504$MOD_LIVEPATCH: pre_patch_callback: vmlinux
505livepatch: '$MOD_LIVEPATCH': starting patching transition
506livepatch: '$MOD_LIVEPATCH': completing patching transition
507$MOD_LIVEPATCH: post_patch_callback: vmlinux
508livepatch: '$MOD_LIVEPATCH': patching complete
509% modprobe $MOD_LIVEPATCH2
510livepatch: enabling patch '$MOD_LIVEPATCH2'
511livepatch: '$MOD_LIVEPATCH2': initializing patching transition
512$MOD_LIVEPATCH2: pre_patch_callback: vmlinux
513livepatch: '$MOD_LIVEPATCH2': starting patching transition
514livepatch: '$MOD_LIVEPATCH2': completing patching transition
515$MOD_LIVEPATCH2: post_patch_callback: vmlinux
516livepatch: '$MOD_LIVEPATCH2': patching complete
517% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH2/enabled
518livepatch: '$MOD_LIVEPATCH2': initializing unpatching transition
519$MOD_LIVEPATCH2: pre_unpatch_callback: vmlinux
520livepatch: '$MOD_LIVEPATCH2': starting unpatching transition
521livepatch: '$MOD_LIVEPATCH2': completing unpatching transition
522$MOD_LIVEPATCH2: post_unpatch_callback: vmlinux
523livepatch: '$MOD_LIVEPATCH2': unpatching complete
524% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
525livepatch: '$MOD_LIVEPATCH': initializing unpatching transition
526$MOD_LIVEPATCH: pre_unpatch_callback: vmlinux
527livepatch: '$MOD_LIVEPATCH': starting unpatching transition
528livepatch: '$MOD_LIVEPATCH': completing unpatching transition
529$MOD_LIVEPATCH: post_unpatch_callback: vmlinux
530livepatch: '$MOD_LIVEPATCH': unpatching complete
531% rmmod $MOD_LIVEPATCH2
532% rmmod $MOD_LIVEPATCH"
533
534
535# TEST: atomic replace
536#
537# Load multiple livepatches, but the second as an 'atomic-replace'
538# patch. When the latter loads, the original livepatch should be
539# disabled and *none* of its pre/post-unpatch callbacks executed. On
540# the other hand, when the atomic-replace livepatch is disabled, its
541# pre/post-unpatch callbacks *should* be executed.
542#
543# - Load and unload two livepatches, the second of which has its
544# .replace flag set true.
545#
546# - Pre and post patch callbacks are executed for both livepatches.
547#
548# - Once the atomic replace module is loaded, only its pre and post
549# unpatch callbacks are executed.
550
551echo -n "TEST: atomic replace ... "
552dmesg -C
553
554load_lp $MOD_LIVEPATCH
555load_lp $MOD_LIVEPATCH2 replace=1
556disable_lp $MOD_LIVEPATCH2
557unload_lp $MOD_LIVEPATCH2
558unload_lp $MOD_LIVEPATCH
559
560check_result "% modprobe $MOD_LIVEPATCH
561livepatch: enabling patch '$MOD_LIVEPATCH'
562livepatch: '$MOD_LIVEPATCH': initializing patching transition
563$MOD_LIVEPATCH: pre_patch_callback: vmlinux
564livepatch: '$MOD_LIVEPATCH': starting patching transition
565livepatch: '$MOD_LIVEPATCH': completing patching transition
566$MOD_LIVEPATCH: post_patch_callback: vmlinux
567livepatch: '$MOD_LIVEPATCH': patching complete
568% modprobe $MOD_LIVEPATCH2 replace=1
569livepatch: enabling patch '$MOD_LIVEPATCH2'
570livepatch: '$MOD_LIVEPATCH2': initializing patching transition
571$MOD_LIVEPATCH2: pre_patch_callback: vmlinux
572livepatch: '$MOD_LIVEPATCH2': starting patching transition
573livepatch: '$MOD_LIVEPATCH2': completing patching transition
574$MOD_LIVEPATCH2: post_patch_callback: vmlinux
575livepatch: '$MOD_LIVEPATCH2': patching complete
576% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH2/enabled
577livepatch: '$MOD_LIVEPATCH2': initializing unpatching transition
578$MOD_LIVEPATCH2: pre_unpatch_callback: vmlinux
579livepatch: '$MOD_LIVEPATCH2': starting unpatching transition
580livepatch: '$MOD_LIVEPATCH2': completing unpatching transition
581$MOD_LIVEPATCH2: post_unpatch_callback: vmlinux
582livepatch: '$MOD_LIVEPATCH2': unpatching complete
583% rmmod $MOD_LIVEPATCH2
584% rmmod $MOD_LIVEPATCH"
585
586
587exit 0
diff --git a/tools/testing/selftests/livepatch/test-livepatch.sh b/tools/testing/selftests/livepatch/test-livepatch.sh
new file mode 100755
index 000000000000..f05268aea859
--- /dev/null
+++ b/tools/testing/selftests/livepatch/test-livepatch.sh
@@ -0,0 +1,168 @@
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3# Copyright (C) 2018 Joe Lawrence <joe.lawrence@redhat.com>
4
5. $(dirname $0)/functions.sh
6
7MOD_LIVEPATCH=test_klp_livepatch
8MOD_REPLACE=test_klp_atomic_replace
9
10set_dynamic_debug
11
12
13# TEST: basic function patching
14# - load a livepatch that modifies the output from /proc/cmdline and
15# verify correct behavior
16# - unload the livepatch and make sure the patch was removed
17
18echo -n "TEST: basic function patching ... "
19dmesg -C
20
21load_lp $MOD_LIVEPATCH
22
23if [[ "$(cat /proc/cmdline)" != "$MOD_LIVEPATCH: this has been live patched" ]] ; then
24 echo -e "FAIL\n\n"
25 die "livepatch kselftest(s) failed"
26fi
27
28disable_lp $MOD_LIVEPATCH
29unload_lp $MOD_LIVEPATCH
30
31if [[ "$(cat /proc/cmdline)" == "$MOD_LIVEPATCH: this has been live patched" ]] ; then
32 echo -e "FAIL\n\n"
33 die "livepatch kselftest(s) failed"
34fi
35
36check_result "% modprobe $MOD_LIVEPATCH
37livepatch: enabling patch '$MOD_LIVEPATCH'
38livepatch: '$MOD_LIVEPATCH': initializing patching transition
39livepatch: '$MOD_LIVEPATCH': starting patching transition
40livepatch: '$MOD_LIVEPATCH': completing patching transition
41livepatch: '$MOD_LIVEPATCH': patching complete
42% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
43livepatch: '$MOD_LIVEPATCH': initializing unpatching transition
44livepatch: '$MOD_LIVEPATCH': starting unpatching transition
45livepatch: '$MOD_LIVEPATCH': completing unpatching transition
46livepatch: '$MOD_LIVEPATCH': unpatching complete
47% rmmod $MOD_LIVEPATCH"
48
49
50# TEST: multiple livepatches
51# - load a livepatch that modifies the output from /proc/cmdline and
52# verify correct behavior
53# - load another livepatch and verify that both livepatches are active
54# - unload the second livepatch and verify that the first is still active
55# - unload the first livepatch and verify none are active
56
57echo -n "TEST: multiple livepatches ... "
58dmesg -C
59
60load_lp $MOD_LIVEPATCH
61
62grep 'live patched' /proc/cmdline > /dev/kmsg
63grep 'live patched' /proc/meminfo > /dev/kmsg
64
65load_lp $MOD_REPLACE replace=0
66
67grep 'live patched' /proc/cmdline > /dev/kmsg
68grep 'live patched' /proc/meminfo > /dev/kmsg
69
70disable_lp $MOD_REPLACE
71unload_lp $MOD_REPLACE
72
73grep 'live patched' /proc/cmdline > /dev/kmsg
74grep 'live patched' /proc/meminfo > /dev/kmsg
75
76disable_lp $MOD_LIVEPATCH
77unload_lp $MOD_LIVEPATCH
78
79grep 'live patched' /proc/cmdline > /dev/kmsg
80grep 'live patched' /proc/meminfo > /dev/kmsg
81
82check_result "% modprobe $MOD_LIVEPATCH
83livepatch: enabling patch '$MOD_LIVEPATCH'
84livepatch: '$MOD_LIVEPATCH': initializing patching transition
85livepatch: '$MOD_LIVEPATCH': starting patching transition
86livepatch: '$MOD_LIVEPATCH': completing patching transition
87livepatch: '$MOD_LIVEPATCH': patching complete
88$MOD_LIVEPATCH: this has been live patched
89% modprobe $MOD_REPLACE replace=0
90livepatch: enabling patch '$MOD_REPLACE'
91livepatch: '$MOD_REPLACE': initializing patching transition
92livepatch: '$MOD_REPLACE': starting patching transition
93livepatch: '$MOD_REPLACE': completing patching transition
94livepatch: '$MOD_REPLACE': patching complete
95$MOD_LIVEPATCH: this has been live patched
96$MOD_REPLACE: this has been live patched
97% echo 0 > /sys/kernel/livepatch/$MOD_REPLACE/enabled
98livepatch: '$MOD_REPLACE': initializing unpatching transition
99livepatch: '$MOD_REPLACE': starting unpatching transition
100livepatch: '$MOD_REPLACE': completing unpatching transition
101livepatch: '$MOD_REPLACE': unpatching complete
102% rmmod $MOD_REPLACE
103$MOD_LIVEPATCH: this has been live patched
104% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
105livepatch: '$MOD_LIVEPATCH': initializing unpatching transition
106livepatch: '$MOD_LIVEPATCH': starting unpatching transition
107livepatch: '$MOD_LIVEPATCH': completing unpatching transition
108livepatch: '$MOD_LIVEPATCH': unpatching complete
109% rmmod $MOD_LIVEPATCH"
110
111
112# TEST: atomic replace livepatch
113# - load a livepatch that modifies the output from /proc/cmdline and
114# verify correct behavior
115# - load an atomic replace livepatch and verify that only the second is active
116# - remove the first livepatch and verify that the atomic replace livepatch
117# is still active
118# - remove the atomic replace livepatch and verify that none are active
119
120echo -n "TEST: atomic replace livepatch ... "
121dmesg -C
122
123load_lp $MOD_LIVEPATCH
124
125grep 'live patched' /proc/cmdline > /dev/kmsg
126grep 'live patched' /proc/meminfo > /dev/kmsg
127
128load_lp $MOD_REPLACE replace=1
129
130grep 'live patched' /proc/cmdline > /dev/kmsg
131grep 'live patched' /proc/meminfo > /dev/kmsg
132
133unload_lp $MOD_LIVEPATCH
134
135grep 'live patched' /proc/cmdline > /dev/kmsg
136grep 'live patched' /proc/meminfo > /dev/kmsg
137
138disable_lp $MOD_REPLACE
139unload_lp $MOD_REPLACE
140
141grep 'live patched' /proc/cmdline > /dev/kmsg
142grep 'live patched' /proc/meminfo > /dev/kmsg
143
144check_result "% modprobe $MOD_LIVEPATCH
145livepatch: enabling patch '$MOD_LIVEPATCH'
146livepatch: '$MOD_LIVEPATCH': initializing patching transition
147livepatch: '$MOD_LIVEPATCH': starting patching transition
148livepatch: '$MOD_LIVEPATCH': completing patching transition
149livepatch: '$MOD_LIVEPATCH': patching complete
150$MOD_LIVEPATCH: this has been live patched
151% modprobe $MOD_REPLACE replace=1
152livepatch: enabling patch '$MOD_REPLACE'
153livepatch: '$MOD_REPLACE': initializing patching transition
154livepatch: '$MOD_REPLACE': starting patching transition
155livepatch: '$MOD_REPLACE': completing patching transition
156livepatch: '$MOD_REPLACE': patching complete
157$MOD_REPLACE: this has been live patched
158% rmmod $MOD_LIVEPATCH
159$MOD_REPLACE: this has been live patched
160% echo 0 > /sys/kernel/livepatch/$MOD_REPLACE/enabled
161livepatch: '$MOD_REPLACE': initializing unpatching transition
162livepatch: '$MOD_REPLACE': starting unpatching transition
163livepatch: '$MOD_REPLACE': completing unpatching transition
164livepatch: '$MOD_REPLACE': unpatching complete
165% rmmod $MOD_REPLACE"
166
167
168exit 0
diff --git a/tools/testing/selftests/livepatch/test-shadow-vars.sh b/tools/testing/selftests/livepatch/test-shadow-vars.sh
new file mode 100755
index 000000000000..04a37831e204
--- /dev/null
+++ b/tools/testing/selftests/livepatch/test-shadow-vars.sh
@@ -0,0 +1,60 @@
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3# Copyright (C) 2018 Joe Lawrence <joe.lawrence@redhat.com>
4
5. $(dirname $0)/functions.sh
6
7MOD_TEST=test_klp_shadow_vars
8
9set_dynamic_debug
10
11
12# TEST: basic shadow variable API
13# - load a module that exercises the shadow variable API
14
15echo -n "TEST: basic shadow variable API ... "
16dmesg -C
17
18load_mod $MOD_TEST
19unload_mod $MOD_TEST
20
21check_result "% modprobe $MOD_TEST
22$MOD_TEST: klp_shadow_get(obj=PTR5, id=0x1234) = PTR0
23$MOD_TEST: got expected NULL result
24$MOD_TEST: shadow_ctor: PTR6 -> PTR1
25$MOD_TEST: klp_shadow_alloc(obj=PTR5, id=0x1234, size=8, gfp_flags=GFP_KERNEL), ctor=PTR7, ctor_data=PTR1 = PTR6
26$MOD_TEST: shadow_ctor: PTR8 -> PTR2
27$MOD_TEST: klp_shadow_alloc(obj=PTR9, id=0x1234, size=8, gfp_flags=GFP_KERNEL), ctor=PTR7, ctor_data=PTR2 = PTR8
28$MOD_TEST: shadow_ctor: PTR10 -> PTR3
29$MOD_TEST: klp_shadow_alloc(obj=PTR5, id=0x1235, size=8, gfp_flags=GFP_KERNEL), ctor=PTR7, ctor_data=PTR3 = PTR10
30$MOD_TEST: klp_shadow_get(obj=PTR5, id=0x1234) = PTR6
31$MOD_TEST: got expected PTR6 -> PTR1 result
32$MOD_TEST: klp_shadow_get(obj=PTR9, id=0x1234) = PTR8
33$MOD_TEST: got expected PTR8 -> PTR2 result
34$MOD_TEST: klp_shadow_get(obj=PTR5, id=0x1235) = PTR10
35$MOD_TEST: got expected PTR10 -> PTR3 result
36$MOD_TEST: shadow_ctor: PTR11 -> PTR4
37$MOD_TEST: klp_shadow_get_or_alloc(obj=PTR12, id=0x1234, size=8, gfp_flags=GFP_KERNEL), ctor=PTR7, ctor_data=PTR4 = PTR11
38$MOD_TEST: klp_shadow_get_or_alloc(obj=PTR12, id=0x1234, size=8, gfp_flags=GFP_KERNEL), ctor=PTR7, ctor_data=PTR4 = PTR11
39$MOD_TEST: got expected PTR11 -> PTR4 result
40$MOD_TEST: shadow_dtor(obj=PTR5, shadow_data=PTR6)
41$MOD_TEST: klp_shadow_free(obj=PTR5, id=0x1234, dtor=PTR13)
42$MOD_TEST: klp_shadow_get(obj=PTR5, id=0x1234) = PTR0
43$MOD_TEST: got expected NULL result
44$MOD_TEST: shadow_dtor(obj=PTR9, shadow_data=PTR8)
45$MOD_TEST: klp_shadow_free(obj=PTR9, id=0x1234, dtor=PTR13)
46$MOD_TEST: klp_shadow_get(obj=PTR9, id=0x1234) = PTR0
47$MOD_TEST: got expected NULL result
48$MOD_TEST: shadow_dtor(obj=PTR12, shadow_data=PTR11)
49$MOD_TEST: klp_shadow_free(obj=PTR12, id=0x1234, dtor=PTR13)
50$MOD_TEST: klp_shadow_get(obj=PTR12, id=0x1234) = PTR0
51$MOD_TEST: got expected NULL result
52$MOD_TEST: klp_shadow_get(obj=PTR5, id=0x1235) = PTR10
53$MOD_TEST: got expected PTR10 -> PTR3 result
54$MOD_TEST: shadow_dtor(obj=PTR5, shadow_data=PTR10)
55$MOD_TEST: klp_shadow_free_all(id=0x1235, dtor=PTR13)
56$MOD_TEST: klp_shadow_get(obj=PTR5, id=0x1234) = PTR0
57$MOD_TEST: shadow_get() got expected NULL result
58% rmmod test_klp_shadow_vars"
59
60exit 0