1 /* 2 * Copyright (C) 2017 Joe Lawrence <joe.lawrence@redhat.com> 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 int count; 57 58 /* 59 * Patch: handle in-flight dummy structures, if they do not 60 * already have a SV_COUNTER shadow variable, then attach a 61 * new one. 62 */ 63 count = 0; 64 shadow_count = klp_shadow_get_or_alloc(d, SV_COUNTER, 65 &count, sizeof(count), 66 GFP_NOWAIT); 67 if (shadow_count) 68 *shadow_count += 1; 69 70 return time_after(jiffies, d->jiffies_expire); 71 } 72 73 void livepatch_fix2_dummy_free(struct dummy *d) 74 { 75 void **shadow_leak, *leak; 76 int *shadow_count; 77 78 /* Patch: copy the memory leak patch from the fix1 module. */ 79 shadow_leak = klp_shadow_get(d, SV_LEAK); 80 if (shadow_leak) { 81 leak = *shadow_leak; 82 klp_shadow_free(d, SV_LEAK); 83 kfree(leak); 84 pr_info("%s: dummy @ %p, prevented leak @ %p\n", 85 __func__, d, leak); 86 } else { 87 pr_info("%s: dummy @ %p leaked!\n", __func__, d); 88 } 89 90 /* 91 * Patch: fetch the SV_COUNTER shadow variable and display 92 * the final count. Detach the shadow variable. 93 */ 94 shadow_count = klp_shadow_get(d, SV_COUNTER); 95 if (shadow_count) { 96 pr_info("%s: dummy @ %p, check counter = %d\n", 97 __func__, d, *shadow_count); 98 klp_shadow_free(d, SV_COUNTER); 99 } 100 101 kfree(d); 102 } 103 104 static struct klp_func funcs[] = { 105 { 106 .old_name = "dummy_check", 107 .new_func = livepatch_fix2_dummy_check, 108 }, 109 { 110 .old_name = "dummy_free", 111 .new_func = livepatch_fix2_dummy_free, 112 }, { } 113 }; 114 115 static struct klp_object objs[] = { 116 { 117 .name = "livepatch_shadow_mod", 118 .funcs = funcs, 119 }, { } 120 }; 121 122 static struct klp_patch patch = { 123 .mod = THIS_MODULE, 124 .objs = objs, 125 }; 126 127 static int livepatch_shadow_fix2_init(void) 128 { 129 int ret; 130 131 ret = klp_register_patch(&patch); 132 if (ret) 133 return ret; 134 ret = klp_enable_patch(&patch); 135 if (ret) { 136 WARN_ON(klp_unregister_patch(&patch)); 137 return ret; 138 } 139 return 0; 140 } 141 142 static void livepatch_shadow_fix2_exit(void) 143 { 144 /* Cleanup any existing SV_COUNTER shadow variables */ 145 klp_shadow_free_all(SV_COUNTER); 146 147 WARN_ON(klp_unregister_patch(&patch)); 148 } 149 150 module_init(livepatch_shadow_fix2_init); 151 module_exit(livepatch_shadow_fix2_exit); 152 MODULE_LICENSE("GPL"); 153 MODULE_INFO(livepatch, "Y"); 154