1*93862e38SJoe Lawrence /* 2*93862e38SJoe Lawrence * Copyright (C) 2017 Joe Lawrence <joe.lawrence@redhat.com> 3*93862e38SJoe Lawrence * 4*93862e38SJoe Lawrence * This program is free software; you can redistribute it and/or 5*93862e38SJoe Lawrence * modify it under the terms of the GNU General Public License 6*93862e38SJoe Lawrence * as published by the Free Software Foundation; either version 2 7*93862e38SJoe Lawrence * of the License, or (at your option) any later version. 8*93862e38SJoe Lawrence * 9*93862e38SJoe Lawrence * This program is distributed in the hope that it will be useful, 10*93862e38SJoe Lawrence * but WITHOUT ANY WARRANTY; without even the implied warranty of 11*93862e38SJoe Lawrence * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12*93862e38SJoe Lawrence * GNU General Public License for more details. 13*93862e38SJoe Lawrence * 14*93862e38SJoe Lawrence * You should have received a copy of the GNU General Public License 15*93862e38SJoe Lawrence * along with this program; if not, see <http://www.gnu.org/licenses/>. 16*93862e38SJoe Lawrence */ 17*93862e38SJoe Lawrence 18*93862e38SJoe Lawrence /* 19*93862e38SJoe Lawrence * livepatch-callbacks-demo.c - (un)patching callbacks livepatch demo 20*93862e38SJoe Lawrence * 21*93862e38SJoe Lawrence * 22*93862e38SJoe Lawrence * Purpose 23*93862e38SJoe Lawrence * ------- 24*93862e38SJoe Lawrence * 25*93862e38SJoe Lawrence * Demonstration of registering livepatch (un)patching callbacks. 26*93862e38SJoe Lawrence * 27*93862e38SJoe Lawrence * 28*93862e38SJoe Lawrence * Usage 29*93862e38SJoe Lawrence * ----- 30*93862e38SJoe Lawrence * 31*93862e38SJoe Lawrence * Step 1 - load the simple module 32*93862e38SJoe Lawrence * 33*93862e38SJoe Lawrence * insmod samples/livepatch/livepatch-callbacks-mod.ko 34*93862e38SJoe Lawrence * 35*93862e38SJoe Lawrence * 36*93862e38SJoe Lawrence * Step 2 - load the demonstration livepatch (with callbacks) 37*93862e38SJoe Lawrence * 38*93862e38SJoe Lawrence * insmod samples/livepatch/livepatch-callbacks-demo.ko 39*93862e38SJoe Lawrence * 40*93862e38SJoe Lawrence * 41*93862e38SJoe Lawrence * Step 3 - cleanup 42*93862e38SJoe Lawrence * 43*93862e38SJoe Lawrence * echo 0 > /sys/kernel/livepatch/livepatch_callbacks_demo/enabled 44*93862e38SJoe Lawrence * rmmod livepatch_callbacks_demo 45*93862e38SJoe Lawrence * rmmod livepatch_callbacks_mod 46*93862e38SJoe Lawrence * 47*93862e38SJoe Lawrence * Watch dmesg output to see livepatch enablement, callback execution 48*93862e38SJoe Lawrence * and patching operations for both vmlinux and module targets. 49*93862e38SJoe Lawrence * 50*93862e38SJoe Lawrence * NOTE: swap the insmod order of livepatch-callbacks-mod.ko and 51*93862e38SJoe Lawrence * livepatch-callbacks-demo.ko to observe what happens when a 52*93862e38SJoe Lawrence * target module is loaded after a livepatch with callbacks. 53*93862e38SJoe Lawrence * 54*93862e38SJoe Lawrence * NOTE: 'pre_patch_ret' is a module parameter that sets the pre-patch 55*93862e38SJoe Lawrence * callback return status. Try setting up a non-zero status 56*93862e38SJoe Lawrence * such as -19 (-ENODEV): 57*93862e38SJoe Lawrence * 58*93862e38SJoe Lawrence * # Load demo livepatch, vmlinux is patched 59*93862e38SJoe Lawrence * insmod samples/livepatch/livepatch-callbacks-demo.ko 60*93862e38SJoe Lawrence * 61*93862e38SJoe Lawrence * # Setup next pre-patch callback to return -ENODEV 62*93862e38SJoe Lawrence * echo -19 > /sys/module/livepatch_callbacks_demo/parameters/pre_patch_ret 63*93862e38SJoe Lawrence * 64*93862e38SJoe Lawrence * # Module loader refuses to load the target module 65*93862e38SJoe Lawrence * insmod samples/livepatch/livepatch-callbacks-mod.ko 66*93862e38SJoe Lawrence * insmod: ERROR: could not insert module samples/livepatch/livepatch-callbacks-mod.ko: No such device 67*93862e38SJoe Lawrence * 68*93862e38SJoe Lawrence * NOTE: There is a second target module, 69*93862e38SJoe Lawrence * livepatch-callbacks-busymod.ko, available for experimenting 70*93862e38SJoe Lawrence * with livepatch (un)patch callbacks. This module contains 71*93862e38SJoe Lawrence * a 'sleep_secs' parameter that parks the module on one of the 72*93862e38SJoe Lawrence * functions that the livepatch demo module wants to patch. 73*93862e38SJoe Lawrence * Modifying this value and tweaking the order of module loads can 74*93862e38SJoe Lawrence * effectively demonstrate stalled patch transitions: 75*93862e38SJoe Lawrence * 76*93862e38SJoe Lawrence * # Load a target module, let it park on 'busymod_work_func' for 77*93862e38SJoe Lawrence * # thirty seconds 78*93862e38SJoe Lawrence * insmod samples/livepatch/livepatch-callbacks-busymod.ko sleep_secs=30 79*93862e38SJoe Lawrence * 80*93862e38SJoe Lawrence * # Meanwhile load the livepatch 81*93862e38SJoe Lawrence * insmod samples/livepatch/livepatch-callbacks-demo.ko 82*93862e38SJoe Lawrence * 83*93862e38SJoe Lawrence * # ... then load and unload another target module while the 84*93862e38SJoe Lawrence * # transition is in progress 85*93862e38SJoe Lawrence * insmod samples/livepatch/livepatch-callbacks-mod.ko 86*93862e38SJoe Lawrence * rmmod samples/livepatch/livepatch-callbacks-mod.ko 87*93862e38SJoe Lawrence * 88*93862e38SJoe Lawrence * # Finally cleanup 89*93862e38SJoe Lawrence * echo 0 > /sys/kernel/livepatch/livepatch_callbacks_demo/enabled 90*93862e38SJoe Lawrence * rmmod samples/livepatch/livepatch-callbacks-demo.ko 91*93862e38SJoe Lawrence */ 92*93862e38SJoe Lawrence 93*93862e38SJoe Lawrence #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 94*93862e38SJoe Lawrence 95*93862e38SJoe Lawrence #include <linux/module.h> 96*93862e38SJoe Lawrence #include <linux/kernel.h> 97*93862e38SJoe Lawrence #include <linux/livepatch.h> 98*93862e38SJoe Lawrence 99*93862e38SJoe Lawrence static int pre_patch_ret; 100*93862e38SJoe Lawrence module_param(pre_patch_ret, int, 0644); 101*93862e38SJoe Lawrence MODULE_PARM_DESC(pre_patch_ret, "pre_patch_ret (default=0)"); 102*93862e38SJoe Lawrence 103*93862e38SJoe Lawrence static const char *const module_state[] = { 104*93862e38SJoe Lawrence [MODULE_STATE_LIVE] = "[MODULE_STATE_LIVE] Normal state", 105*93862e38SJoe Lawrence [MODULE_STATE_COMING] = "[MODULE_STATE_COMING] Full formed, running module_init", 106*93862e38SJoe Lawrence [MODULE_STATE_GOING] = "[MODULE_STATE_GOING] Going away", 107*93862e38SJoe Lawrence [MODULE_STATE_UNFORMED] = "[MODULE_STATE_UNFORMED] Still setting it up", 108*93862e38SJoe Lawrence }; 109*93862e38SJoe Lawrence 110*93862e38SJoe Lawrence static void callback_info(const char *callback, struct klp_object *obj) 111*93862e38SJoe Lawrence { 112*93862e38SJoe Lawrence if (obj->mod) 113*93862e38SJoe Lawrence pr_info("%s: %s -> %s\n", callback, obj->mod->name, 114*93862e38SJoe Lawrence module_state[obj->mod->state]); 115*93862e38SJoe Lawrence else 116*93862e38SJoe Lawrence pr_info("%s: vmlinux\n", callback); 117*93862e38SJoe Lawrence } 118*93862e38SJoe Lawrence 119*93862e38SJoe Lawrence /* Executed on object patching (ie, patch enablement) */ 120*93862e38SJoe Lawrence static int pre_patch_callback(struct klp_object *obj) 121*93862e38SJoe Lawrence { 122*93862e38SJoe Lawrence callback_info(__func__, obj); 123*93862e38SJoe Lawrence return pre_patch_ret; 124*93862e38SJoe Lawrence } 125*93862e38SJoe Lawrence 126*93862e38SJoe Lawrence /* Executed on object unpatching (ie, patch disablement) */ 127*93862e38SJoe Lawrence static void post_patch_callback(struct klp_object *obj) 128*93862e38SJoe Lawrence { 129*93862e38SJoe Lawrence callback_info(__func__, obj); 130*93862e38SJoe Lawrence } 131*93862e38SJoe Lawrence 132*93862e38SJoe Lawrence /* Executed on object unpatching (ie, patch disablement) */ 133*93862e38SJoe Lawrence static void pre_unpatch_callback(struct klp_object *obj) 134*93862e38SJoe Lawrence { 135*93862e38SJoe Lawrence callback_info(__func__, obj); 136*93862e38SJoe Lawrence } 137*93862e38SJoe Lawrence 138*93862e38SJoe Lawrence /* Executed on object unpatching (ie, patch disablement) */ 139*93862e38SJoe Lawrence static void post_unpatch_callback(struct klp_object *obj) 140*93862e38SJoe Lawrence { 141*93862e38SJoe Lawrence callback_info(__func__, obj); 142*93862e38SJoe Lawrence } 143*93862e38SJoe Lawrence 144*93862e38SJoe Lawrence static void patched_work_func(struct work_struct *work) 145*93862e38SJoe Lawrence { 146*93862e38SJoe Lawrence pr_info("%s\n", __func__); 147*93862e38SJoe Lawrence } 148*93862e38SJoe Lawrence 149*93862e38SJoe Lawrence static struct klp_func no_funcs[] = { 150*93862e38SJoe Lawrence { } 151*93862e38SJoe Lawrence }; 152*93862e38SJoe Lawrence 153*93862e38SJoe Lawrence static struct klp_func busymod_funcs[] = { 154*93862e38SJoe Lawrence { 155*93862e38SJoe Lawrence .old_name = "busymod_work_func", 156*93862e38SJoe Lawrence .new_func = patched_work_func, 157*93862e38SJoe Lawrence }, { } 158*93862e38SJoe Lawrence }; 159*93862e38SJoe Lawrence 160*93862e38SJoe Lawrence static struct klp_object objs[] = { 161*93862e38SJoe Lawrence { 162*93862e38SJoe Lawrence .name = NULL, /* vmlinux */ 163*93862e38SJoe Lawrence .funcs = no_funcs, 164*93862e38SJoe Lawrence .callbacks = { 165*93862e38SJoe Lawrence .pre_patch = pre_patch_callback, 166*93862e38SJoe Lawrence .post_patch = post_patch_callback, 167*93862e38SJoe Lawrence .pre_unpatch = pre_unpatch_callback, 168*93862e38SJoe Lawrence .post_unpatch = post_unpatch_callback, 169*93862e38SJoe Lawrence }, 170*93862e38SJoe Lawrence }, { 171*93862e38SJoe Lawrence .name = "livepatch_callbacks_mod", 172*93862e38SJoe Lawrence .funcs = no_funcs, 173*93862e38SJoe Lawrence .callbacks = { 174*93862e38SJoe Lawrence .pre_patch = pre_patch_callback, 175*93862e38SJoe Lawrence .post_patch = post_patch_callback, 176*93862e38SJoe Lawrence .pre_unpatch = pre_unpatch_callback, 177*93862e38SJoe Lawrence .post_unpatch = post_unpatch_callback, 178*93862e38SJoe Lawrence }, 179*93862e38SJoe Lawrence }, { 180*93862e38SJoe Lawrence .name = "livepatch_callbacks_busymod", 181*93862e38SJoe Lawrence .funcs = busymod_funcs, 182*93862e38SJoe Lawrence .callbacks = { 183*93862e38SJoe Lawrence .pre_patch = pre_patch_callback, 184*93862e38SJoe Lawrence .post_patch = post_patch_callback, 185*93862e38SJoe Lawrence .pre_unpatch = pre_unpatch_callback, 186*93862e38SJoe Lawrence .post_unpatch = post_unpatch_callback, 187*93862e38SJoe Lawrence }, 188*93862e38SJoe Lawrence }, { } 189*93862e38SJoe Lawrence }; 190*93862e38SJoe Lawrence 191*93862e38SJoe Lawrence static struct klp_patch patch = { 192*93862e38SJoe Lawrence .mod = THIS_MODULE, 193*93862e38SJoe Lawrence .objs = objs, 194*93862e38SJoe Lawrence }; 195*93862e38SJoe Lawrence 196*93862e38SJoe Lawrence static int livepatch_callbacks_demo_init(void) 197*93862e38SJoe Lawrence { 198*93862e38SJoe Lawrence int ret; 199*93862e38SJoe Lawrence 200*93862e38SJoe Lawrence if (!klp_have_reliable_stack() && !patch.immediate) { 201*93862e38SJoe Lawrence /* 202*93862e38SJoe Lawrence * WARNING: Be very careful when using 'patch.immediate' in 203*93862e38SJoe Lawrence * your patches. It's ok to use it for simple patches like 204*93862e38SJoe Lawrence * this, but for more complex patches which change function 205*93862e38SJoe Lawrence * semantics, locking semantics, or data structures, it may not 206*93862e38SJoe Lawrence * be safe. Use of this option will also prevent removal of 207*93862e38SJoe Lawrence * the patch. 208*93862e38SJoe Lawrence * 209*93862e38SJoe Lawrence * See Documentation/livepatch/livepatch.txt for more details. 210*93862e38SJoe Lawrence */ 211*93862e38SJoe Lawrence patch.immediate = true; 212*93862e38SJoe Lawrence pr_notice("The consistency model isn't supported for your architecture. Bypassing safety mechanisms and applying the patch immediately.\n"); 213*93862e38SJoe Lawrence } 214*93862e38SJoe Lawrence 215*93862e38SJoe Lawrence ret = klp_register_patch(&patch); 216*93862e38SJoe Lawrence if (ret) 217*93862e38SJoe Lawrence return ret; 218*93862e38SJoe Lawrence ret = klp_enable_patch(&patch); 219*93862e38SJoe Lawrence if (ret) { 220*93862e38SJoe Lawrence WARN_ON(klp_unregister_patch(&patch)); 221*93862e38SJoe Lawrence return ret; 222*93862e38SJoe Lawrence } 223*93862e38SJoe Lawrence return 0; 224*93862e38SJoe Lawrence } 225*93862e38SJoe Lawrence 226*93862e38SJoe Lawrence static void livepatch_callbacks_demo_exit(void) 227*93862e38SJoe Lawrence { 228*93862e38SJoe Lawrence WARN_ON(klp_unregister_patch(&patch)); 229*93862e38SJoe Lawrence } 230*93862e38SJoe Lawrence 231*93862e38SJoe Lawrence module_init(livepatch_callbacks_demo_init); 232*93862e38SJoe Lawrence module_exit(livepatch_callbacks_demo_exit); 233*93862e38SJoe Lawrence MODULE_LICENSE("GPL"); 234*93862e38SJoe Lawrence MODULE_INFO(livepatch, "Y"); 235