xref: /OK3568_Linux_fs/kernel/tools/testing/selftests/livepatch/test-callbacks.sh (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun#!/bin/bash
2*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0
3*4882a593Smuzhiyun# Copyright (C) 2018 Joe Lawrence <joe.lawrence@redhat.com>
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun. $(dirname $0)/functions.sh
6*4882a593Smuzhiyun
7*4882a593SmuzhiyunMOD_LIVEPATCH=test_klp_callbacks_demo
8*4882a593SmuzhiyunMOD_LIVEPATCH2=test_klp_callbacks_demo2
9*4882a593SmuzhiyunMOD_TARGET=test_klp_callbacks_mod
10*4882a593SmuzhiyunMOD_TARGET_BUSY=test_klp_callbacks_busy
11*4882a593Smuzhiyun
12*4882a593Smuzhiyunsetup_config
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun# Test a combination of loading a kernel module and a livepatch that
16*4882a593Smuzhiyun# patches a function in the first module.  Load the target module
17*4882a593Smuzhiyun# before the livepatch module.  Unload them in the same order.
18*4882a593Smuzhiyun#
19*4882a593Smuzhiyun# - On livepatch enable, before the livepatch transition starts,
20*4882a593Smuzhiyun#   pre-patch callbacks are executed for vmlinux and $MOD_TARGET (those
21*4882a593Smuzhiyun#   klp_objects currently loaded).  After klp_objects are patched
22*4882a593Smuzhiyun#   according to the klp_patch, their post-patch callbacks run and the
23*4882a593Smuzhiyun#   transition completes.
24*4882a593Smuzhiyun#
25*4882a593Smuzhiyun# - Similarly, on livepatch disable, pre-patch callbacks run before the
26*4882a593Smuzhiyun#   unpatching transition starts.  klp_objects are reverted, post-patch
27*4882a593Smuzhiyun#   callbacks execute and the transition completes.
28*4882a593Smuzhiyun
29*4882a593Smuzhiyunstart_test "target module before livepatch"
30*4882a593Smuzhiyun
31*4882a593Smuzhiyunload_mod $MOD_TARGET
32*4882a593Smuzhiyunload_lp $MOD_LIVEPATCH
33*4882a593Smuzhiyundisable_lp $MOD_LIVEPATCH
34*4882a593Smuzhiyununload_lp $MOD_LIVEPATCH
35*4882a593Smuzhiyununload_mod $MOD_TARGET
36*4882a593Smuzhiyun
37*4882a593Smuzhiyuncheck_result "% modprobe $MOD_TARGET
38*4882a593Smuzhiyun$MOD_TARGET: ${MOD_TARGET}_init
39*4882a593Smuzhiyun% modprobe $MOD_LIVEPATCH
40*4882a593Smuzhiyunlivepatch: enabling patch '$MOD_LIVEPATCH'
41*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': initializing patching transition
42*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_patch_callback: vmlinux
43*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET -> [MODULE_STATE_LIVE] Normal state
44*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': starting patching transition
45*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': completing patching transition
46*4882a593Smuzhiyun$MOD_LIVEPATCH: post_patch_callback: vmlinux
47*4882a593Smuzhiyun$MOD_LIVEPATCH: post_patch_callback: $MOD_TARGET -> [MODULE_STATE_LIVE] Normal state
48*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': patching complete
49*4882a593Smuzhiyun% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
50*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': initializing unpatching transition
51*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_unpatch_callback: vmlinux
52*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_LIVE] Normal state
53*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': starting unpatching transition
54*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': completing unpatching transition
55*4882a593Smuzhiyun$MOD_LIVEPATCH: post_unpatch_callback: vmlinux
56*4882a593Smuzhiyun$MOD_LIVEPATCH: post_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_LIVE] Normal state
57*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': unpatching complete
58*4882a593Smuzhiyun% rmmod $MOD_LIVEPATCH
59*4882a593Smuzhiyun% rmmod $MOD_TARGET
60*4882a593Smuzhiyun$MOD_TARGET: ${MOD_TARGET}_exit"
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun# This test is similar to the previous test, but (un)load the livepatch
64*4882a593Smuzhiyun# module before the target kernel module.  This tests the livepatch
65*4882a593Smuzhiyun# core's module_coming handler.
66*4882a593Smuzhiyun#
67*4882a593Smuzhiyun# - On livepatch enable, only pre/post-patch callbacks are executed for
68*4882a593Smuzhiyun#   currently loaded klp_objects, in this case, vmlinux.
69*4882a593Smuzhiyun#
70*4882a593Smuzhiyun# - When a targeted module is subsequently loaded, only its
71*4882a593Smuzhiyun#   pre/post-patch callbacks are executed.
72*4882a593Smuzhiyun#
73*4882a593Smuzhiyun# - On livepatch disable, all currently loaded klp_objects' (vmlinux and
74*4882a593Smuzhiyun#   $MOD_TARGET) pre/post-unpatch callbacks are executed.
75*4882a593Smuzhiyun
76*4882a593Smuzhiyunstart_test "module_coming notifier"
77*4882a593Smuzhiyun
78*4882a593Smuzhiyunload_lp $MOD_LIVEPATCH
79*4882a593Smuzhiyunload_mod $MOD_TARGET
80*4882a593Smuzhiyundisable_lp $MOD_LIVEPATCH
81*4882a593Smuzhiyununload_lp $MOD_LIVEPATCH
82*4882a593Smuzhiyununload_mod $MOD_TARGET
83*4882a593Smuzhiyun
84*4882a593Smuzhiyuncheck_result "% modprobe $MOD_LIVEPATCH
85*4882a593Smuzhiyunlivepatch: enabling patch '$MOD_LIVEPATCH'
86*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': initializing patching transition
87*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_patch_callback: vmlinux
88*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': starting patching transition
89*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': completing patching transition
90*4882a593Smuzhiyun$MOD_LIVEPATCH: post_patch_callback: vmlinux
91*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': patching complete
92*4882a593Smuzhiyun% modprobe $MOD_TARGET
93*4882a593Smuzhiyunlivepatch: applying patch '$MOD_LIVEPATCH' to loading module '$MOD_TARGET'
94*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init
95*4882a593Smuzhiyun$MOD_LIVEPATCH: post_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init
96*4882a593Smuzhiyun$MOD_TARGET: ${MOD_TARGET}_init
97*4882a593Smuzhiyun% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
98*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': initializing unpatching transition
99*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_unpatch_callback: vmlinux
100*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_LIVE] Normal state
101*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': starting unpatching transition
102*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': completing unpatching transition
103*4882a593Smuzhiyun$MOD_LIVEPATCH: post_unpatch_callback: vmlinux
104*4882a593Smuzhiyun$MOD_LIVEPATCH: post_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_LIVE] Normal state
105*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': unpatching complete
106*4882a593Smuzhiyun% rmmod $MOD_LIVEPATCH
107*4882a593Smuzhiyun% rmmod $MOD_TARGET
108*4882a593Smuzhiyun$MOD_TARGET: ${MOD_TARGET}_exit"
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun# Test loading the livepatch after a targeted kernel module, then unload
112*4882a593Smuzhiyun# the kernel module before disabling the livepatch.  This tests the
113*4882a593Smuzhiyun# livepatch core's module_going handler.
114*4882a593Smuzhiyun#
115*4882a593Smuzhiyun# - First load a target module, then the livepatch.
116*4882a593Smuzhiyun#
117*4882a593Smuzhiyun# - When a target module is unloaded, the livepatch is only reverted
118*4882a593Smuzhiyun#   from that klp_object ($MOD_TARGET).  As such, only its pre and
119*4882a593Smuzhiyun#   post-unpatch callbacks are executed when this occurs.
120*4882a593Smuzhiyun#
121*4882a593Smuzhiyun# - When the livepatch is disabled, pre and post-unpatch callbacks are
122*4882a593Smuzhiyun#   run for the remaining klp_object, vmlinux.
123*4882a593Smuzhiyun
124*4882a593Smuzhiyunstart_test "module_going notifier"
125*4882a593Smuzhiyun
126*4882a593Smuzhiyunload_mod $MOD_TARGET
127*4882a593Smuzhiyunload_lp $MOD_LIVEPATCH
128*4882a593Smuzhiyununload_mod $MOD_TARGET
129*4882a593Smuzhiyundisable_lp $MOD_LIVEPATCH
130*4882a593Smuzhiyununload_lp $MOD_LIVEPATCH
131*4882a593Smuzhiyun
132*4882a593Smuzhiyuncheck_result "% modprobe $MOD_TARGET
133*4882a593Smuzhiyun$MOD_TARGET: ${MOD_TARGET}_init
134*4882a593Smuzhiyun% modprobe $MOD_LIVEPATCH
135*4882a593Smuzhiyunlivepatch: enabling patch '$MOD_LIVEPATCH'
136*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': initializing patching transition
137*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_patch_callback: vmlinux
138*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET -> [MODULE_STATE_LIVE] Normal state
139*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': starting patching transition
140*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': completing patching transition
141*4882a593Smuzhiyun$MOD_LIVEPATCH: post_patch_callback: vmlinux
142*4882a593Smuzhiyun$MOD_LIVEPATCH: post_patch_callback: $MOD_TARGET -> [MODULE_STATE_LIVE] Normal state
143*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': patching complete
144*4882a593Smuzhiyun% rmmod $MOD_TARGET
145*4882a593Smuzhiyun$MOD_TARGET: ${MOD_TARGET}_exit
146*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_GOING] Going away
147*4882a593Smuzhiyunlivepatch: reverting patch '$MOD_LIVEPATCH' on unloading module '$MOD_TARGET'
148*4882a593Smuzhiyun$MOD_LIVEPATCH: post_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_GOING] Going away
149*4882a593Smuzhiyun% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
150*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': initializing unpatching transition
151*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_unpatch_callback: vmlinux
152*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': starting unpatching transition
153*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': completing unpatching transition
154*4882a593Smuzhiyun$MOD_LIVEPATCH: post_unpatch_callback: vmlinux
155*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': unpatching complete
156*4882a593Smuzhiyun% rmmod $MOD_LIVEPATCH"
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun# This test is similar to the previous test, however the livepatch is
160*4882a593Smuzhiyun# loaded first.  This tests the livepatch core's module_coming and
161*4882a593Smuzhiyun# module_going handlers.
162*4882a593Smuzhiyun#
163*4882a593Smuzhiyun# - First load the livepatch.
164*4882a593Smuzhiyun#
165*4882a593Smuzhiyun# - When a targeted kernel module is subsequently loaded, only its
166*4882a593Smuzhiyun#   pre/post-patch callbacks are executed.
167*4882a593Smuzhiyun#
168*4882a593Smuzhiyun# - When the target module is unloaded, the livepatch is only reverted
169*4882a593Smuzhiyun#   from the $MOD_TARGET klp_object.  As such, only pre and
170*4882a593Smuzhiyun#   post-unpatch callbacks are executed when this occurs.
171*4882a593Smuzhiyun
172*4882a593Smuzhiyunstart_test "module_coming and module_going notifiers"
173*4882a593Smuzhiyun
174*4882a593Smuzhiyunload_lp $MOD_LIVEPATCH
175*4882a593Smuzhiyunload_mod $MOD_TARGET
176*4882a593Smuzhiyununload_mod $MOD_TARGET
177*4882a593Smuzhiyundisable_lp $MOD_LIVEPATCH
178*4882a593Smuzhiyununload_lp $MOD_LIVEPATCH
179*4882a593Smuzhiyun
180*4882a593Smuzhiyuncheck_result "% modprobe $MOD_LIVEPATCH
181*4882a593Smuzhiyunlivepatch: enabling patch '$MOD_LIVEPATCH'
182*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': initializing patching transition
183*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_patch_callback: vmlinux
184*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': starting patching transition
185*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': completing patching transition
186*4882a593Smuzhiyun$MOD_LIVEPATCH: post_patch_callback: vmlinux
187*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': patching complete
188*4882a593Smuzhiyun% modprobe $MOD_TARGET
189*4882a593Smuzhiyunlivepatch: applying patch '$MOD_LIVEPATCH' to loading module '$MOD_TARGET'
190*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init
191*4882a593Smuzhiyun$MOD_LIVEPATCH: post_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init
192*4882a593Smuzhiyun$MOD_TARGET: ${MOD_TARGET}_init
193*4882a593Smuzhiyun% rmmod $MOD_TARGET
194*4882a593Smuzhiyun$MOD_TARGET: ${MOD_TARGET}_exit
195*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_GOING] Going away
196*4882a593Smuzhiyunlivepatch: reverting patch '$MOD_LIVEPATCH' on unloading module '$MOD_TARGET'
197*4882a593Smuzhiyun$MOD_LIVEPATCH: post_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_GOING] Going away
198*4882a593Smuzhiyun% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
199*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': initializing unpatching transition
200*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_unpatch_callback: vmlinux
201*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': starting unpatching transition
202*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': completing unpatching transition
203*4882a593Smuzhiyun$MOD_LIVEPATCH: post_unpatch_callback: vmlinux
204*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': unpatching complete
205*4882a593Smuzhiyun% rmmod $MOD_LIVEPATCH"
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun# A simple test of loading a livepatch without one of its patch target
209*4882a593Smuzhiyun# klp_objects ever loaded ($MOD_TARGET).
210*4882a593Smuzhiyun#
211*4882a593Smuzhiyun# - Load the livepatch.
212*4882a593Smuzhiyun#
213*4882a593Smuzhiyun# - As expected, only pre/post-(un)patch handlers are executed for
214*4882a593Smuzhiyun#   vmlinux.
215*4882a593Smuzhiyun
216*4882a593Smuzhiyunstart_test "target module not present"
217*4882a593Smuzhiyun
218*4882a593Smuzhiyunload_lp $MOD_LIVEPATCH
219*4882a593Smuzhiyundisable_lp $MOD_LIVEPATCH
220*4882a593Smuzhiyununload_lp $MOD_LIVEPATCH
221*4882a593Smuzhiyun
222*4882a593Smuzhiyuncheck_result "% modprobe $MOD_LIVEPATCH
223*4882a593Smuzhiyunlivepatch: enabling patch '$MOD_LIVEPATCH'
224*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': initializing patching transition
225*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_patch_callback: vmlinux
226*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': starting patching transition
227*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': completing patching transition
228*4882a593Smuzhiyun$MOD_LIVEPATCH: post_patch_callback: vmlinux
229*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': patching complete
230*4882a593Smuzhiyun% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
231*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': initializing unpatching transition
232*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_unpatch_callback: vmlinux
233*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': starting unpatching transition
234*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': completing unpatching transition
235*4882a593Smuzhiyun$MOD_LIVEPATCH: post_unpatch_callback: vmlinux
236*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': unpatching complete
237*4882a593Smuzhiyun% rmmod $MOD_LIVEPATCH"
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun# Test a scenario where a vmlinux pre-patch callback returns a non-zero
241*4882a593Smuzhiyun# status (ie, failure).
242*4882a593Smuzhiyun#
243*4882a593Smuzhiyun# - First load a target module.
244*4882a593Smuzhiyun#
245*4882a593Smuzhiyun# - Load the livepatch module, setting its 'pre_patch_ret' value to -19
246*4882a593Smuzhiyun#   (-ENODEV).  When its vmlinux pre-patch callback executes, this
247*4882a593Smuzhiyun#   status code will propagate back to the module-loading subsystem.
248*4882a593Smuzhiyun#   The result is that the insmod command refuses to load the livepatch
249*4882a593Smuzhiyun#   module.
250*4882a593Smuzhiyun
251*4882a593Smuzhiyunstart_test "pre-patch callback -ENODEV"
252*4882a593Smuzhiyun
253*4882a593Smuzhiyunload_mod $MOD_TARGET
254*4882a593Smuzhiyunload_failing_mod $MOD_LIVEPATCH pre_patch_ret=-19
255*4882a593Smuzhiyununload_mod $MOD_TARGET
256*4882a593Smuzhiyun
257*4882a593Smuzhiyuncheck_result "% modprobe $MOD_TARGET
258*4882a593Smuzhiyun$MOD_TARGET: ${MOD_TARGET}_init
259*4882a593Smuzhiyun% modprobe $MOD_LIVEPATCH pre_patch_ret=-19
260*4882a593Smuzhiyunlivepatch: enabling patch '$MOD_LIVEPATCH'
261*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': initializing patching transition
262*4882a593Smuzhiyuntest_klp_callbacks_demo: pre_patch_callback: vmlinux
263*4882a593Smuzhiyunlivepatch: pre-patch callback failed for object 'vmlinux'
264*4882a593Smuzhiyunlivepatch: failed to enable patch '$MOD_LIVEPATCH'
265*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': canceling patching transition, going to unpatch
266*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': completing unpatching transition
267*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': unpatching complete
268*4882a593Smuzhiyunmodprobe: ERROR: could not insert '$MOD_LIVEPATCH': No such device
269*4882a593Smuzhiyun% rmmod $MOD_TARGET
270*4882a593Smuzhiyun$MOD_TARGET: ${MOD_TARGET}_exit"
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun# Similar to the previous test, setup a livepatch such that its vmlinux
274*4882a593Smuzhiyun# pre-patch callback returns success.  However, when a targeted kernel
275*4882a593Smuzhiyun# module is later loaded, have the livepatch return a failing status
276*4882a593Smuzhiyun# code.
277*4882a593Smuzhiyun#
278*4882a593Smuzhiyun# - Load the livepatch, vmlinux pre-patch callback succeeds.
279*4882a593Smuzhiyun#
280*4882a593Smuzhiyun# - Set a trap so subsequent pre-patch callbacks to this livepatch will
281*4882a593Smuzhiyun#   return -ENODEV.
282*4882a593Smuzhiyun#
283*4882a593Smuzhiyun# - The livepatch pre-patch callback for subsequently loaded target
284*4882a593Smuzhiyun#   modules will return failure, so the module loader refuses to load
285*4882a593Smuzhiyun#   the kernel module.  No post-patch or pre/post-unpatch callbacks are
286*4882a593Smuzhiyun#   executed for this klp_object.
287*4882a593Smuzhiyun#
288*4882a593Smuzhiyun# - Pre/post-unpatch callbacks are run for the vmlinux klp_object.
289*4882a593Smuzhiyun
290*4882a593Smuzhiyunstart_test "module_coming + pre-patch callback -ENODEV"
291*4882a593Smuzhiyun
292*4882a593Smuzhiyunload_lp $MOD_LIVEPATCH
293*4882a593Smuzhiyunset_pre_patch_ret $MOD_LIVEPATCH -19
294*4882a593Smuzhiyunload_failing_mod $MOD_TARGET
295*4882a593Smuzhiyundisable_lp $MOD_LIVEPATCH
296*4882a593Smuzhiyununload_lp $MOD_LIVEPATCH
297*4882a593Smuzhiyun
298*4882a593Smuzhiyuncheck_result "% modprobe $MOD_LIVEPATCH
299*4882a593Smuzhiyunlivepatch: enabling patch '$MOD_LIVEPATCH'
300*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': initializing patching transition
301*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_patch_callback: vmlinux
302*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': starting patching transition
303*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': completing patching transition
304*4882a593Smuzhiyun$MOD_LIVEPATCH: post_patch_callback: vmlinux
305*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': patching complete
306*4882a593Smuzhiyun% echo -19 > /sys/module/$MOD_LIVEPATCH/parameters/pre_patch_ret
307*4882a593Smuzhiyun% modprobe $MOD_TARGET
308*4882a593Smuzhiyunlivepatch: applying patch '$MOD_LIVEPATCH' to loading module '$MOD_TARGET'
309*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init
310*4882a593Smuzhiyunlivepatch: pre-patch callback failed for object '$MOD_TARGET'
311*4882a593Smuzhiyunlivepatch: patch '$MOD_LIVEPATCH' failed for module '$MOD_TARGET', refusing to load module '$MOD_TARGET'
312*4882a593Smuzhiyunmodprobe: ERROR: could not insert '$MOD_TARGET': No such device
313*4882a593Smuzhiyun% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
314*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': initializing unpatching transition
315*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_unpatch_callback: vmlinux
316*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': starting unpatching transition
317*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': completing unpatching transition
318*4882a593Smuzhiyun$MOD_LIVEPATCH: post_unpatch_callback: vmlinux
319*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': unpatching complete
320*4882a593Smuzhiyun% rmmod $MOD_LIVEPATCH"
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun# Test loading multiple targeted kernel modules.  This test-case is
324*4882a593Smuzhiyun# mainly for comparing with the next test-case.
325*4882a593Smuzhiyun#
326*4882a593Smuzhiyun# - Load a target "busy" kernel module which kicks off a worker function
327*4882a593Smuzhiyun#   that immediately exits.
328*4882a593Smuzhiyun#
329*4882a593Smuzhiyun# - Proceed with loading the livepatch and another ordinary target
330*4882a593Smuzhiyun#   module.  Post-patch callbacks are executed and the transition
331*4882a593Smuzhiyun#   completes quickly.
332*4882a593Smuzhiyun
333*4882a593Smuzhiyunstart_test "multiple target modules"
334*4882a593Smuzhiyun
335*4882a593Smuzhiyunload_mod $MOD_TARGET_BUSY block_transition=N
336*4882a593Smuzhiyunload_lp $MOD_LIVEPATCH
337*4882a593Smuzhiyunload_mod $MOD_TARGET
338*4882a593Smuzhiyununload_mod $MOD_TARGET
339*4882a593Smuzhiyundisable_lp $MOD_LIVEPATCH
340*4882a593Smuzhiyununload_lp $MOD_LIVEPATCH
341*4882a593Smuzhiyununload_mod $MOD_TARGET_BUSY
342*4882a593Smuzhiyun
343*4882a593Smuzhiyuncheck_result "% modprobe $MOD_TARGET_BUSY block_transition=N
344*4882a593Smuzhiyun$MOD_TARGET_BUSY: ${MOD_TARGET_BUSY}_init
345*4882a593Smuzhiyun$MOD_TARGET_BUSY: busymod_work_func enter
346*4882a593Smuzhiyun$MOD_TARGET_BUSY: busymod_work_func exit
347*4882a593Smuzhiyun% modprobe $MOD_LIVEPATCH
348*4882a593Smuzhiyunlivepatch: enabling patch '$MOD_LIVEPATCH'
349*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': initializing patching transition
350*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_patch_callback: vmlinux
351*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET_BUSY -> [MODULE_STATE_LIVE] Normal state
352*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': starting patching transition
353*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': completing patching transition
354*4882a593Smuzhiyun$MOD_LIVEPATCH: post_patch_callback: vmlinux
355*4882a593Smuzhiyun$MOD_LIVEPATCH: post_patch_callback: $MOD_TARGET_BUSY -> [MODULE_STATE_LIVE] Normal state
356*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': patching complete
357*4882a593Smuzhiyun% modprobe $MOD_TARGET
358*4882a593Smuzhiyunlivepatch: applying patch '$MOD_LIVEPATCH' to loading module '$MOD_TARGET'
359*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init
360*4882a593Smuzhiyun$MOD_LIVEPATCH: post_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init
361*4882a593Smuzhiyun$MOD_TARGET: ${MOD_TARGET}_init
362*4882a593Smuzhiyun% rmmod $MOD_TARGET
363*4882a593Smuzhiyun$MOD_TARGET: ${MOD_TARGET}_exit
364*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_GOING] Going away
365*4882a593Smuzhiyunlivepatch: reverting patch '$MOD_LIVEPATCH' on unloading module '$MOD_TARGET'
366*4882a593Smuzhiyun$MOD_LIVEPATCH: post_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_GOING] Going away
367*4882a593Smuzhiyun% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
368*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': initializing unpatching transition
369*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_unpatch_callback: vmlinux
370*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_unpatch_callback: $MOD_TARGET_BUSY -> [MODULE_STATE_LIVE] Normal state
371*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': starting unpatching transition
372*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': completing unpatching transition
373*4882a593Smuzhiyun$MOD_LIVEPATCH: post_unpatch_callback: vmlinux
374*4882a593Smuzhiyun$MOD_LIVEPATCH: post_unpatch_callback: $MOD_TARGET_BUSY -> [MODULE_STATE_LIVE] Normal state
375*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': unpatching complete
376*4882a593Smuzhiyun% rmmod $MOD_LIVEPATCH
377*4882a593Smuzhiyun% rmmod $MOD_TARGET_BUSY
378*4882a593Smuzhiyun$MOD_TARGET_BUSY: ${MOD_TARGET_BUSY}_exit"
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun# A similar test as the previous one, but force the "busy" kernel module
382*4882a593Smuzhiyun# to block the livepatch transition.
383*4882a593Smuzhiyun#
384*4882a593Smuzhiyun# The livepatching core will refuse to patch a task that is currently
385*4882a593Smuzhiyun# executing a to-be-patched function -- the consistency model stalls the
386*4882a593Smuzhiyun# current patch transition until this safety-check is met.  Test a
387*4882a593Smuzhiyun# scenario where one of a livepatch's target klp_objects sits on such a
388*4882a593Smuzhiyun# function for a long time.  Meanwhile, load and unload other target
389*4882a593Smuzhiyun# kernel modules while the livepatch transition is in progress.
390*4882a593Smuzhiyun#
391*4882a593Smuzhiyun# - Load the "busy" kernel module, this time make its work function loop
392*4882a593Smuzhiyun#
393*4882a593Smuzhiyun# - Meanwhile, the livepatch is loaded.  Notice that the patch
394*4882a593Smuzhiyun#   transition does not complete as the targeted "busy" module is
395*4882a593Smuzhiyun#   sitting on a to-be-patched function.
396*4882a593Smuzhiyun#
397*4882a593Smuzhiyun# - Load a second target module (this one is an ordinary idle kernel
398*4882a593Smuzhiyun#   module).  Note that *no* post-patch callbacks will be executed while
399*4882a593Smuzhiyun#   the livepatch is still in transition.
400*4882a593Smuzhiyun#
401*4882a593Smuzhiyun# - Request an unload of the simple kernel module.  The patch is still
402*4882a593Smuzhiyun#   transitioning, so its pre-unpatch callbacks are skipped.
403*4882a593Smuzhiyun#
404*4882a593Smuzhiyun# - Finally the livepatch is disabled.  Since none of the patch's
405*4882a593Smuzhiyun#   klp_object's post-patch callbacks executed, the remaining
406*4882a593Smuzhiyun#   klp_object's pre-unpatch callbacks are skipped.
407*4882a593Smuzhiyun
408*4882a593Smuzhiyunstart_test "busy target module"
409*4882a593Smuzhiyun
410*4882a593Smuzhiyunload_mod $MOD_TARGET_BUSY block_transition=Y
411*4882a593Smuzhiyunload_lp_nowait $MOD_LIVEPATCH
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun# Wait until the livepatch reports in-transition state, i.e. that it's
414*4882a593Smuzhiyun# stalled on $MOD_TARGET_BUSY::busymod_work_func()
415*4882a593Smuzhiyunloop_until 'grep -q '^1$' /sys/kernel/livepatch/$MOD_LIVEPATCH/transition' ||
416*4882a593Smuzhiyun	die "failed to stall transition"
417*4882a593Smuzhiyun
418*4882a593Smuzhiyunload_mod $MOD_TARGET
419*4882a593Smuzhiyununload_mod $MOD_TARGET
420*4882a593Smuzhiyundisable_lp $MOD_LIVEPATCH
421*4882a593Smuzhiyununload_lp $MOD_LIVEPATCH
422*4882a593Smuzhiyununload_mod $MOD_TARGET_BUSY
423*4882a593Smuzhiyun
424*4882a593Smuzhiyuncheck_result "% modprobe $MOD_TARGET_BUSY block_transition=Y
425*4882a593Smuzhiyun$MOD_TARGET_BUSY: ${MOD_TARGET_BUSY}_init
426*4882a593Smuzhiyun$MOD_TARGET_BUSY: busymod_work_func enter
427*4882a593Smuzhiyun% modprobe $MOD_LIVEPATCH
428*4882a593Smuzhiyunlivepatch: enabling patch '$MOD_LIVEPATCH'
429*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': initializing patching transition
430*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_patch_callback: vmlinux
431*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET_BUSY -> [MODULE_STATE_LIVE] Normal state
432*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': starting patching transition
433*4882a593Smuzhiyun% modprobe $MOD_TARGET
434*4882a593Smuzhiyunlivepatch: applying patch '$MOD_LIVEPATCH' to loading module '$MOD_TARGET'
435*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init
436*4882a593Smuzhiyun$MOD_TARGET: ${MOD_TARGET}_init
437*4882a593Smuzhiyun% rmmod $MOD_TARGET
438*4882a593Smuzhiyun$MOD_TARGET: ${MOD_TARGET}_exit
439*4882a593Smuzhiyunlivepatch: reverting patch '$MOD_LIVEPATCH' on unloading module '$MOD_TARGET'
440*4882a593Smuzhiyun$MOD_LIVEPATCH: post_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_GOING] Going away
441*4882a593Smuzhiyun% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
442*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': reversing transition from patching to unpatching
443*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': starting unpatching transition
444*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': completing unpatching transition
445*4882a593Smuzhiyun$MOD_LIVEPATCH: post_unpatch_callback: vmlinux
446*4882a593Smuzhiyun$MOD_LIVEPATCH: post_unpatch_callback: $MOD_TARGET_BUSY -> [MODULE_STATE_LIVE] Normal state
447*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': unpatching complete
448*4882a593Smuzhiyun% rmmod $MOD_LIVEPATCH
449*4882a593Smuzhiyun% rmmod $MOD_TARGET_BUSY
450*4882a593Smuzhiyun$MOD_TARGET_BUSY: busymod_work_func exit
451*4882a593Smuzhiyun$MOD_TARGET_BUSY: ${MOD_TARGET_BUSY}_exit"
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun# Test loading multiple livepatches.  This test-case is mainly for comparing
455*4882a593Smuzhiyun# with the next test-case.
456*4882a593Smuzhiyun#
457*4882a593Smuzhiyun# - Load and unload two livepatches, pre and post (un)patch callbacks
458*4882a593Smuzhiyun#   execute as each patch progresses through its (un)patching
459*4882a593Smuzhiyun#   transition.
460*4882a593Smuzhiyun
461*4882a593Smuzhiyunstart_test "multiple livepatches"
462*4882a593Smuzhiyun
463*4882a593Smuzhiyunload_lp $MOD_LIVEPATCH
464*4882a593Smuzhiyunload_lp $MOD_LIVEPATCH2
465*4882a593Smuzhiyundisable_lp $MOD_LIVEPATCH2
466*4882a593Smuzhiyundisable_lp $MOD_LIVEPATCH
467*4882a593Smuzhiyununload_lp $MOD_LIVEPATCH2
468*4882a593Smuzhiyununload_lp $MOD_LIVEPATCH
469*4882a593Smuzhiyun
470*4882a593Smuzhiyuncheck_result "% modprobe $MOD_LIVEPATCH
471*4882a593Smuzhiyunlivepatch: enabling patch '$MOD_LIVEPATCH'
472*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': initializing patching transition
473*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_patch_callback: vmlinux
474*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': starting patching transition
475*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': completing patching transition
476*4882a593Smuzhiyun$MOD_LIVEPATCH: post_patch_callback: vmlinux
477*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': patching complete
478*4882a593Smuzhiyun% modprobe $MOD_LIVEPATCH2
479*4882a593Smuzhiyunlivepatch: enabling patch '$MOD_LIVEPATCH2'
480*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH2': initializing patching transition
481*4882a593Smuzhiyun$MOD_LIVEPATCH2: pre_patch_callback: vmlinux
482*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH2': starting patching transition
483*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH2': completing patching transition
484*4882a593Smuzhiyun$MOD_LIVEPATCH2: post_patch_callback: vmlinux
485*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH2': patching complete
486*4882a593Smuzhiyun% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH2/enabled
487*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH2': initializing unpatching transition
488*4882a593Smuzhiyun$MOD_LIVEPATCH2: pre_unpatch_callback: vmlinux
489*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH2': starting unpatching transition
490*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH2': completing unpatching transition
491*4882a593Smuzhiyun$MOD_LIVEPATCH2: post_unpatch_callback: vmlinux
492*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH2': unpatching complete
493*4882a593Smuzhiyun% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
494*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': initializing unpatching transition
495*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_unpatch_callback: vmlinux
496*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': starting unpatching transition
497*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': completing unpatching transition
498*4882a593Smuzhiyun$MOD_LIVEPATCH: post_unpatch_callback: vmlinux
499*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': unpatching complete
500*4882a593Smuzhiyun% rmmod $MOD_LIVEPATCH2
501*4882a593Smuzhiyun% rmmod $MOD_LIVEPATCH"
502*4882a593Smuzhiyun
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun# Load multiple livepatches, but the second as an 'atomic-replace'
505*4882a593Smuzhiyun# patch.  When the latter loads, the original livepatch should be
506*4882a593Smuzhiyun# disabled and *none* of its pre/post-unpatch callbacks executed.  On
507*4882a593Smuzhiyun# the other hand, when the atomic-replace livepatch is disabled, its
508*4882a593Smuzhiyun# pre/post-unpatch callbacks *should* be executed.
509*4882a593Smuzhiyun#
510*4882a593Smuzhiyun# - Load and unload two livepatches, the second of which has its
511*4882a593Smuzhiyun#   .replace flag set true.
512*4882a593Smuzhiyun#
513*4882a593Smuzhiyun# - Pre and post patch callbacks are executed for both livepatches.
514*4882a593Smuzhiyun#
515*4882a593Smuzhiyun# - Once the atomic replace module is loaded, only its pre and post
516*4882a593Smuzhiyun#   unpatch callbacks are executed.
517*4882a593Smuzhiyun
518*4882a593Smuzhiyunstart_test "atomic replace"
519*4882a593Smuzhiyun
520*4882a593Smuzhiyunload_lp $MOD_LIVEPATCH
521*4882a593Smuzhiyunload_lp $MOD_LIVEPATCH2 replace=1
522*4882a593Smuzhiyundisable_lp $MOD_LIVEPATCH2
523*4882a593Smuzhiyununload_lp $MOD_LIVEPATCH2
524*4882a593Smuzhiyununload_lp $MOD_LIVEPATCH
525*4882a593Smuzhiyun
526*4882a593Smuzhiyuncheck_result "% modprobe $MOD_LIVEPATCH
527*4882a593Smuzhiyunlivepatch: enabling patch '$MOD_LIVEPATCH'
528*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': initializing patching transition
529*4882a593Smuzhiyun$MOD_LIVEPATCH: pre_patch_callback: vmlinux
530*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': starting patching transition
531*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': completing patching transition
532*4882a593Smuzhiyun$MOD_LIVEPATCH: post_patch_callback: vmlinux
533*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH': patching complete
534*4882a593Smuzhiyun% modprobe $MOD_LIVEPATCH2 replace=1
535*4882a593Smuzhiyunlivepatch: enabling patch '$MOD_LIVEPATCH2'
536*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH2': initializing patching transition
537*4882a593Smuzhiyun$MOD_LIVEPATCH2: pre_patch_callback: vmlinux
538*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH2': starting patching transition
539*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH2': completing patching transition
540*4882a593Smuzhiyun$MOD_LIVEPATCH2: post_patch_callback: vmlinux
541*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH2': patching complete
542*4882a593Smuzhiyun% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH2/enabled
543*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH2': initializing unpatching transition
544*4882a593Smuzhiyun$MOD_LIVEPATCH2: pre_unpatch_callback: vmlinux
545*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH2': starting unpatching transition
546*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH2': completing unpatching transition
547*4882a593Smuzhiyun$MOD_LIVEPATCH2: post_unpatch_callback: vmlinux
548*4882a593Smuzhiyunlivepatch: '$MOD_LIVEPATCH2': unpatching complete
549*4882a593Smuzhiyun% rmmod $MOD_LIVEPATCH2
550*4882a593Smuzhiyun% rmmod $MOD_LIVEPATCH"
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun
553*4882a593Smuzhiyunexit 0
554