^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2017 Joe Lawrence <joe.lawrence@redhat.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * livepatch-callbacks-demo.c - (un)patching callbacks livepatch demo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Purpose
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * -------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Demonstration of registering livepatch (un)patching callbacks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Usage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * -----
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * Step 1 - load the simple module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * insmod samples/livepatch/livepatch-callbacks-mod.ko
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * Step 2 - load the demonstration livepatch (with callbacks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * insmod samples/livepatch/livepatch-callbacks-demo.ko
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * Step 3 - cleanup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * echo 0 > /sys/kernel/livepatch/livepatch_callbacks_demo/enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * rmmod livepatch_callbacks_demo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * rmmod livepatch_callbacks_mod
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * Watch dmesg output to see livepatch enablement, callback execution
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * and patching operations for both vmlinux and module targets.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * NOTE: swap the insmod order of livepatch-callbacks-mod.ko and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * livepatch-callbacks-demo.ko to observe what happens when a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * target module is loaded after a livepatch with callbacks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * NOTE: 'pre_patch_ret' is a module parameter that sets the pre-patch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * callback return status. Try setting up a non-zero status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * such as -19 (-ENODEV):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * # Load demo livepatch, vmlinux is patched
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * insmod samples/livepatch/livepatch-callbacks-demo.ko
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * # Setup next pre-patch callback to return -ENODEV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * echo -19 > /sys/module/livepatch_callbacks_demo/parameters/pre_patch_ret
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * # Module loader refuses to load the target module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * insmod samples/livepatch/livepatch-callbacks-mod.ko
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * insmod: ERROR: could not insert module samples/livepatch/livepatch-callbacks-mod.ko: No such device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * NOTE: There is a second target module,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * livepatch-callbacks-busymod.ko, available for experimenting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * with livepatch (un)patch callbacks. This module contains
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * a 'sleep_secs' parameter that parks the module on one of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * functions that the livepatch demo module wants to patch.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * Modifying this value and tweaking the order of module loads can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * effectively demonstrate stalled patch transitions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * # Load a target module, let it park on 'busymod_work_func' for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * # thirty seconds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * insmod samples/livepatch/livepatch-callbacks-busymod.ko sleep_secs=30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * # Meanwhile load the livepatch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * insmod samples/livepatch/livepatch-callbacks-demo.ko
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * # ... then load and unload another target module while the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * # transition is in progress
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * insmod samples/livepatch/livepatch-callbacks-mod.ko
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * rmmod samples/livepatch/livepatch-callbacks-mod.ko
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * # Finally cleanup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * echo 0 > /sys/kernel/livepatch/livepatch_callbacks_demo/enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * rmmod samples/livepatch/livepatch-callbacks-demo.ko
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #include <linux/livepatch.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static int pre_patch_ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) module_param(pre_patch_ret, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) MODULE_PARM_DESC(pre_patch_ret, "pre_patch_ret (default=0)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static const char *const module_state[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) [MODULE_STATE_LIVE] = "[MODULE_STATE_LIVE] Normal state",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) [MODULE_STATE_COMING] = "[MODULE_STATE_COMING] Full formed, running module_init",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) [MODULE_STATE_GOING] = "[MODULE_STATE_GOING] Going away",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) [MODULE_STATE_UNFORMED] = "[MODULE_STATE_UNFORMED] Still setting it up",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static void callback_info(const char *callback, struct klp_object *obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (obj->mod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) pr_info("%s: %s -> %s\n", callback, obj->mod->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) module_state[obj->mod->state]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) pr_info("%s: vmlinux\n", callback);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /* Executed on object patching (ie, patch enablement) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static int pre_patch_callback(struct klp_object *obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) callback_info(__func__, obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return pre_patch_ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /* Executed on object unpatching (ie, patch disablement) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static void post_patch_callback(struct klp_object *obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) callback_info(__func__, obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /* Executed on object unpatching (ie, patch disablement) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static void pre_unpatch_callback(struct klp_object *obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) callback_info(__func__, obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /* Executed on object unpatching (ie, patch disablement) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) static void post_unpatch_callback(struct klp_object *obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) callback_info(__func__, obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static void patched_work_func(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) pr_info("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static struct klp_func no_funcs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static struct klp_func busymod_funcs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) .old_name = "busymod_work_func",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) .new_func = patched_work_func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }, { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static struct klp_object objs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) .name = NULL, /* vmlinux */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) .funcs = no_funcs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) .callbacks = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) .pre_patch = pre_patch_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) .post_patch = post_patch_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) .pre_unpatch = pre_unpatch_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) .post_unpatch = post_unpatch_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) .name = "livepatch_callbacks_mod",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) .funcs = no_funcs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .callbacks = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) .pre_patch = pre_patch_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) .post_patch = post_patch_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) .pre_unpatch = pre_unpatch_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) .post_unpatch = post_unpatch_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) .name = "livepatch_callbacks_busymod",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) .funcs = busymod_funcs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) .callbacks = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) .pre_patch = pre_patch_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) .post_patch = post_patch_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) .pre_unpatch = pre_unpatch_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) .post_unpatch = post_unpatch_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }, { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static struct klp_patch patch = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) .mod = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) .objs = objs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static int livepatch_callbacks_demo_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return klp_enable_patch(&patch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static void livepatch_callbacks_demo_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) module_init(livepatch_callbacks_demo_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) module_exit(livepatch_callbacks_demo_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) MODULE_INFO(livepatch, "Y");