1 // SPDX-License-Identifier: GPL-2.0-or-later 1 2 /* 3 * Copyright (C) 2017 Joe Lawrence <joe.lawren 4 */ 5 6 /* 7 * livepatch-callbacks-demo.c - (un)patching c 8 * 9 * 10 * Purpose 11 * ------- 12 * 13 * Demonstration of registering livepatch (un) 14 * 15 * 16 * Usage 17 * ----- 18 * 19 * Step 1 - load the simple module 20 * 21 * insmod samples/livepatch/livepatch-callba 22 * 23 * 24 * Step 2 - load the demonstration livepatch ( 25 * 26 * insmod samples/livepatch/livepatch-callba 27 * 28 * 29 * Step 3 - cleanup 30 * 31 * echo 0 > /sys/kernel/livepatch/livepatch_ 32 * rmmod livepatch_callbacks_demo 33 * rmmod livepatch_callbacks_mod 34 * 35 * Watch dmesg output to see livepatch enablem 36 * and patching operations for both vmlinux an 37 * 38 * NOTE: swap the insmod order of livepatch-ca 39 * livepatch-callbacks-demo.ko to observ 40 * target module is loaded after a livep 41 * 42 * NOTE: 'pre_patch_ret' is a module parameter 43 * callback return status. Try setting 44 * such as -19 (-ENODEV): 45 * 46 * # Load demo livepatch, vmlinux is pat 47 * insmod samples/livepatch/livepatch-ca 48 * 49 * # Setup next pre-patch callback to re 50 * echo -19 > /sys/module/livepatch_call 51 * 52 * # Module loader refuses to load the t 53 * insmod samples/livepatch/livepatch-ca 54 * insmod: ERROR: could not insert modul 55 * 56 * NOTE: There is a second target module, 57 * livepatch-callbacks-busymod.ko, avail 58 * with livepatch (un)patch callbacks. 59 * a 'sleep_secs' parameter that parks t 60 * functions that the livepatch demo mod 61 * Modifying this value and tweaking the 62 * effectively demonstrate stalled patch 63 * 64 * # Load a target module, let it park o 65 * # thirty seconds 66 * insmod samples/livepatch/livepatch-ca 67 * 68 * # Meanwhile load the livepatch 69 * insmod samples/livepatch/livepatch-ca 70 * 71 * # ... then load and unload another ta 72 * # transition is in progress 73 * insmod samples/livepatch/livepatch-ca 74 * rmmod samples/livepatch/livepatch-cal 75 * 76 * # Finally cleanup 77 * echo 0 > /sys/kernel/livepatch/livepa 78 * rmmod samples/livepatch/livepatch-cal 79 */ 80 81 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 82 83 #include <linux/module.h> 84 #include <linux/kernel.h> 85 #include <linux/livepatch.h> 86 87 static int pre_patch_ret; 88 module_param(pre_patch_ret, int, 0644); 89 MODULE_PARM_DESC(pre_patch_ret, "pre_patch_ret 90 91 static const char *const module_state[] = { 92 [MODULE_STATE_LIVE] = "[MODULE_STA 93 [MODULE_STATE_COMING] = "[MODULE_STA 94 [MODULE_STATE_GOING] = "[MODULE_STA 95 [MODULE_STATE_UNFORMED] = "[MODULE_STA 96 }; 97 98 static void callback_info(const char *callback 99 { 100 if (obj->mod) 101 pr_info("%s: %s -> %s\n", call 102 module_state[obj->mod- 103 else 104 pr_info("%s: vmlinux\n", callb 105 } 106 107 /* Executed on object patching (ie, patch enab 108 static int pre_patch_callback(struct klp_objec 109 { 110 callback_info(__func__, obj); 111 return pre_patch_ret; 112 } 113 114 /* Executed on object unpatching (ie, patch di 115 static void post_patch_callback(struct klp_obj 116 { 117 callback_info(__func__, obj); 118 } 119 120 /* Executed on object unpatching (ie, patch di 121 static void pre_unpatch_callback(struct klp_ob 122 { 123 callback_info(__func__, obj); 124 } 125 126 /* Executed on object unpatching (ie, patch di 127 static void post_unpatch_callback(struct klp_o 128 { 129 callback_info(__func__, obj); 130 } 131 132 static void patched_work_func(struct work_stru 133 { 134 pr_info("%s\n", __func__); 135 } 136 137 static struct klp_func no_funcs[] = { 138 { } 139 }; 140 141 static struct klp_func busymod_funcs[] = { 142 { 143 .old_name = "busymod_work_func 144 .new_func = patched_work_func, 145 }, { } 146 }; 147 148 static struct klp_object objs[] = { 149 { 150 .name = NULL, /* vmlinux */ 151 .funcs = no_funcs, 152 .callbacks = { 153 .pre_patch = pre_patch 154 .post_patch = post_pat 155 .pre_unpatch = pre_unp 156 .post_unpatch = post_u 157 }, 158 }, { 159 .name = "livepatch_callbacks_m 160 .funcs = no_funcs, 161 .callbacks = { 162 .pre_patch = pre_patch 163 .post_patch = post_pat 164 .pre_unpatch = pre_unp 165 .post_unpatch = post_u 166 }, 167 }, { 168 .name = "livepatch_callbacks_b 169 .funcs = busymod_funcs, 170 .callbacks = { 171 .pre_patch = pre_patch 172 .post_patch = post_pat 173 .pre_unpatch = pre_unp 174 .post_unpatch = post_u 175 }, 176 }, { } 177 }; 178 179 static struct klp_patch patch = { 180 .mod = THIS_MODULE, 181 .objs = objs, 182 }; 183 184 static int livepatch_callbacks_demo_init(void) 185 { 186 return klp_enable_patch(&patch); 187 } 188 189 static void livepatch_callbacks_demo_exit(void 190 { 191 } 192 193 module_init(livepatch_callbacks_demo_init); 194 module_exit(livepatch_callbacks_demo_exit); 195 MODULE_LICENSE("GPL"); 196 MODULE_INFO(livepatch, "Y"); 197
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.