1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2017 Joe Lawrence <joe.lawrence@redhat.com> 4 */ 5 6 /* 7 * livepatch-shadow-fix2.c - Shadow variables, livepatch demo 8 * 9 * Purpose 10 * ------- 11 * 12 * Adds functionality to livepatch-shadow-mod's in-flight data 13 * structures through a shadow variable. The livepatch patches a 14 * routine that periodically inspects data structures, incrementing a 15 * per-data-structure counter, creating the counter if needed. 16 * 17 * 18 * Usage 19 * ----- 20 * 21 * This module is not intended to be standalone. See the "Usage" 22 * section of livepatch-shadow-mod.c. 23 */ 24 25 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 26 27 #include <linux/module.h> 28 #include <linux/kernel.h> 29 #include <linux/livepatch.h> 30 #include <linux/slab.h> 31 32 /* Shadow variable enums */ 33 #define SV_LEAK 1 34 #define SV_COUNTER 2 35 36 struct dummy { 37 struct list_head list; 38 unsigned long jiffies_expire; 39 }; 40 41 static bool livepatch_fix2_dummy_check(struct dummy *d, unsigned long jiffies) 42 { 43 int *shadow_count; 44 45 /* 46 * Patch: handle in-flight dummy structures, if they do not 47 * already have a SV_COUNTER shadow variable, then attach a 48 * new one. 49 */ 50 shadow_count = klp_shadow_get_or_alloc(d, SV_COUNTER, 51 sizeof(*shadow_count), GFP_NOWAIT, 52 NULL, NULL); 53 if (shadow_count) 54 *shadow_count += 1; 55 56 return time_after(jiffies, d->jiffies_expire); 57 } 58 59 static void livepatch_fix2_dummy_leak_dtor(void *obj, void *shadow_data) 60 { 61 void *d = obj; 62 int **shadow_leak = shadow_data; 63 64 pr_info("%s: dummy @ %p, prevented leak @ %p\n", 65 __func__, d, *shadow_leak); 66 kfree(*shadow_leak); 67 } 68 69 static void livepatch_fix2_dummy_free(struct dummy *d) 70 { 71 int **shadow_leak; 72 int *shadow_count; 73 74 /* Patch: copy the memory leak patch from the fix1 module. */ 75 shadow_leak = klp_shadow_get(d, SV_LEAK); 76 if (shadow_leak) 77 klp_shadow_free(d, SV_LEAK, livepatch_fix2_dummy_leak_dtor); 78 else 79 pr_info("%s: dummy @ %p leaked!\n", __func__, d); 80 81 /* 82 * Patch: fetch the SV_COUNTER shadow variable and display 83 * the final count. Detach the shadow variable. 84 */ 85 shadow_count = klp_shadow_get(d, SV_COUNTER); 86 if (shadow_count) { 87 pr_info("%s: dummy @ %p, check counter = %d\n", 88 __func__, d, *shadow_count); 89 klp_shadow_free(d, SV_COUNTER, NULL); 90 } 91 92 kfree(d); 93 } 94 95 static struct klp_func funcs[] = { 96 { 97 .old_name = "dummy_check", 98 .new_func = livepatch_fix2_dummy_check, 99 }, 100 { 101 .old_name = "dummy_free", 102 .new_func = livepatch_fix2_dummy_free, 103 }, { } 104 }; 105 106 static struct klp_object objs[] = { 107 { 108 .name = "livepatch_shadow_mod", 109 .funcs = funcs, 110 }, { } 111 }; 112 113 static struct klp_patch patch = { 114 .mod = THIS_MODULE, 115 .objs = objs, 116 }; 117 118 static int livepatch_shadow_fix2_init(void) 119 { 120 return klp_enable_patch(&patch); 121 } 122 123 static void livepatch_shadow_fix2_exit(void) 124 { 125 /* Cleanup any existing SV_COUNTER shadow variables */ 126 klp_shadow_free_all(SV_COUNTER, NULL); 127 } 128 129 module_init(livepatch_shadow_fix2_init); 130 module_exit(livepatch_shadow_fix2_exit); 131 MODULE_LICENSE("GPL"); 132 MODULE_INFO(livepatch, "Y"); 133