Linux Audio

Check our new training course

Loading...
v6.2
  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
v5.4
  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