diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-03-08 08:58:25 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-03-08 08:58:25 -0800 |
| commit | b7af27bf9471f5d54d71dc2e4228d6bc065bdb57 (patch) | |
| tree | efe61bdce366720345f4f4fb663c31c9a4f00a08 | |
| parent | 851ca779d110f694b5d078bc4af06d3ad37169e8 (diff) | |
| parent | f9d138145686b52b48ccb36557d6842076e2b9dd (diff) | |
| download | linux-b7af27bf9471f5d54d71dc2e4228d6bc065bdb57.tar.gz linux-b7af27bf9471f5d54d71dc2e4228d6bc065bdb57.tar.bz2 linux-b7af27bf9471f5d54d71dc2e4228d6bc065bdb57.zip | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/livepatching/livepatching
Pull livepatching updates from Jiri Kosina:
- support for something we call 'atomic replace', and allows for much
better handling of cumulative patches (which is something very useful
for distros), from Jason Baron with help of Petr Mladek and Joe
Lawrence
- improvement of handling of tasks blocking finalization, from Miroslav
Benes
- update of MAINTAINERS file to reflect move towards group
maintainership
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/livepatching/livepatching: (22 commits)
livepatch/selftests: use "$@" to preserve argument list
livepatch: Module coming and going callbacks can proceed with all listed patches
livepatch: Proper error handling in the shadow variables selftest
livepatch: return -ENOMEM on ptr_id() allocation failure
livepatch: Introduce klp_for_each_patch macro
livepatch: core: Return EOPNOTSUPP instead of ENOSYS
selftests/livepatch: add DYNAMIC_DEBUG config dependency
livepatch: samples: non static warnings fix
livepatch: update MAINTAINERS
livepatch: Remove signal sysfs attribute
livepatch: Send a fake signal periodically
selftests/livepatch: introduce tests
livepatch: Remove ordering (stacking) of the livepatches
livepatch: Atomic replace and cumulative patches documentation
livepatch: Remove Nop structures when unused
livepatch: Add atomic replace
livepatch: Use lists to manage patches, objects and functions
livepatch: Simplify API by removing registration step
livepatch: Don't block the removal of patches loaded after a forced transition
livepatch: Consolidate klp_free functions
...
35 files changed, 2649 insertions, 1071 deletions
diff --git a/Documentation/ABI/testing/sysfs-kernel-livepatch b/Documentation/ABI/testing/sysfs-kernel-livepatch index dac7e1e62a8b..85db352f68f9 100644 --- a/Documentation/ABI/testing/sysfs-kernel-livepatch +++ b/Documentation/ABI/testing/sysfs-kernel-livepatch @@ -33,18 +33,6 @@ Description: An attribute which indicates whether the patch is currently in transition. -What: /sys/kernel/livepatch/<patch>/signal -Date: Nov 2017 -KernelVersion: 4.15.0 -Contact: live-patching@vger.kernel.org -Description: - A writable attribute that allows administrator to affect the - course of an existing transition. Writing 1 sends a fake - signal to all remaining blocking tasks. The fake signal - means that no proper signal is delivered (there is no data in - signal pending structures). Tasks are interrupted or woken up, - and forced to change their patched state. - What: /sys/kernel/livepatch/<patch>/force Date: Nov 2017 KernelVersion: 4.15.0 diff --git a/Documentation/livepatch/callbacks.txt b/Documentation/livepatch/callbacks.txt index c9776f48e458..182e31d4abce 100644 --- a/Documentation/livepatch/callbacks.txt +++ b/Documentation/livepatch/callbacks.txt @@ -118,488 +118,9 @@ similar change to their hw_features value. (Client functions of the value may need to be updated accordingly.) -Test cases -========== - -What follows is not an exhaustive test suite of every possible livepatch -pre/post-(un)patch combination, but a selection that demonstrates a few -important concepts. Each test case uses the kernel modules located in -the samples/livepatch/ and assumes that no livepatches are loaded at the -beginning of the test. - - -Test 1 ------- - -Test a combination of loading a kernel module and a livepatch that -patches a function in the first module. (Un)load the target module -before the livepatch module: - -- load target module -- load livepatch -- disable livepatch -- unload target module -- unload livepatch - -First load a target module: - - % insmod samples/livepatch/livepatch-callbacks-mod.ko - [ 34.475708] livepatch_callbacks_mod: livepatch_callbacks_mod_init - -On livepatch enable, before the livepatch transition starts, pre-patch -callbacks are executed for vmlinux and livepatch_callbacks_mod (those -klp_objects currently loaded). After klp_objects are patched according -to the klp_patch, their post-patch callbacks run and the transition -completes: - - % insmod samples/livepatch/livepatch-callbacks-demo.ko - [ 36.503719] livepatch: enabling patch 'livepatch_callbacks_demo' - [ 36.504213] livepatch: 'livepatch_callbacks_demo': initializing patching transition - [ 36.504238] livepatch_callbacks_demo: pre_patch_callback: vmlinux - [ 36.504721] livepatch_callbacks_demo: pre_patch_callback: livepatch_callbacks_mod -> [MODULE_STATE_LIVE] Normal state - [ 36.505849] livepatch: 'livepatch_callbacks_demo': starting patching transition - [ 37.727133] livepatch: 'livepatch_callbacks_demo': completing patching transition - [ 37.727232] livepatch_callbacks_demo: post_patch_callback: vmlinux - [ 37.727860] livepatch_callbacks_demo: post_patch_callback: livepatch_callbacks_mod -> [MODULE_STATE_LIVE] Normal state - [ 37.728792] livepatch: 'livepatch_callbacks_demo': patching complete - -Similarly, on livepatch disable, pre-patch callbacks run before the -unpatching transition starts. klp_objects are reverted, post-patch -callbacks execute and the transition completes: - - % echo 0 > /sys/kernel/livepatch/livepatch_callbacks_demo/enabled - [ 38.510209] livepatch: 'livepatch_callbacks_demo': initializing unpatching transition - [ 38.510234] livepatch_callbacks_demo: pre_unpatch_callback: vmlinux - [ 38.510982] livepatch_callbacks_demo: pre_unpatch_callback: livepatch_callbacks_mod -> [MODULE_STATE_LIVE] Normal state - [ 38.512209] livepatch: 'livepatch_callbacks_demo': starting unpatching transition - [ 39.711132] livepatch: 'livepatch_callbacks_demo': completing unpatching transition - [ 39.711210] livepatch_callbacks_demo: post_unpatch_callback: vmlinux - [ 39.711779] livepatch_callbacks_demo: post_unpatch_callback: livepatch_callbacks_mod -> [MODULE_STATE_LIVE] Normal state - [ 39.712735] livepatch: 'livepatch_callbacks_demo': unpatching complete - - % rmmod samples/livepatch/livepatch-callbacks-demo.ko - % rmmod samples/livepatch/livepatch-callbacks-mod.ko - [ 42.534183] livepatch_callbacks_mod: livepatch_callbacks_mod_exit - - -Test 2 ------- - -This test is similar to the previous test, but (un)load the livepatch -module before the target kernel module. This tests the livepatch core's -module_coming handler: - -- load livepatch -- load target module -- disable livepatch -- unload livepatch -- unload target module - - -On livepatch enable, only pre/post-patch callbacks are executed for -currently loaded klp_objects, in this case, vmlinux: - - % insmod samples/livepatch/livepatch-callbacks-demo.ko - [ 44.553328] livepatch: enabling patch 'livepatch_callbacks_demo' - [ 44.553997] livepatch: 'livepatch_callbacks_demo': initializing patching transition - [ 44.554049] livepatch_callbacks_demo: pre_patch_callback: vmlinux - [ 44.554845] livepatch: 'livepatch_callbacks_demo': starting patching transition - [ 45.727128] livepatch: 'livepatch_callbacks_demo': completing patching transition - [ 45.727212] livepatch_callbacks_demo: post_patch_callback: vmlinux - [ 45.727961] livepatch: 'livepatch_callbacks_demo': patching complete - -When a targeted module is subsequently loaded, only its pre/post-patch -callbacks are executed: - - % insmod samples/livepatch/livepatch-callbacks-mod.ko - [ 46.560845] livepatch: applying patch 'livepatch_callbacks_demo' to loading module 'livepatch_callbacks_mod' - [ 46.561988] livepatch_callbacks_demo: pre_patch_callback: livepatch_callbacks_mod -> [MODULE_STATE_COMING] Full formed, running module_init - [ 46.563452] livepatch_callbacks_demo: post_patch_callback: livepatch_callbacks_mod -> [MODULE_STATE_COMING] Full formed, running module_init - [ 46.565495] livepatch_callbacks_mod: livepatch_callbacks_mod_init - -On livepatch disable, all currently loaded klp_objects' (vmlinux and -livepatch_callbacks_mod) pre/post-unpatch callbacks are executed: - - % echo 0 > /sys/kernel/livepatch/livepatch_callbacks_demo/enabled - [ 48.568885] livepatch: 'livepatch_callbacks_demo': initializing unpatching transition - [ 48.568910] livepatch_callbacks_demo: pre_unpatch_callback: vmlinux - [ 48.569441] livepatch_callbacks_demo: pre_unpatch_callback: livepatch_callbacks_mod -> [MODULE_STATE_LIVE] Normal state - [ 48.570502] livepatch: 'livepatch_callbacks_demo': starting unpatching transition - [ 49.759091] livepatch: 'livepatch_callbacks_demo': completing unpatching transition - [ 49.759171] livepatch_callbacks_demo: post_unpatch_callback: vmlinux - [ 49.759742] livepatch_callbacks_demo: post_unpatch_callback: livepatch_callbacks_mod -> [MODULE_STATE_LIVE] Normal state - [ 49.760690] livepatch: 'livepatch_callbacks_demo': unpatching complete - - % rmmod samples/livepatch/livepatch-callbacks-demo.ko - % rmmod samples/livepatch/livepatch-callbacks-mod.ko - [ 52.592283] livepatch_callbacks_mod: livepatch_callbacks_mod_exit - - -Test 3 ------- - -Test loading the livepatch after a targeted kernel module, then unload -the kernel module before disabling the livepatch. This tests the -livepatch core's module_going handler: - -- load target module -- load livepatch -- unload target module -- disable livepatch -- unload livepatch - -First load a target module, then the livepatch: - - % insmod samples/livepatch/livepatch-callbacks-mod.ko - [ 54.607948] livepatch_callbacks_mod: livepatch_callbacks_mod_init - - % insmod samples/livepatch/livepatch-callbacks-demo.ko - [ 56.613919] livepatch: enabling patch 'livepatch_callbacks_demo' - [ 56.614411] livepatch: 'livepatch_callbacks_demo': initializing patching transition - [ 56.614436] livepatch_callbacks_demo: pre_patch_callback: vmlinux - [ 56.614818] livepatch_callbacks_demo: pre_patch_callback: livepatch_callbacks_mod -> [MODULE_STATE_LIVE] Normal state - [ 56.615656] livepatch: 'livepatch_callbacks_demo': starting patching transition - [ 57.759070] livepatch: 'livepatch_callbacks_demo': completing patching transition - [ 57.759147] livepatch_callbacks_demo: post_patch_callback: vmlinux - [ 57.759621] livepatch_callbacks_demo: post_patch_callback: livepatch_callbacks_mod -> [MODULE_STATE_LIVE] Normal state - [ 57.760307] livepatch: 'livepatch_callbacks_demo': patching complete - -When a target module is unloaded, the livepatch is only reverted from -that klp_object (livepatch_callbacks_mod). As such, only its pre and -post-unpatch callbacks are executed when this occurs: - - % rmmod samples/livepatch/livepatch-callbacks-mod.ko - [ 58.623409] livepatch_callbacks_mod: livepatch_callbacks_mod_exit - [ 58.623903] livepatch_callbacks_demo: pre_unpatch_callback: livepatch_callbacks_mod -> [MODULE_STATE_GOING] Going away - [ 58.624658] livepatch: reverting patch 'livepatch_callbacks_demo' on unloading module 'livepatch_callbacks_mod' - [ 58.625305] livepatch_callbacks_demo: post_unpatch_callback: livepatch_callbacks_mod -> [MODULE_STATE_GOING] Going away - -When the livepatch is disabled, pre and post-unpatch callbacks are run -for the remaining klp_object, vmlinux: - - % echo 0 > /sys/kernel/livepatch/livepatch_callbacks_demo/enabled - [ 60.638420] livepatch: 'livepatch_callbacks_demo': initializing unpatching transition - [ 60.638444] livepatch_callbacks_demo: pre_unpatch_callback: vmlinux - [ 60.638996] livepatch: 'livepatch_callbacks_demo': starting unpatching transition - [ 61.727088] livepatch: 'livepatch_callbacks_demo': completing unpatching transition - [ 61.727165] livepatch_callbacks_demo: post_unpatch_callback: vmlinux - [ 61.727985] livepatch: 'livepatch_callbacks_demo': unpatching complete - - % rmmod samples/livepatch/livepatch-callbacks-demo.ko - - -Test 4 ------- - -This test is similar to the previous test, however the livepatch is -loaded first. This tests the livepatch core's module_coming and -module_going handlers: - -- load livepatch -- load target module -- unload target module -- disable livepatch -- unload livepatch - -First load the livepatch: - - % insmod samples/livepatch/livepatch-callbacks-demo.ko - [ 64.661552] livepatch: enabling patch 'livepatch_callbacks_demo' - [ 64.662147] livepatch: 'livepatch_callbacks_demo': initializing patching transition - [ 64.662175] livepatch_callbacks_demo: pre_patch_callback: vmlinux - [ 64.662850] livepatch: 'livepatch_callbacks_demo': starting patching transition - [ 65.695056] livepatch: 'livepatch_callbacks_demo': completing patching transition - [ 65.695147] livepatch_callbacks_demo: post_patch_callback: vmlinux - [ 65.695561] livepatch: 'livepatch_callbacks_demo': patching complete - -When a targeted kernel module is subsequently loaded, only its -pre/post-patch callbacks are executed: - - % insmod samples/livepatch/livepatch-callbacks-mod.ko - [ 66.669196] livepatch: applying patch 'livepatch_callbacks_demo' to loading module 'livepatch_callbacks_mod' - [ 66.669882] livepatch_callbacks_demo: pre_patch_callback: livepatch_callbacks_mod -> [MODULE_STATE_COMING] Full formed, running module_init - [ 66.670744] livepatch_callbacks_demo: post_patch_callback: livepatch_callbacks_mod -> [MODULE_STATE_COMING] Full formed, running module_init - [ 66.672873] livepatch_callbacks_mod: livepatch_callbacks_mod_init - -When the target module is unloaded, the livepatch is only reverted from -the livepatch_callbacks_mod klp_object. As such, only pre and -post-unpatch callbacks are executed when this occurs: - - % rmmod samples/livepatch/livepatch-callbacks-mod.ko - [ 68.680065] livepatch_callbacks_mod: livepatch_callbacks_mod_exit - [ 68.680688] livepatch_callbacks_demo: pre_unpatch_callback: livepatch_callbacks_mod -> [MODULE_STATE_GOING] Going away - [ 68.681452] livepatch: reverting patch 'livepatch_callbacks_demo' on unloading module 'livepatch_callbacks_mod' - [ 68.682094] livepatch_callbacks_demo: post_unpatch_callback: livepatch_callbacks_mod -> [MODULE_STATE_GOING] Going away - - % echo 0 > /sys/kernel/livepatch/livepatch_callbacks_demo/enabled - [ 70.689225] livepatch: 'livepatch_callbacks_demo': initializing unpatching transition - [ 70.689256] livepatch_callbacks_demo: pre_unpatch_callback: vmlinux - [ 70.689882] livepatch: 'livepatch_callbacks_demo': starting unpatching transition - [ 71.711080] livepatch: 'livepatch_callbacks_demo': completing unpatching transition - [ 71.711481] livepatch_callbacks_demo: post_unpatch_callback: vmlinux - [ 71.711988] livepatch: 'livepatch_callbacks_demo': unpatching complete - - % rmmod samples/livepatch/livepatch-callbacks-demo.ko - - -Test 5 ------- - -A simple test of loading a livepatch without one of its patch target -klp_objects ever loaded (livepatch_callbacks_mod): - -- load livepatch -- disable livepatch -- unload livepatch - -Load the livepatch: - - % insmod samples/livepatch/livepatch-callbacks-demo.ko - [ 74.711081] livepatch: enabling patch 'livepatch_callbacks_demo' - [ 74.711595] livepatch: 'livepatch_callbacks_demo': initializing patching transition - [ 74.711639] livepatch_callbacks_demo: pre_patch_callback: vmlinux - [ 74.712272] livepatch: 'livepatch_callbacks_demo': starting patching transition - [ 75.743137] livepatch: 'livepatch_callbacks_demo': completing patching transition - [ 75.743219] livepatch_callbacks_demo: post_patch_callback: vmlinux - [ 75.743867] livepatch: 'livepatch_callbacks_demo': patching complete - -As expected, only pre/post-(un)patch handlers are executed for vmlinux: - - % echo 0 > /sys/kernel/livepatch/livepatch_callbacks_demo/enabled - [ 76.716254] livepatch: 'livepatch_callbacks_demo': initializing unpatching transition - [ 76.716278] livepatch_callbacks_demo: pre_unpatch_callback: vmlinux - [ 76.716666] livepatch: 'livepatch_callbacks_demo': starting unpatching transition - [ 77.727089] livepatch: 'livepatch_callbacks_demo': completing unpatching transition - [ 77.727194] livepatch_callbacks_demo: post_unpatch_callback: vmlinux - [ 77.727907] livepatch: 'livepatch_callbacks_demo': unpatching complete +Other Examples +============== - % rmmod samples/livepatch/livepatch-callbacks-demo.ko - - -Test 6 ------- - -Test a scenario where a vmlinux pre-patch callback returns a non-zero -status (ie, failure): - -- load target module -- load livepatch -ENODEV -- unload target module - -First load a target module: - - % insmod samples/livepatch/livepatch-callbacks-mod.ko - [ 80.740520] livepatch_callbacks_mod: livepatch_callbacks_mod_init - -Load the livepatch module, setting its 'pre_patch_ret' value to -19 -(-ENODEV). When its vmlinux pre-patch callback executed, this status -code will propagate back to the module-loading subsystem. The result is -that the insmod command refuses to load the livepatch module: - - % insmod samples/livepatch/livepatch-callbacks-demo.ko pre_patch_ret=-19 - [ 82.747326] livepatch: enabling patch 'livepatch_callbacks_demo' - [ 82.747743] livepatch: 'livepatch_callbacks_demo': initializing patching transition - [ 82.747767] livepatch_callbacks_demo: pre_patch_callback: vmlinux - [ 82.748237] livepatch: pre-patch callback failed for object 'vmlinux' - [ 82.748637] livepatch: failed to enable patch 'livepatch_callbacks_demo' - [ 82.749059] livepatch: 'livepatch_callbacks_demo': canceling transition, going to unpatch - [ 82.749060] livepatch: 'livepatch_callbacks_demo': completing unpatching transition - [ 82.749868] livepatch: 'livepatch_callbacks_demo': unpatching complete - [ 82.765809] insmod: ERROR: could not insert module samples/livepatch/livepatch-callbacks-demo.ko: No such device - - % rmmod samples/livepatch/livepatch-callbacks-mod.ko - [ 84.774238] livepatch_callbacks_mod: livepatch_callbacks_mod_exit - - -Test 7 ------- - -Similar to the previous test, setup a livepatch such that its vmlinux -pre-patch callback returns success. However, when a targeted kernel -module is later loaded, have the livepatch return a failing status code: - -- load livepatch -- setup -ENODEV -- load target module -- disable livepatch -- unload livepatch - -Load the livepatch, notice vmlinux pre-patch callback succeeds: - - % insmod samples/livepatch/livepatch-callbacks-demo.ko - [ 86.787845] livepatch: enabling patch 'livepatch_callbacks_demo' - [ 86.788325] livepatch: 'livepatch_callbacks_demo': initializing patching transition - [ 86.788427] livepatch_callbacks_demo: pre_patch_callback: vmlinux - [ 86.788821] livepatch: 'livepatch_callbacks_demo': starting patching transition - [ 87.711069] livepatch: 'livepatch_callbacks_demo': completing patching transition - [ 87.711143] livepatch_callbacks_demo: post_patch_callback: vmlinux - [ 87.711886] livepatch: 'livepatch_callbacks_demo': patching complete - -Set a trap so subsequent pre-patch callbacks to this livepatch will -return -ENODEV: - - % echo -19 > /sys/module/livepatch_callbacks_demo/parameters/pre_patch_ret - -The livepatch pre-patch callback for subsequently loaded target modules -will return failure, so the module loader refuses to load the kernel -module. Notice that no post-patch or pre/post-unpatch callbacks are -executed for this klp_object: - - % insmod samples/livepatch/livepatch-callbacks-mod.ko - [ 90.796976] livepatch: applying patch 'livepatch_callbacks_demo' to loading module 'livepatch_callbacks_mod' - [ 90.797834] livepatch_callbacks_demo: pre_patch_callback: livepatch_callbacks_mod -> [MODULE_STATE_COMING] Full formed, running module_init - [ 90.798900] livepatch: pre-patch callback failed for object 'livepatch_callbacks_mod' - [ 90.799652] livepatch: patch 'livepatch_callbacks_demo' failed for module 'livepatch_callbacks_mod', refusing to load module 'livepatch_callbacks_mod' - [ 90.819737] insmod: ERROR: could not insert module samples/livepatch/livepatch-callbacks-mod.ko: No such device - -However, pre/post-unpatch callbacks run for the vmlinux klp_object: - - % echo 0 > /sys/kernel/livepatch/livepatch_callbacks_demo/enabled - [ 92.823547] livepatch: 'livepatch_callbacks_demo': initializing unpatching transition - [ 92.823573] livepatch_callbacks_demo: pre_unpatch_callback: vmlinux - [ 92.824331] livepatch: 'livepatch_callbacks_demo': starting unpatching transition - [ 93.727128] livepatch: 'livepatch_callbacks_demo': completing unpatching transition - [ 93.727327] livepatch_callbacks_demo: post_unpatch_callback: vmlinux - [ 93.727861] livepatch: 'livepatch_callbacks_demo': unpatching complete - - % rmmod samples/livepatch/livepatch-callbacks-demo.ko - - -Test 8 ------- - -Test loading multiple targeted kernel modules. This test-case is -mainly for comparing with the next test-case. - -- load busy target module (0s sleep), -- load livepatch -- load target module -- unload target module -- disable livepatch -- unload livepatch -- unload busy target module - - -Load a target "busy" kernel module which kicks off a worker function -that immediately exits: - - % insmod samples/livepatch/livepatch-callbacks-busymod.ko sleep_secs=0 - [ 96.910107] livepatch_callbacks_busymod: livepatch_callbacks_mod_init - [ 96.910600] livepatch_callbacks_busymod: busymod_work_func, sleeping 0 seconds ... - [ 96.913024] livepatch_callbacks_busymod: busymod_work_func exit - -Proceed with loading the livepatch and another ordinary target module, -notice that the post-patch callbacks are executed and the transition -completes quickly: - - % insmod samples/livepatch/livepatch-callbacks-demo.ko - [ 98.917892] livepatch: enabling patch 'livepatch_callbacks_demo' - [ 98.918426] livepatch: 'livepatch_callbacks_demo': initializing patching transition - [ 98.918453] livepatch_callbacks_demo: pre_patch_callback: vmlinux - [ 98.918955] livepatch_callbacks_demo: pre_patch_callback: livepatch_callbacks_busymod -> [MODULE_STATE_LIVE] Normal state - [ 98.923835] livepatch: 'livepatch_callbacks_demo': starting patching transition - [ 99.743104] livepatch: 'livepatch_callbacks_demo': completing patching transition - [ 99.743156] livepatch_callbacks_demo: post_patch_callback: vmlinux - [ 99.743679] livepatch_callbacks_demo: post_patch_callback: livepatch_callbacks_busymod -> [MODULE_STATE_LIVE] Normal state - [ 99.744616] livepatch: 'livepatch_callbacks_demo': patching complete - - % insmod samples/livepatch/livepatch-callbacks-mod.ko - [ 100.930955] livepatch: applying patch 'livepatch_callbacks_demo' to loading module 'livepatch_callbacks_mod' - [ 100.931668] livepatch_callbacks_demo: pre_patch_callback: livepatch_callbacks_mod -> [MODULE_STATE_COMING] Full formed, running module_init - [ 100.932645] livepatch_callbacks_demo: post_patch_callback: livepatch_callbacks_mod -> [MODULE_STATE_COMING] Full formed, running module_init - [ 100.934125] livepatch_callbacks_mod: livepatch_callbacks_mod_init - - % rmmod samples/livepatch/livepatch-callbacks-mod.ko - [ 102.942805] livepatch_callbacks_mod: livepatch_callbacks_mod_exit - [ 102.943640] livepatch_callbacks_demo: pre_unpatch_callback: livepatch_callbacks_mod -> [MODULE_STATE_GOING] Going away - [ 102.944585] livepatch: reverting patch 'livepatch_callbacks_demo' on unloading module 'livepatch_callbacks_mod' - [ 102.945455] livepatch_callbacks_demo: post_unpatch_callback: livepatch_callbacks_mod -> [MODULE_STATE_GOING] Going away - - % echo 0 > /sys/kernel/livepatch/livepatch_callbacks_demo/enabled - [ 104.953815] livepatch: 'livepatch_callbacks_demo': initializing unpatching transition - [ 104.953838] livepatch_callbacks_demo: pre_unpatch_callback: vmlinux - [ 104.954431] livepatch_callbacks_demo: pre_unpatch_callback: livepatch_callbacks_busymod -> [MODULE_STATE_LIVE] Normal state - [ 104.955426] livepatch: 'livepatch_callbacks_demo': starting unpatching transition - [ 106.719073] livepatch: 'livepatch_callbacks_demo': completing unpatching transition - [ 106.722633] livepatch_callbacks_demo: post_unpatch_callback: vmlinux - [ 106.723282] livepatch_callbacks_demo: post_unpatch_callback: livepatch_callbacks_busymod -> [MODULE_STATE_LIVE] Normal state - [ 106.724279] livepatch: 'livepatch_callbacks_demo': unpatching complete - - % rmmod samples/livepatch/livepatch-callbacks-demo.ko - % rmmod samples/livepatch/livepatch-callbacks-busymod.ko - [ 108.975660] livepatch_callbacks_busymod: livepatch_callbacks_mod_exit - - -Test 9 ------- - -A similar test as the previous one, but force the "busy" kernel module -to do longer work. - -The livepatching core will refuse to patch a task that is currently -executing a to-be-patched function -- the consistency model stalls the -current patch transition until this safety-check is met. Test a -scenario where one of a livepatch's target klp_objects sits on such a -function for a long time. Meanwhile, load and unload other target -kernel modules while the livepatch transition is in progress. - -- load busy target module (30s sleep) -- load livepatch -- load target module -- unload target module -- disable livepatch -- unload livepatch -- unload busy target module - - -Load the "busy" kernel module, this time make it do 30 seconds worth of -work: - - % insmod samples/livepatch/livepatch-callbacks-busymod.ko sleep_secs=30 - [ 110.993362] livepatch_callbacks_busymod: livepatch_callbacks_mod_init - [ 110.994059] livepatch_callbacks_busymod: busymod_work_func, sleeping 30 seconds ... - -Meanwhile, the livepatch is loaded. Notice that the patch transition -does not complete as the targeted "busy" module is sitting on a -to-be-patched function: - - % insmod samples/livepatch/livepatch-callbacks-demo.ko - [ 113.000309] livepatch: enabling patch 'livepatch_callbacks_demo' - [ 113.000764] livepatch: 'livepatch_callbacks_demo': initializing patching transition - [ 113.000791] livepatch_callbacks_demo: pre_patch_callback: vmlinux - [ 113.001289] livepatch_callbacks_demo: pre_patch_callback: livepatch_callbacks_busymod -> [MODULE_STATE_LIVE] Normal state - [ 113.005208] livepatch: 'livepatch_callbacks_demo': starting patching transition - -Load a second target module (this one is an ordinary idle kernel -module). Note that *no* post-patch callbacks will be executed while the -livepatch is still in transition: - - % insmod samples/livepatch/livepatch-callbacks-mod.ko - [ 115.012740] livepatch: applying patch 'livepatch_callbacks_demo' to loading module 'livepatch_callbacks_mod' - [ 115.013406] livepatch_callbacks_demo: pre_patch_callback: livepatch_callbacks_mod -> [MODULE_STATE_COMING] Full formed, running module_init - [ 115.015315] livepatch_callbacks_mod: livepatch_callbacks_mod_init - -Request an unload of the simple kernel module. The patch is still -transitioning, so its pre-unpatch callbacks are skipped: - - % rmmod samples/livepatch/livepatch-callbacks-mod.ko - [ 117.022626] livepatch_callbacks_mod: livepatch_callbacks_mod_exit - [ 117.023376] livepatch: reverting patch 'livepatch_callbacks_demo' on unloading module 'livepatch_callbacks_mod' - [ 117.024533] livepatch_callbacks_demo: post_unpatch_callback: livepatch_callbacks_mod -> [MODULE_STATE_GOING] Going away - -Finally the livepatch is disabled. Since none of the patch's -klp_object's post-patch callbacks executed, the remaining klp_object's -pre-unpatch callbacks are skipped: - - % echo 0 > /sys/kernel/livepatch/livepatch_callbacks_demo/enabled - [ 119.035408] livepatch: 'livepatch_callbacks_demo': reversing transition from patching to unpatching - [ 119.035485] livepatch: 'livepatch_callbacks_demo': starting unpatching transition - [ 119.711166] livepatch: 'livepatch_callbacks_demo': completing unpatching transition - [ 119.714179] livepatch_callbacks_demo: post_unpatch_callback: vmlinux - [ 119.714653] livepatch_callbacks_demo: post_unpatch_callback: livepatch_callbacks_busymod -> [MODULE_STATE_LIVE] Normal state - [ 119.715437] livepatch: 'livepatch_callbacks_demo': unpatching complete - - % rmmod samples/livepatch/livepatch-callbacks-demo.ko - % rmmod samples/livepatch/livepatch-callbacks-busymod.ko - [ 141.279111] livepatch_callbacks_busymod: busymod_work_func exit - [ 141.279760] livepatch_callbacks_busymod: livepatch_callbacks_mod_exit +Sample livepatch modules demonstrating the callback API can be found in +samples/livepatch/ directory. These samples were modified for use in +kselftests and can be found in the lib/livepatch directory. diff --git a/Documentation/livepatch/cumulative-patches.txt b/Documentation/livepatch/cumulative-patches.txt new file mode 100644 index 000000000000..0012808e8d44 --- /dev/null +++ b/Documentation/livepatch/cumulative-patches.txt @@ -0,0 +1,102 @@ +=================================== +Atomic Replace & Cumulative Patches +=================================== + +There might be dependencies between livepatches. If multiple patches need +to do different changes to the same function(s) then we need to define +an order in which the patches will be installed. And function implementations +from any newer livepatch must be done on top of the older ones. + +This might become a maintenance nightmare. Especially when more patches +modified the same function in different ways. + +An elegant solution comes with the feature called "Atomic Replace". It allows +creation of so called "Cumulative Patches". They include all wanted changes +from all older livepatches and completely replace them in one transition. + +Usage +----- + +The atomic replace can be enabled by setting "replace" flag in struct klp_patch, +for example: + + static struct klp_patch patch = { + .mod = THIS_MODULE, + .objs = objs, + .replace = true, + }; + +All processes are then migrated to use the code only from the new patch. +Once the transition is finished, all older patches are automatically +disabled. + +Ftrace handlers are transparently removed from functions that are no +longer modified by the new cumulative patch. + +As a result |
