Based on kernel version 4.16.1. Page generated on 2018-04-09 11:53 EST.
1 ====================== 2 (Un)patching Callbacks 3 ====================== 4 5 Livepatch (un)patch-callbacks provide a mechanism for livepatch modules 6 to execute callback functions when a kernel object is (un)patched. They 7 can be considered a "power feature" that extends livepatching abilities 8 to include: 9 10 - Safe updates to global data 11 12 - "Patches" to init and probe functions 13 14 - Patching otherwise unpatchable code (i.e. assembly) 15 16 In most cases, (un)patch callbacks will need to be used in conjunction 17 with memory barriers and kernel synchronization primitives, like 18 mutexes/spinlocks, or even stop_machine(), to avoid concurrency issues. 19 20 Callbacks differ from existing kernel facilities: 21 22 - Module init/exit code doesn't run when disabling and re-enabling a 23 patch. 24 25 - A module notifier can't stop a to-be-patched module from loading. 26 27 Callbacks are part of the klp_object structure and their implementation 28 is specific to that klp_object. Other livepatch objects may or may not 29 be patched, irrespective of the target klp_object's current state. 30 31 Callbacks can be registered for the following livepatch actions: 32 33 * Pre-patch - before a klp_object is patched 34 35 * Post-patch - after a klp_object has been patched and is active 36 across all tasks 37 38 * Pre-unpatch - before a klp_object is unpatched (ie, patched code is 39 active), used to clean up post-patch callback 40 resources 41 42 * Post-unpatch - after a klp_object has been patched, all code has 43 been restored and no tasks are running patched code, 44 used to cleanup pre-patch callback resources 45 46 Each callback is optional, omitting one does not preclude specifying any 47 other. However, the livepatching core executes the handlers in 48 symmetry: pre-patch callbacks have a post-unpatch counterpart and 49 post-patch callbacks have a pre-unpatch counterpart. An unpatch 50 callback will only be executed if its corresponding patch callback was 51 executed. Typical use cases pair a patch handler that acquires and 52 configures resources with an unpatch handler tears down and releases 53 those same resources. 54 55 A callback is only executed if its host klp_object is loaded. For 56 in-kernel vmlinux targets, this means that callbacks will always execute 57 when a livepatch is enabled/disabled. For patch target kernel modules, 58 callbacks will only execute if the target module is loaded. When a 59 module target is (un)loaded, its callbacks will execute only if the 60 livepatch module is enabled. 61 62 The pre-patch callback, if specified, is expected to return a status 63 code (0 for success, -ERRNO on error). An error status code indicates 64 to the livepatching core that patching of the current klp_object is not 65 safe and to stop the current patching request. (When no pre-patch 66 callback is provided, the transition is assumed to be safe.) If a 67 pre-patch callback returns failure, the kernel's module loader will: 68 69 - Refuse to load a livepatch, if the livepatch is loaded after 70 targeted code. 71 72 or: 73 74 - Refuse to load a module, if the livepatch was already successfully 75 loaded. 76 77 No post-patch, pre-unpatch, or post-unpatch callbacks will be executed 78 for a given klp_object if the object failed to patch, due to a failed 79 pre_patch callback or for any other reason. 80 81 If a patch transition is reversed, no pre-unpatch handlers will be run 82 (this follows the previously mentioned symmetry -- pre-unpatch callbacks 83 will only occur if their corresponding post-patch callback executed). 84 85 If the object did successfully patch, but the patch transition never 86 started for some reason (e.g., if another object failed to patch), 87 only the post-unpatch callback will be called. 88 89 90 Example Use-cases 91 ================= 92 93 Update global data 94 ------------------ 95 96 A pre-patch callback can be useful to update a global variable. For 97 example, 75ff39ccc1bd ("tcp: make challenge acks less predictable") 98 changes a global sysctl, as well as patches the tcp_send_challenge_ack() 99 function. 100 101 In this case, if we're being super paranoid, it might make sense to 102 patch the data *after* patching is complete with a post-patch callback, 103 so that tcp_send_challenge_ack() could first be changed to read 104 sysctl_tcp_challenge_ack_limit with READ_ONCE. 105 106 107 Support __init and probe function patches 108 ----------------------------------------- 109 110 Although __init and probe functions are not directly livepatch-able, it 111 may be possible to implement similar updates via pre/post-patch 112 callbacks. 113 114 48900cb6af42 ("virtio-net: drop NETIF_F_FRAGLIST") change the way that 115 virtnet_probe() initialized its driver's net_device features. A 116 pre/post-patch callback could iterate over all such devices, making a 117 similar change to their hw_features value. (Client functions of the 118 value may need to be updated accordingly.) 119 120 121 Test cases 122 ========== 123 124 What follows is not an exhaustive test suite of every possible livepatch 125 pre/post-(un)patch combination, but a selection that demonstrates a few 126 important concepts. Each test case uses the kernel modules located in 127 the samples/livepatch/ and assumes that no livepatches are loaded at the 128 beginning of the test. 129 130 131 Test 1 132 ------ 133 134 Test a combination of loading a kernel module and a livepatch that 135 patches a function in the first module. (Un)load the target module 136 before the livepatch module: 137 138 - load target module 139 - load livepatch 140 - disable livepatch 141 - unload target module 142 - unload livepatch 143 144 First load a target module: 145 146 % insmod samples/livepatch/livepatch-callbacks-mod.ko 147 [ 34.475708] livepatch_callbacks_mod: livepatch_callbacks_mod_init 148 149 On livepatch enable, before the livepatch transition starts, pre-patch 150 callbacks are executed for vmlinux and livepatch_callbacks_mod (those 151 klp_objects currently loaded). After klp_objects are patched according 152 to the klp_patch, their post-patch callbacks run and the transition 153 completes: 154 155 % insmod samples/livepatch/livepatch-callbacks-demo.ko 156 [ 36.503719] livepatch: enabling patch 'livepatch_callbacks_demo' 157 [ 36.504213] livepatch: 'livepatch_callbacks_demo': initializing patching transition 158 [ 36.504238] livepatch_callbacks_demo: pre_patch_callback: vmlinux 159 [ 36.504721] livepatch_callbacks_demo: pre_patch_callback: livepatch_callbacks_mod -> [MODULE_STATE_LIVE] Normal state 160 [ 36.505849] livepatch: 'livepatch_callbacks_demo': starting patching transition 161 [ 37.727133] livepatch: 'livepatch_callbacks_demo': completing patching transition 162 [ 37.727232] livepatch_callbacks_demo: post_patch_callback: vmlinux 163 [ 37.727860] livepatch_callbacks_demo: post_patch_callback: livepatch_callbacks_mod -> [MODULE_STATE_LIVE] Normal state 164 [ 37.728792] livepatch: 'livepatch_callbacks_demo': patching complete 165 166 Similarly, on livepatch disable, pre-patch callbacks run before the 167 unpatching transition starts. klp_objects are reverted, post-patch 168 callbacks execute and the transition completes: 169 170 % echo 0 > /sys/kernel/livepatch/livepatch_callbacks_demo/enabled 171 [ 38.510209] livepatch: 'livepatch_callbacks_demo': initializing unpatching transition 172 [ 38.510234] livepatch_callbacks_demo: pre_unpatch_callback: vmlinux 173 [ 38.510982] livepatch_callbacks_demo: pre_unpatch_callback: livepatch_callbacks_mod -> [MODULE_STATE_LIVE] Normal state 174 [ 38.512209] livepatch: 'livepatch_callbacks_demo': starting unpatching transition 175 [ 39.711132] livepatch: 'livepatch_callbacks_demo': completing unpatching transition 176 [ 39.711210] livepatch_callbacks_demo: post_unpatch_callback: vmlinux 177 [ 39.711779] livepatch_callbacks_demo: post_unpatch_callback: livepatch_callbacks_mod -> [MODULE_STATE_LIVE] Normal state 178 [ 39.712735] livepatch: 'livepatch_callbacks_demo': unpatching complete 179 180 % rmmod samples/livepatch/livepatch-callbacks-demo.ko 181 % rmmod samples/livepatch/livepatch-callbacks-mod.ko 182 [ 42.534183] livepatch_callbacks_mod: livepatch_callbacks_mod_exit 183 184 185 Test 2 186 ------ 187 188 This test is similar to the previous test, but (un)load the livepatch 189 module before the target kernel module. This tests the livepatch core's 190 module_coming handler: 191 192 - load livepatch 193 - load target module 194 - disable livepatch 195 - unload livepatch 196 - unload target module 197 198 199 On livepatch enable, only pre/post-patch callbacks are executed for 200 currently loaded klp_objects, in this case, vmlinux: 201 202 % insmod samples/livepatch/livepatch-callbacks-demo.ko 203 [ 44.553328] livepatch: enabling patch 'livepatch_callbacks_demo' 204 [ 44.553997] livepatch: 'livepatch_callbacks_demo': initializing patching transition 205 [ 44.554049] livepatch_callbacks_demo: pre_patch_callback: vmlinux 206 [ 44.554845] livepatch: 'livepatch_callbacks_demo': starting patching transition 207 [ 45.727128] livepatch: 'livepatch_callbacks_demo': completing patching transition 208 [ 45.727212] livepatch_callbacks_demo: post_patch_callback: vmlinux 209 [ 45.727961] livepatch: 'livepatch_callbacks_demo': patching complete 210 211 When a targeted module is subsequently loaded, only its pre/post-patch 212 callbacks are executed: 213 214 % insmod samples/livepatch/livepatch-callbacks-mod.ko 215 [ 46.560845] livepatch: applying patch 'livepatch_callbacks_demo' to loading module 'livepatch_callbacks_mod' 216 [ 46.561988] livepatch_callbacks_demo: pre_patch_callback: livepatch_callbacks_mod -> [MODULE_STATE_COMING] Full formed, running module_init 217 [ 46.563452] livepatch_callbacks_demo: post_patch_callback: livepatch_callbacks_mod -> [MODULE_STATE_COMING] Full formed, running module_init 218 [ 46.565495] livepatch_callbacks_mod: livepatch_callbacks_mod_init 219 220 On livepatch disable, all currently loaded klp_objects' (vmlinux and 221 livepatch_callbacks_mod) pre/post-unpatch callbacks are executed: 222 223 % echo 0 > /sys/kernel/livepatch/livepatch_callbacks_demo/enabled 224 [ 48.568885] livepatch: 'livepatch_callbacks_demo': initializing unpatching transition 225 [ 48.568910] livepatch_callbacks_demo: pre_unpatch_callback: vmlinux 226 [ 48.569441] livepatch_callbacks_demo: pre_unpatch_callback: livepatch_callbacks_mod -> [MODULE_STATE_LIVE] Normal state 227 [ 48.570502] livepatch: 'livepatch_callbacks_demo': starting unpatching transition 228 [ 49.759091] livepatch: 'livepatch_callbacks_demo': completing unpatching transition 229 [ 49.759171] livepatch_callbacks_demo: post_unpatch_callback: vmlinux 230 [ 49.759742] livepatch_callbacks_demo: post_unpatch_callback: livepatch_callbacks_mod -> [MODULE_STATE_LIVE] Normal state 231 [ 49.760690] livepatch: 'livepatch_callbacks_demo': unpatching complete 232 233 % rmmod samples/livepatch/livepatch-callbacks-demo.ko 234 % rmmod samples/livepatch/livepatch-callbacks-mod.ko 235 [ 52.592283] livepatch_callbacks_mod: livepatch_callbacks_mod_exit 236 237 238 Test 3 239 ------ 240 241 Test loading the livepatch after a targeted kernel module, then unload 242 the kernel module before disabling the livepatch. This tests the 243 livepatch core's module_going handler: 244 245 - load target module 246 - load livepatch 247 - unload target module 248 - disable livepatch 249 - unload livepatch 250 251 First load a target module, then the livepatch: 252 253 % insmod samples/livepatch/livepatch-callbacks-mod.ko 254 [ 54.607948] livepatch_callbacks_mod: livepatch_callbacks_mod_init 255 256 % insmod samples/livepatch/livepatch-callbacks-demo.ko 257 [ 56.613919] livepatch: enabling patch 'livepatch_callbacks_demo' 258 [ 56.614411] livepatch: 'livepatch_callbacks_demo': initializing patching transition 259 [ 56.614436] livepatch_callbacks_demo: pre_patch_callback: vmlinux 260 [ 56.614818] livepatch_callbacks_demo: pre_patch_callback: livepatch_callbacks_mod -> [MODULE_STATE_LIVE] Normal state 261 [ 56.615656] livepatch: 'livepatch_callbacks_demo': starting patching transition 262 [ 57.759070] livepatch: 'livepatch_callbacks_demo': completing patching transition 263 [ 57.759147] livepatch_callbacks_demo: post_patch_callback: vmlinux 264 [ 57.759621] livepatch_callbacks_demo: post_patch_callback: livepatch_callbacks_mod -> [MODULE_STATE_LIVE] Normal state 265 [ 57.760307] livepatch: 'livepatch_callbacks_demo': patching complete 266 267 When a target module is unloaded, the livepatch is only reverted from 268 that klp_object (livepatch_callbacks_mod). As such, only its pre and 269 post-unpatch callbacks are executed when this occurs: 270 271 % rmmod samples/livepatch/livepatch-callbacks-mod.ko 272 [ 58.623409] livepatch_callbacks_mod: livepatch_callbacks_mod_exit 273 [ 58.623903] livepatch_callbacks_demo: pre_unpatch_callback: livepatch_callbacks_mod -> [MODULE_STATE_GOING] Going away 274 [ 58.624658] livepatch: reverting patch 'livepatch_callbacks_demo' on unloading module 'livepatch_callbacks_mod' 275 [ 58.625305] livepatch_callbacks_demo: post_unpatch_callback: livepatch_callbacks_mod -> [MODULE_STATE_GOING] Going away 276 277 When the livepatch is disabled, pre and post-unpatch callbacks are run 278 for the remaining klp_object, vmlinux: 279 280 % echo 0 > /sys/kernel/livepatch/livepatch_callbacks_demo/enabled 281 [ 60.638420] livepatch: 'livepatch_callbacks_demo': initializing unpatching transition 282 [ 60.638444] livepatch_callbacks_demo: pre_unpatch_callback: vmlinux 283 [ 60.638996] livepatch: 'livepatch_callbacks_demo': starting unpatching transition 284 [ 61.727088] livepatch: 'livepatch_callbacks_demo': completing unpatching transition 285 [ 61.727165] livepatch_callbacks_demo: post_unpatch_callback: vmlinux 286 [ 61.727985] livepatch: 'livepatch_callbacks_demo': unpatching complete 287 288 % rmmod samples/livepatch/livepatch-callbacks-demo.ko 289 290 291 Test 4 292 ------ 293 294 This test is similar to the previous test, however the livepatch is 295 loaded first. This tests the livepatch core's module_coming and 296 module_going handlers: 297 298 - load livepatch 299 - load target module 300 - unload target module 301 - disable livepatch 302 - unload livepatch 303 304 First load the livepatch: 305 306 % insmod samples/livepatch/livepatch-callbacks-demo.ko 307 [ 64.661552] livepatch: enabling patch 'livepatch_callbacks_demo' 308 [ 64.662147] livepatch: 'livepatch_callbacks_demo': initializing patching transition 309 [ 64.662175] livepatch_callbacks_demo: pre_patch_callback: vmlinux 310 [ 64.662850] livepatch: 'livepatch_callbacks_demo': starting patching transition 311 [ 65.695056] livepatch: 'livepatch_callbacks_demo': completing patching transition 312 [ 65.695147] livepatch_callbacks_demo: post_patch_callback: vmlinux 313 [ 65.695561] livepatch: 'livepatch_callbacks_demo': patching complete 314 315 When a targeted kernel module is subsequently loaded, only its 316 pre/post-patch callbacks are executed: 317 318 % insmod samples/livepatch/livepatch-callbacks-mod.ko 319 [ 66.669196] livepatch: applying patch 'livepatch_callbacks_demo' to loading module 'livepatch_callbacks_mod' 320 [ 66.669882] livepatch_callbacks_demo: pre_patch_callback: livepatch_callbacks_mod -> [MODULE_STATE_COMING] Full formed, running module_init 321 [ 66.670744] livepatch_callbacks_demo: post_patch_callback: livepatch_callbacks_mod -> [MODULE_STATE_COMING] Full formed, running module_init 322 [ 66.672873] livepatch_callbacks_mod: livepatch_callbacks_mod_init 323 324 When the target module is unloaded, the livepatch is only reverted from 325 the livepatch_callbacks_mod klp_object. As such, only pre and 326 post-unpatch callbacks are executed when this occurs: 327 328 % rmmod samples/livepatch/livepatch-callbacks-mod.ko 329 [ 68.680065] livepatch_callbacks_mod: livepatch_callbacks_mod_exit 330 [ 68.680688] livepatch_callbacks_demo: pre_unpatch_callback: livepatch_callbacks_mod -> [MODULE_STATE_GOING] Going away 331 [ 68.681452] livepatch: reverting patch 'livepatch_callbacks_demo' on unloading module 'livepatch_callbacks_mod' 332 [ 68.682094] livepatch_callbacks_demo: post_unpatch_callback: livepatch_callbacks_mod -> [MODULE_STATE_GOING] Going away 333 334 % echo 0 > /sys/kernel/livepatch/livepatch_callbacks_demo/enabled 335 [ 70.689225] livepatch: 'livepatch_callbacks_demo': initializing unpatching transition 336 [ 70.689256] livepatch_callbacks_demo: pre_unpatch_callback: vmlinux 337 [ 70.689882] livepatch: 'livepatch_callbacks_demo': starting unpatching transition 338 [ 71.711080] livepatch: 'livepatch_callbacks_demo': completing unpatching transition 339 [ 71.711481] livepatch_callbacks_demo: post_unpatch_callback: vmlinux 340 [ 71.711988] livepatch: 'livepatch_callbacks_demo': unpatching complete 341 342 % rmmod samples/livepatch/livepatch-callbacks-demo.ko 343 344 345 Test 5 346 ------ 347 348 A simple test of loading a livepatch without one of its patch target 349 klp_objects ever loaded (livepatch_callbacks_mod): 350 351 - load livepatch 352 - disable livepatch 353 - unload livepatch 354 355 Load the livepatch: 356 357 % insmod samples/livepatch/livepatch-callbacks-demo.ko 358 [ 74.711081] livepatch: enabling patch 'livepatch_callbacks_demo' 359 [ 74.711595] livepatch: 'livepatch_callbacks_demo': initializing patching transition 360 [ 74.711639] livepatch_callbacks_demo: pre_patch_callback: vmlinux 361 [ 74.712272] livepatch: 'livepatch_callbacks_demo': starting patching transition 362 [ 75.743137] livepatch: 'livepatch_callbacks_demo': completing patching transition 363 [ 75.743219] livepatch_callbacks_demo: post_patch_callback: vmlinux 364 [ 75.743867] livepatch: 'livepatch_callbacks_demo': patching complete 365 366 As expected, only pre/post-(un)patch handlers are executed for vmlinux: 367 368 % echo 0 > /sys/kernel/livepatch/livepatch_callbacks_demo/enabled 369 [ 76.716254] livepatch: 'livepatch_callbacks_demo': initializing unpatching transition 370 [ 76.716278] livepatch_callbacks_demo: pre_unpatch_callback: vmlinux 371 [ 76.716666] livepatch: 'livepatch_callbacks_demo': starting unpatching transition 372 [ 77.727089] livepatch: 'livepatch_callbacks_demo': completing unpatching transition 373 [ 77.727194] livepatch_callbacks_demo: post_unpatch_callback: vmlinux 374 [ 77.727907] livepatch: 'livepatch_callbacks_demo': unpatching complete 375 376 % rmmod samples/livepatch/livepatch-callbacks-demo.ko 377 378 379 Test 6 380 ------ 381 382 Test a scenario where a vmlinux pre-patch callback returns a non-zero 383 status (ie, failure): 384 385 - load target module 386 - load livepatch -ENODEV 387 - unload target module 388 389 First load a target module: 390 391 % insmod samples/livepatch/livepatch-callbacks-mod.ko 392 [ 80.740520] livepatch_callbacks_mod: livepatch_callbacks_mod_init 393 394 Load the livepatch module, setting its 'pre_patch_ret' value to -19 395 (-ENODEV). When its vmlinux pre-patch callback executed, this status 396 code will propagate back to the module-loading subsystem. The result is 397 that the insmod command refuses to load the livepatch module: 398 399 % insmod samples/livepatch/livepatch-callbacks-demo.ko pre_patch_ret=-19 400 [ 82.747326] livepatch: enabling patch 'livepatch_callbacks_demo' 401 [ 82.747743] livepatch: 'livepatch_callbacks_demo': initializing patching transition 402 [ 82.747767] livepatch_callbacks_demo: pre_patch_callback: vmlinux 403 [ 82.748237] livepatch: pre-patch callback failed for object 'vmlinux' 404 [ 82.748637] livepatch: failed to enable patch 'livepatch_callbacks_demo' 405 [ 82.749059] livepatch: 'livepatch_callbacks_demo': canceling transition, going to unpatch 406 [ 82.749060] livepatch: 'livepatch_callbacks_demo': completing unpatching transition 407 [ 82.749868] livepatch: 'livepatch_callbacks_demo': unpatching complete 408 [ 82.765809] insmod: ERROR: could not insert module samples/livepatch/livepatch-callbacks-demo.ko: No such device 409 410 % rmmod samples/livepatch/livepatch-callbacks-mod.ko 411 [ 84.774238] livepatch_callbacks_mod: livepatch_callbacks_mod_exit 412 413 414 Test 7 415 ------ 416 417 Similar to the previous test, setup a livepatch such that its vmlinux 418 pre-patch callback returns success. However, when a targeted kernel 419 module is later loaded, have the livepatch return a failing status code: 420 421 - load livepatch 422 - setup -ENODEV 423 - load target module 424 - disable livepatch 425 - unload livepatch 426 427 Load the livepatch, notice vmlinux pre-patch callback succeeds: 428 429 % insmod samples/livepatch/livepatch-callbacks-demo.ko 430 [ 86.787845] livepatch: enabling patch 'livepatch_callbacks_demo' 431 [ 86.788325] livepatch: 'livepatch_callbacks_demo': initializing patching transition 432 [ 86.788427] livepatch_callbacks_demo: pre_patch_callback: vmlinux 433 [ 86.788821] livepatch: 'livepatch_callbacks_demo': starting patching transition 434 [ 87.711069] livepatch: 'livepatch_callbacks_demo': completing patching transition 435 [ 87.711143] livepatch_callbacks_demo: post_patch_callback: vmlinux 436 [ 87.711886] livepatch: 'livepatch_callbacks_demo': patching complete 437 438 Set a trap so subsequent pre-patch callbacks to this livepatch will 439 return -ENODEV: 440 441 % echo -19 > /sys/module/livepatch_callbacks_demo/parameters/pre_patch_ret 442 443 The livepatch pre-patch callback for subsequently loaded target modules 444 will return failure, so the module loader refuses to load the kernel 445 module. Notice that no post-patch or pre/post-unpatch callbacks are 446 executed for this klp_object: 447 448 % insmod samples/livepatch/livepatch-callbacks-mod.ko 449 [ 90.796976] livepatch: applying patch 'livepatch_callbacks_demo' to loading module 'livepatch_callbacks_mod' 450 [ 90.797834] livepatch_callbacks_demo: pre_patch_callback: livepatch_callbacks_mod -> [MODULE_STATE_COMING] Full formed, running module_init 451 [ 90.798900] livepatch: pre-patch callback failed for object 'livepatch_callbacks_mod' 452 [ 90.799652] livepatch: patch 'livepatch_callbacks_demo' failed for module 'livepatch_callbacks_mod', refusing to load module 'livepatch_callbacks_mod' 453 [ 90.819737] insmod: ERROR: could not insert module samples/livepatch/livepatch-callbacks-mod.ko: No such device 454 455 However, pre/post-unpatch callbacks run for the vmlinux klp_object: 456 457 % echo 0 > /sys/kernel/livepatch/livepatch_callbacks_demo/enabled 458 [ 92.823547] livepatch: 'livepatch_callbacks_demo': initializing unpatching transition 459 [ 92.823573] livepatch_callbacks_demo: pre_unpatch_callback: vmlinux 460 [ 92.824331] livepatch: 'livepatch_callbacks_demo': starting unpatching transition 461 [ 93.727128] livepatch: 'livepatch_callbacks_demo': completing unpatching transition 462 [ 93.727327] livepatch_callbacks_demo: post_unpatch_callback: vmlinux 463 [ 93.727861] livepatch: 'livepatch_callbacks_demo': unpatching complete 464 465 % rmmod samples/livepatch/livepatch-callbacks-demo.ko 466 467 468 Test 8 469 ------ 470 471 Test loading multiple targeted kernel modules. This test-case is 472 mainly for comparing with the next test-case. 473 474 - load busy target module (0s sleep), 475 - load livepatch 476 - load target module 477 - unload target module 478 - disable livepatch 479 - unload livepatch 480 - unload busy target module 481 482 483 Load a target "busy" kernel module which kicks off a worker function 484 that immediately exits: 485 486 % insmod samples/livepatch/livepatch-callbacks-busymod.ko sleep_secs=0 487 [ 96.910107] livepatch_callbacks_busymod: livepatch_callbacks_mod_init 488 [ 96.910600] livepatch_callbacks_busymod: busymod_work_func, sleeping 0 seconds ... 489 [ 96.913024] livepatch_callbacks_busymod: busymod_work_func exit 490 491 Proceed with loading the livepatch and another ordinary target module, 492 notice that the post-patch callbacks are executed and the transition 493 completes quickly: 494 495 % insmod samples/livepatch/livepatch-callbacks-demo.ko 496 [ 98.917892] livepatch: enabling patch 'livepatch_callbacks_demo' 497 [ 98.918426] livepatch: 'livepatch_callbacks_demo': initializing patching transition 498 [ 98.918453] livepatch_callbacks_demo: pre_patch_callback: vmlinux 499 [ 98.918955] livepatch_callbacks_demo: pre_patch_callback: livepatch_callbacks_busymod -> [MODULE_STATE_LIVE] Normal state 500 [ 98.923835] livepatch: 'livepatch_callbacks_demo': starting patching transition 501 [ 99.743104] livepatch: 'livepatch_callbacks_demo': completing patching transition 502 [ 99.743156] livepatch_callbacks_demo: post_patch_callback: vmlinux 503 [ 99.743679] livepatch_callbacks_demo: post_patch_callback: livepatch_callbacks_busymod -> [MODULE_STATE_LIVE] Normal state 504 [ 99.744616] livepatch: 'livepatch_callbacks_demo': patching complete 505 506 % insmod samples/livepatch/livepatch-callbacks-mod.ko 507 [ 100.930955] livepatch: applying patch 'livepatch_callbacks_demo' to loading module 'livepatch_callbacks_mod' 508 [ 100.931668] livepatch_callbacks_demo: pre_patch_callback: livepatch_callbacks_mod -> [MODULE_STATE_COMING] Full formed, running module_init 509 [ 100.932645] livepatch_callbacks_demo: post_patch_callback: livepatch_callbacks_mod -> [MODULE_STATE_COMING] Full formed, running module_init 510 [ 100.934125] livepatch_callbacks_mod: livepatch_callbacks_mod_init 511 512 % rmmod samples/livepatch/livepatch-callbacks-mod.ko 513 [ 102.942805] livepatch_callbacks_mod: livepatch_callbacks_mod_exit 514 [ 102.943640] livepatch_callbacks_demo: pre_unpatch_callback: livepatch_callbacks_mod -> [MODULE_STATE_GOING] Going away 515 [ 102.944585] livepatch: reverting patch 'livepatch_callbacks_demo' on unloading module 'livepatch_callbacks_mod' 516 [ 102.945455] livepatch_callbacks_demo: post_unpatch_callback: livepatch_callbacks_mod -> [MODULE_STATE_GOING] Going away 517 518 % echo 0 > /sys/kernel/livepatch/livepatch_callbacks_demo/enabled 519 [ 104.953815] livepatch: 'livepatch_callbacks_demo': initializing unpatching transition 520 [ 104.953838] livepatch_callbacks_demo: pre_unpatch_callback: vmlinux 521 [ 104.954431] livepatch_callbacks_demo: pre_unpatch_callback: livepatch_callbacks_busymod -> [MODULE_STATE_LIVE] Normal state 522 [ 104.955426] livepatch: 'livepatch_callbacks_demo': starting unpatching transition 523 [ 106.719073] livepatch: 'livepatch_callbacks_demo': completing unpatching transition 524 [ 106.722633] livepatch_callbacks_demo: post_unpatch_callback: vmlinux 525 [ 106.723282] livepatch_callbacks_demo: post_unpatch_callback: livepatch_callbacks_busymod -> [MODULE_STATE_LIVE] Normal state 526 [ 106.724279] livepatch: 'livepatch_callbacks_demo': unpatching complete 527 528 % rmmod samples/livepatch/livepatch-callbacks-demo.ko 529 % rmmod samples/livepatch/livepatch-callbacks-busymod.ko 530 [ 108.975660] livepatch_callbacks_busymod: livepatch_callbacks_mod_exit 531 532 533 Test 9 534 ------ 535 536 A similar test as the previous one, but force the "busy" kernel module 537 to do longer work. 538 539 The livepatching core will refuse to patch a task that is currently 540 executing a to-be-patched function -- the consistency model stalls the 541 current patch transition until this safety-check is met. Test a 542 scenario where one of a livepatch's target klp_objects sits on such a 543 function for a long time. Meanwhile, load and unload other target 544 kernel modules while the livepatch transition is in progress. 545 546 - load busy target module (30s sleep) 547 - load livepatch 548 - load target module 549 - unload target module 550 - disable livepatch 551 - unload livepatch 552 - unload busy target module 553 554 555 Load the "busy" kernel module, this time make it do 30 seconds worth of 556 work: 557 558 % insmod samples/livepatch/livepatch-callbacks-busymod.ko sleep_secs=30 559 [ 110.993362] livepatch_callbacks_busymod: livepatch_callbacks_mod_init 560 [ 110.994059] livepatch_callbacks_busymod: busymod_work_func, sleeping 30 seconds ... 561 562 Meanwhile, the livepatch is loaded. Notice that the patch transition 563 does not complete as the targeted "busy" module is sitting on a 564 to-be-patched function: 565 566 % insmod samples/livepatch/livepatch-callbacks-demo.ko 567 [ 113.000309] livepatch: enabling patch 'livepatch_callbacks_demo' 568 [ 113.000764] livepatch: 'livepatch_callbacks_demo': initializing patching transition 569 [ 113.000791] livepatch_callbacks_demo: pre_patch_callback: vmlinux 570 [ 113.001289] livepatch_callbacks_demo: pre_patch_callback: livepatch_callbacks_busymod -> [MODULE_STATE_LIVE] Normal state 571 [ 113.005208] livepatch: 'livepatch_callbacks_demo': starting patching transition 572 573 Load a second target module (this one is an ordinary idle kernel 574 module). Note that *no* post-patch callbacks will be executed while the 575 livepatch is still in transition: 576 577 % insmod samples/livepatch/livepatch-callbacks-mod.ko 578 [ 115.012740] livepatch: applying patch 'livepatch_callbacks_demo' to loading module 'livepatch_callbacks_mod' 579 [ 115.013406] livepatch_callbacks_demo: pre_patch_callback: livepatch_callbacks_mod -> [MODULE_STATE_COMING] Full formed, running module_init 580 [ 115.015315] livepatch_callbacks_mod: livepatch_callbacks_mod_init 581 582 Request an unload of the simple kernel module. The patch is still 583 transitioning, so its pre-unpatch callbacks are skipped: 584 585 % rmmod samples/livepatch/livepatch-callbacks-mod.ko 586 [ 117.022626] livepatch_callbacks_mod: livepatch_callbacks_mod_exit 587 [ 117.023376] livepatch: reverting patch 'livepatch_callbacks_demo' on unloading module 'livepatch_callbacks_mod' 588 [ 117.024533] livepatch_callbacks_demo: post_unpatch_callback: livepatch_callbacks_mod -> [MODULE_STATE_GOING] Going away 589 590 Finally the livepatch is disabled. Since none of the patch's 591 klp_object's post-patch callbacks executed, the remaining klp_object's 592 pre-unpatch callbacks are skipped: 593 594 % echo 0 > /sys/kernel/livepatch/livepatch_callbacks_demo/enabled 595 [ 119.035408] livepatch: 'livepatch_callbacks_demo': reversing transition from patching to unpatching 596 [ 119.035485] livepatch: 'livepatch_callbacks_demo': starting unpatching transition 597 [ 119.711166] livepatch: 'livepatch_callbacks_demo': completing unpatching transition 598 [ 119.714179] livepatch_callbacks_demo: post_unpatch_callback: vmlinux 599 [ 119.714653] livepatch_callbacks_demo: post_unpatch_callback: livepatch_callbacks_busymod -> [MODULE_STATE_LIVE] Normal state 600 [ 119.715437] livepatch: 'livepatch_callbacks_demo': unpatching complete 601 602 % rmmod samples/livepatch/livepatch-callbacks-demo.ko 603 % rmmod samples/livepatch/livepatch-callbacks-busymod.ko 604 [ 141.279111] livepatch_callbacks_busymod: busymod_work_func exit 605 [ 141.279760] livepatch_callbacks_busymod: livepatch_callbacks_mod_exit