1 /* 2 * Copyright (C) 2017 Joe Lawrence <[email protected]> 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 2 7 * of the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 /* 19 * livepatch-shadow-fix2.c - Shadow variables, livepatch demo 20 * 21 * Purpose 22 * ------- 23 * 24 * Adds functionality to livepatch-shadow-mod's in-flight data 25 * structures through a shadow variable. The livepatch patches a 26 * routine that periodically inspects data structures, incrementing a 27 * per-data-structure counter, creating the counter if needed. 28 * 29 * 30 * Usage 31 * ----- 32 * 33 * This module is not intended to be standalone. See the "Usage" 34 * section of livepatch-shadow-mod.c. 35 */ 36 37 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 38 39 #include <linux/module.h> 40 #include <linux/kernel.h> 41 #include <linux/livepatch.h> 42 #include <linux/slab.h> 43 44 /* Shadow variable enums */ 45 #define SV_LEAK 1 46 #define SV_COUNTER 2 47 48 struct dummy { 49 struct list_head list; 50 unsigned long jiffies_expire; 51 }; 52 53 bool livepatch_fix2_dummy_check(struct dummy *d, unsigned long jiffies) 54 { 55 int *shadow_count; 56 57 /* 58 * Patch: handle in-flight dummy structures, if they do not 59 * already have a SV_COUNTER shadow variable, then attach a 60 * new one. 61 */ 62 shadow_count = klp_shadow_get_or_alloc(d, SV_COUNTER, 63 sizeof(*shadow_count), GFP_NOWAIT, 64 NULL, NULL); 65 if (shadow_count) 66 *shadow_count += 1; 67 68 return time_after(jiffies, d->jiffies_expire); 69 } 70 71 void livepatch_fix2_dummy_free(struct dummy *d) 72 { 73 void **shadow_leak, *leak; 74 int *shadow_count; 75 76 /* Patch: copy the memory leak patch from the fix1 module. */ 77 shadow_leak = klp_shadow_get(d, SV_LEAK); 78 if (shadow_leak) { 79 leak = *shadow_leak; 80 klp_shadow_free(d, SV_LEAK); 81 kfree(leak); 82 pr_info("%s: dummy @ %p, prevented leak @ %p\n", 83 __func__, d, leak); 84 } else { 85 pr_info("%s: dummy @ %p leaked!\n", __func__, d); 86 } 87 88 /* 89 * Patch: fetch the SV_COUNTER shadow variable and display 90 * the final count. Detach the shadow variable. 91 */ 92 shadow_count = klp_shadow_get(d, SV_COUNTER); 93 if (shadow_count) { 94 pr_info("%s: dummy @ %p, check counter = %d\n", 95 __func__, d, *shadow_count); 96 klp_shadow_free(d, SV_COUNTER); 97 } 98 99 kfree(d); 100 } 101 102 static struct klp_func funcs[] = { 103 { 104 .old_name = "dummy_check", 105 .new_func = livepatch_fix2_dummy_check, 106 }, 107 { 108 .old_name = "dummy_free", 109 .new_func = livepatch_fix2_dummy_free, 110 }, { } 111 }; 112 113 static struct klp_object objs[] = { 114 { 115 .name = "livepatch_shadow_mod", 116 .funcs = funcs, 117 }, { } 118 }; 119 120 static struct klp_patch patch = { 121 .mod = THIS_MODULE, 122 .objs = objs, 123 }; 124 125 static int livepatch_shadow_fix2_init(void) 126 { 127 int ret; 128 129 ret = klp_register_patch(&patch); 130 if (ret) 131 return ret; 132 ret = klp_enable_patch(&patch); 133 if (ret) { 134 WARN_ON(klp_unregister_patch(&patch)); 135 return ret; 136 } 137 return 0; 138 } 139 140 static void livepatch_shadow_fix2_exit(void) 141 { 142 /* Cleanup any existing SV_COUNTER shadow variables */ 143 klp_shadow_free_all(SV_COUNTER); 144 145 WARN_ON(klp_unregister_patch(&patch)); 146 } 147 148 module_init(livepatch_shadow_fix2_init); 149 module_exit(livepatch_shadow_fix2_exit); 150 MODULE_LICENSE("GPL"); 151 MODULE_INFO(livepatch, "Y"); 152