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