#!/bin/bash # SPDX-License-Identifier: GPL-2.0 # Copyright (C) 2018 Joe Lawrence . $(dirname $0)/functions.sh MOD_LIVEPATCH1=test_klp_livepatch MOD_LIVEPATCH2=test_klp_syscall MOD_LIVEPATCH3=test_klp_callbacks_demo MOD_REPLACE=test_klp_atomic_replace MOD_TARGET=test_klp_mod_target MOD_TARGET_PATCH=test_klp_mod_patch setup_config # - load a livepatch that modifies the output from /proc/cmdline and # verify correct behavior # - unload the livepatch and make sure the patch was removed start_test "basic function patching" load_lp $MOD_LIVEPATCH1 if [[ "$(cat /proc/cmdline)" != "$MOD_LIVEPATCH1: this has been live patched" ]] ; then echo -e "FAIL\n\n" die "livepatch kselftest(s) failed" fi disable_lp $MOD_LIVEPATCH1 unload_lp $MOD_LIVEPATCH1 if [[ "$(cat /proc/cmdline)" == "$MOD_LIVEPATCH1: this has been live patched" ]] ; then echo -e "FAIL\n\n" die "livepatch kselftest(s) failed" fi check_result "% insmod test_modules/$MOD_LIVEPATCH1.ko livepatch: enabling patch '$MOD_LIVEPATCH1' livepatch: '$MOD_LIVEPATCH1': initializing patching transition livepatch: '$MOD_LIVEPATCH1': starting patching transition livepatch: '$MOD_LIVEPATCH1': completing patching transition livepatch: '$MOD_LIVEPATCH1': patching complete % echo 0 > $SYSFS_KLP_DIR/$MOD_LIVEPATCH1/enabled livepatch: '$MOD_LIVEPATCH1': initializing unpatching transition livepatch: '$MOD_LIVEPATCH1': starting unpatching transition livepatch: '$MOD_LIVEPATCH1': completing unpatching transition livepatch: '$MOD_LIVEPATCH1': unpatching complete % rmmod $MOD_LIVEPATCH1" # - load a livepatch that modifies the output from /proc/cmdline and # verify correct behavior # - load another livepatch and verify that both livepatches are active # - unload the second livepatch and verify that the first is still active # - unload the first livepatch and verify none are active start_test "multiple livepatches" load_lp $MOD_LIVEPATCH1 grep 'live patched' /proc/cmdline > /dev/kmsg grep 'live patched' /proc/meminfo > /dev/kmsg load_lp $MOD_REPLACE replace=0 grep 'live patched' /proc/cmdline > /dev/kmsg grep 'live patched' /proc/meminfo > /dev/kmsg disable_lp $MOD_REPLACE unload_lp $MOD_REPLACE grep 'live patched' /proc/cmdline > /dev/kmsg grep 'live patched' /proc/meminfo > /dev/kmsg disable_lp $MOD_LIVEPATCH1 unload_lp $MOD_LIVEPATCH1 grep 'live patched' /proc/cmdline > /dev/kmsg grep 'live patched' /proc/meminfo > /dev/kmsg check_result "% insmod test_modules/$MOD_LIVEPATCH1.ko livepatch: enabling patch '$MOD_LIVEPATCH1' livepatch: '$MOD_LIVEPATCH1': initializing patching transition livepatch: '$MOD_LIVEPATCH1': starting patching transition livepatch: '$MOD_LIVEPATCH1': completing patching transition livepatch: '$MOD_LIVEPATCH1': patching complete $MOD_LIVEPATCH1: this has been live patched % insmod test_modules/$MOD_REPLACE.ko replace=0 livepatch: enabling patch '$MOD_REPLACE' livepatch: '$MOD_REPLACE': initializing patching transition livepatch: '$MOD_REPLACE': starting patching transition livepatch: '$MOD_REPLACE': completing patching transition livepatch: '$MOD_REPLACE': patching complete $MOD_LIVEPATCH1: this has been live patched $MOD_REPLACE: this has been live patched % echo 0 > $SYSFS_KLP_DIR/$MOD_REPLACE/enabled livepatch: '$MOD_REPLACE': initializing unpatching transition livepatch: '$MOD_REPLACE': starting unpatching transition livepatch: '$MOD_REPLACE': completing unpatching transition livepatch: '$MOD_REPLACE': unpatching complete % rmmod $MOD_REPLACE $MOD_LIVEPATCH1: this has been live patched % echo 0 > $SYSFS_KLP_DIR/$MOD_LIVEPATCH1/enabled livepatch: '$MOD_LIVEPATCH1': initializing unpatching transition livepatch: '$MOD_LIVEPATCH1': starting unpatching transition livepatch: '$MOD_LIVEPATCH1': completing unpatching transition livepatch: '$MOD_LIVEPATCH1': unpatching complete % rmmod $MOD_LIVEPATCH1" # - load a livepatch that modifies the output from /proc/cmdline and # verify correct behavior # - load two additional livepatches and check the number of livepatch modules # applied # - load an atomic replace livepatch and check that the other three modules were # disabled # - remove all livepatches besides the atomic replace one and verify that the # atomic replace livepatch is still active # - remove the atomic replace livepatch and verify that none are active start_test "atomic replace livepatch" load_lp $MOD_LIVEPATCH1 grep 'live patched' /proc/cmdline > /dev/kmsg grep 'live patched' /proc/meminfo > /dev/kmsg for mod in $MOD_LIVEPATCH2 $MOD_LIVEPATCH3; do load_lp "$mod" done mods=($SYSFS_KLP_DIR/*) nmods=${#mods[@]} if [ "$nmods" -ne 3 ]; then die "Expecting three modules listed, found $nmods" fi load_lp $MOD_REPLACE replace=1 grep 'live patched' /proc/cmdline > /dev/kmsg grep 'live patched' /proc/meminfo > /dev/kmsg loop_until 'mods=($SYSFS_KLP_DIR/*); nmods=${#mods[@]}; [[ "$nmods" -eq 1 ]]' || die "Expecting only one moduled listed, found $nmods" # These modules were disabled by the atomic replace for mod in $MOD_LIVEPATCH3 $MOD_LIVEPATCH2 $MOD_LIVEPATCH1; do unload_lp "$mod" done grep 'live patched' /proc/cmdline > /dev/kmsg grep 'live patched' /proc/meminfo > /dev/kmsg disable_lp $MOD_REPLACE unload_lp $MOD_REPLACE grep 'live patched' /proc/cmdline > /dev/kmsg grep 'live patched' /proc/meminfo > /dev/kmsg check_result "% insmod test_modules/$MOD_LIVEPATCH1.ko livepatch: enabling patch '$MOD_LIVEPATCH1' livepatch: '$MOD_LIVEPATCH1': initializing patching transition livepatch: '$MOD_LIVEPATCH1': starting patching transition livepatch: '$MOD_LIVEPATCH1': completing patching transition livepatch: '$MOD_LIVEPATCH1': patching complete $MOD_LIVEPATCH1: this has been live patched % insmod test_modules/$MOD_LIVEPATCH2.ko livepatch: enabling patch '$MOD_LIVEPATCH2' livepatch: '$MOD_LIVEPATCH2': initializing patching transition livepatch: '$MOD_LIVEPATCH2': starting patching transition livepatch: '$MOD_LIVEPATCH2': completing patching transition livepatch: '$MOD_LIVEPATCH2': patching complete % insmod test_modules/$MOD_LIVEPATCH3.ko livepatch: enabling patch '$MOD_LIVEPATCH3' livepatch: '$MOD_LIVEPATCH3': initializing patching transition $MOD_LIVEPATCH3: pre_patch_callback: vmlinux livepatch: '$MOD_LIVEPATCH3': starting patching transition livepatch: '$MOD_LIVEPATCH3': completing patching transition $MOD_LIVEPATCH3: post_patch_callback: vmlinux livepatch: '$MOD_LIVEPATCH3': patching complete % insmod test_modules/$MOD_REPLACE.ko replace=1 livepatch: enabling patch '$MOD_REPLACE' livepatch: '$MOD_REPLACE': initializing patching transition livepatch: '$MOD_REPLACE': starting patching transition livepatch: '$MOD_REPLACE': completing patching transition livepatch: '$MOD_REPLACE': patching complete $MOD_REPLACE: this has been live patched % rmmod $MOD_LIVEPATCH3 % rmmod $MOD_LIVEPATCH2 % rmmod $MOD_LIVEPATCH1 $MOD_REPLACE: this has been live patched % echo 0 > $SYSFS_KLP_DIR/$MOD_REPLACE/enabled livepatch: '$MOD_REPLACE': initializing unpatching transition livepatch: '$MOD_REPLACE': starting unpatching transition livepatch: '$MOD_REPLACE': completing unpatching transition livepatch: '$MOD_REPLACE': unpatching complete % rmmod $MOD_REPLACE" # - load a target module that provides /proc/test_klp_mod_target with # original output # - load a livepatch that patches the target module's show function # - verify the proc entry returns livepatched output # - disable and unload the livepatch # - verify the proc entry returns original output again # - unload the target module start_test "module function patching" load_mod $MOD_TARGET if [[ "$(cat /proc/$MOD_TARGET)" != "$MOD_TARGET: original output" ]] ; then echo -e "FAIL\n\n" die "livepatch kselftest(s) failed" fi load_lp $MOD_TARGET_PATCH if [[ "$(cat /proc/$MOD_TARGET)" != "$MOD_TARGET_PATCH: this has been live patched" ]] ; then echo -e "FAIL\n\n" die "livepatch kselftest(s) failed" fi disable_lp $MOD_TARGET_PATCH unload_lp $MOD_TARGET_PATCH if [[ "$(cat /proc/$MOD_TARGET)" != "$MOD_TARGET: original output" ]] ; then echo -e "FAIL\n\n" die "livepatch kselftest(s) failed" fi unload_mod $MOD_TARGET check_result "% insmod test_modules/$MOD_TARGET.ko $MOD_TARGET: test_klp_mod_target_init % insmod test_modules/$MOD_TARGET_PATCH.ko livepatch: enabling patch '$MOD_TARGET_PATCH' livepatch: '$MOD_TARGET_PATCH': initializing patching transition livepatch: '$MOD_TARGET_PATCH': starting patching transition livepatch: '$MOD_TARGET_PATCH': completing patching transition livepatch: '$MOD_TARGET_PATCH': patching complete % echo 0 > $SYSFS_KLP_DIR/$MOD_TARGET_PATCH/enabled livepatch: '$MOD_TARGET_PATCH': initializing unpatching transition livepatch: '$MOD_TARGET_PATCH': starting unpatching transition livepatch: '$MOD_TARGET_PATCH': completing unpatching transition livepatch: '$MOD_TARGET_PATCH': unpatching complete % rmmod $MOD_TARGET_PATCH % rmmod $MOD_TARGET $MOD_TARGET: test_klp_mod_target_exit" # - load a livepatch that targets a not-yet-loaded module # - load the target module: klp_module_coming patches it immediately # - verify the proc entry returns livepatched output # - disable and unload the livepatch # - verify the proc entry returns original output again # - unload the target module start_test "module function patching (livepatch first)" load_lp $MOD_TARGET_PATCH load_mod $MOD_TARGET if [[ "$(cat /proc/$MOD_TARGET)" != "$MOD_TARGET_PATCH: this has been live patched" ]] ; then echo -e "FAIL\n\n" die "livepatch kselftest(s) failed" fi disable_lp $MOD_TARGET_PATCH unload_lp $MOD_TARGET_PATCH if [[ "$(cat /proc/$MOD_TARGET)" != "$MOD_TARGET: original output" ]] ; then echo -e "FAIL\n\n" die "livepatch kselftest(s) failed" fi unload_mod $MOD_TARGET check_result "% insmod test_modules/$MOD_TARGET_PATCH.ko livepatch: enabling patch '$MOD_TARGET_PATCH' livepatch: '$MOD_TARGET_PATCH': initializing patching transition livepatch: '$MOD_TARGET_PATCH': starting patching transition livepatch: '$MOD_TARGET_PATCH': completing patching transition livepatch: '$MOD_TARGET_PATCH': patching complete % insmod test_modules/$MOD_TARGET.ko livepatch: applying patch '$MOD_TARGET_PATCH' to loading module '$MOD_TARGET' $MOD_TARGET: test_klp_mod_target_init % echo 0 > $SYSFS_KLP_DIR/$MOD_TARGET_PATCH/enabled livepatch: '$MOD_TARGET_PATCH': initializing unpatching transition livepatch: '$MOD_TARGET_PATCH': starting unpatching transition livepatch: '$MOD_TARGET_PATCH': completing unpatching transition livepatch: '$MOD_TARGET_PATCH': unpatching complete % rmmod $MOD_TARGET_PATCH % rmmod $MOD_TARGET $MOD_TARGET: test_klp_mod_target_exit" exit 0