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