1439e7271SJoe Lawrence /* 2439e7271SJoe Lawrence * Copyright (C) 2017 Joe Lawrence <joe.lawrence@redhat.com> 3439e7271SJoe Lawrence * 4439e7271SJoe Lawrence * This program is free software; you can redistribute it and/or 5439e7271SJoe Lawrence * modify it under the terms of the GNU General Public License 6439e7271SJoe Lawrence * as published by the Free Software Foundation; either version 2 7439e7271SJoe Lawrence * of the License, or (at your option) any later version. 8439e7271SJoe Lawrence * 9439e7271SJoe Lawrence * This program is distributed in the hope that it will be useful, 10439e7271SJoe Lawrence * but WITHOUT ANY WARRANTY; without even the implied warranty of 11439e7271SJoe Lawrence * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12439e7271SJoe Lawrence * GNU General Public License for more details. 13439e7271SJoe Lawrence * 14439e7271SJoe Lawrence * You should have received a copy of the GNU General Public License 15439e7271SJoe Lawrence * along with this program; if not, see <http://www.gnu.org/licenses/>. 16439e7271SJoe Lawrence */ 17439e7271SJoe Lawrence 18439e7271SJoe Lawrence /* 19439e7271SJoe Lawrence * livepatch-shadow-fix1.c - Shadow variables, livepatch demo 20439e7271SJoe Lawrence * 21439e7271SJoe Lawrence * Purpose 22439e7271SJoe Lawrence * ------- 23439e7271SJoe Lawrence * 24439e7271SJoe Lawrence * Fixes the memory leak introduced in livepatch-shadow-mod through the 25439e7271SJoe Lawrence * use of a shadow variable. This fix demonstrates the "extending" of 26439e7271SJoe Lawrence * short-lived data structures by patching its allocation and release 27439e7271SJoe Lawrence * functions. 28439e7271SJoe Lawrence * 29439e7271SJoe Lawrence * 30439e7271SJoe Lawrence * Usage 31439e7271SJoe Lawrence * ----- 32439e7271SJoe Lawrence * 33439e7271SJoe Lawrence * This module is not intended to be standalone. See the "Usage" 34439e7271SJoe Lawrence * section of livepatch-shadow-mod.c. 35439e7271SJoe Lawrence */ 36439e7271SJoe Lawrence 37439e7271SJoe Lawrence #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 38439e7271SJoe Lawrence 39439e7271SJoe Lawrence #include <linux/module.h> 40439e7271SJoe Lawrence #include <linux/kernel.h> 41439e7271SJoe Lawrence #include <linux/livepatch.h> 42439e7271SJoe Lawrence #include <linux/slab.h> 43439e7271SJoe Lawrence 44439e7271SJoe Lawrence /* Shadow variable enums */ 45439e7271SJoe Lawrence #define SV_LEAK 1 46439e7271SJoe Lawrence 47439e7271SJoe Lawrence /* Allocate new dummies every second */ 48439e7271SJoe Lawrence #define ALLOC_PERIOD 1 49439e7271SJoe Lawrence /* Check for expired dummies after a few new ones have been allocated */ 50439e7271SJoe Lawrence #define CLEANUP_PERIOD (3 * ALLOC_PERIOD) 51439e7271SJoe Lawrence /* Dummies expire after a few cleanup instances */ 52439e7271SJoe Lawrence #define EXPIRE_PERIOD (4 * CLEANUP_PERIOD) 53439e7271SJoe Lawrence 54439e7271SJoe Lawrence struct dummy { 55439e7271SJoe Lawrence struct list_head list; 56439e7271SJoe Lawrence unsigned long jiffies_expire; 57439e7271SJoe Lawrence }; 58439e7271SJoe Lawrence 59*e91c2518SPetr Mladek /* 60*e91c2518SPetr Mladek * The constructor makes more sense together with klp_shadow_get_or_alloc(). 61*e91c2518SPetr Mladek * In this example, it would be safe to assign the pointer also to the shadow 62*e91c2518SPetr Mladek * variable returned by klp_shadow_alloc(). But we wanted to show the more 63*e91c2518SPetr Mladek * complicated use of the API. 64*e91c2518SPetr Mladek */ 65*e91c2518SPetr Mladek static int shadow_leak_ctor(void *obj, void *shadow_data, void *ctor_data) 66*e91c2518SPetr Mladek { 67*e91c2518SPetr Mladek void **shadow_leak = shadow_data; 68*e91c2518SPetr Mladek void *leak = ctor_data; 69*e91c2518SPetr Mladek 70*e91c2518SPetr Mladek *shadow_leak = leak; 71*e91c2518SPetr Mladek return 0; 72*e91c2518SPetr Mladek } 73*e91c2518SPetr Mladek 74439e7271SJoe Lawrence struct dummy *livepatch_fix1_dummy_alloc(void) 75439e7271SJoe Lawrence { 76439e7271SJoe Lawrence struct dummy *d; 77439e7271SJoe Lawrence void *leak; 78439e7271SJoe Lawrence 79439e7271SJoe Lawrence d = kzalloc(sizeof(*d), GFP_KERNEL); 80439e7271SJoe Lawrence if (!d) 81439e7271SJoe Lawrence return NULL; 82439e7271SJoe Lawrence 83439e7271SJoe Lawrence d->jiffies_expire = jiffies + 84439e7271SJoe Lawrence msecs_to_jiffies(1000 * EXPIRE_PERIOD); 85439e7271SJoe Lawrence 86439e7271SJoe Lawrence /* 87439e7271SJoe Lawrence * Patch: save the extra memory location into a SV_LEAK shadow 88439e7271SJoe Lawrence * variable. A patched dummy_free routine can later fetch this 89439e7271SJoe Lawrence * pointer to handle resource release. 90439e7271SJoe Lawrence */ 91439e7271SJoe Lawrence leak = kzalloc(sizeof(int), GFP_KERNEL); 92*e91c2518SPetr Mladek klp_shadow_alloc(d, SV_LEAK, sizeof(leak), GFP_KERNEL, 93*e91c2518SPetr Mladek shadow_leak_ctor, leak); 94439e7271SJoe Lawrence 95439e7271SJoe Lawrence pr_info("%s: dummy @ %p, expires @ %lx\n", 96439e7271SJoe Lawrence __func__, d, d->jiffies_expire); 97439e7271SJoe Lawrence 98439e7271SJoe Lawrence return d; 99439e7271SJoe Lawrence } 100439e7271SJoe Lawrence 101439e7271SJoe Lawrence void livepatch_fix1_dummy_free(struct dummy *d) 102439e7271SJoe Lawrence { 103439e7271SJoe Lawrence void **shadow_leak, *leak; 104439e7271SJoe Lawrence 105439e7271SJoe Lawrence /* 106439e7271SJoe Lawrence * Patch: fetch the saved SV_LEAK shadow variable, detach and 107439e7271SJoe Lawrence * free it. Note: handle cases where this shadow variable does 108439e7271SJoe Lawrence * not exist (ie, dummy structures allocated before this livepatch 109439e7271SJoe Lawrence * was loaded.) 110439e7271SJoe Lawrence */ 111439e7271SJoe Lawrence shadow_leak = klp_shadow_get(d, SV_LEAK); 112439e7271SJoe Lawrence if (shadow_leak) { 113439e7271SJoe Lawrence leak = *shadow_leak; 114439e7271SJoe Lawrence klp_shadow_free(d, SV_LEAK); 115439e7271SJoe Lawrence kfree(leak); 116439e7271SJoe Lawrence pr_info("%s: dummy @ %p, prevented leak @ %p\n", 117439e7271SJoe Lawrence __func__, d, leak); 118439e7271SJoe Lawrence } else { 119439e7271SJoe Lawrence pr_info("%s: dummy @ %p leaked!\n", __func__, d); 120439e7271SJoe Lawrence } 121439e7271SJoe Lawrence 122439e7271SJoe Lawrence kfree(d); 123439e7271SJoe Lawrence } 124439e7271SJoe Lawrence 125439e7271SJoe Lawrence static struct klp_func funcs[] = { 126439e7271SJoe Lawrence { 127439e7271SJoe Lawrence .old_name = "dummy_alloc", 128439e7271SJoe Lawrence .new_func = livepatch_fix1_dummy_alloc, 129439e7271SJoe Lawrence }, 130439e7271SJoe Lawrence { 131439e7271SJoe Lawrence .old_name = "dummy_free", 132439e7271SJoe Lawrence .new_func = livepatch_fix1_dummy_free, 133439e7271SJoe Lawrence }, { } 134439e7271SJoe Lawrence }; 135439e7271SJoe Lawrence 136439e7271SJoe Lawrence static struct klp_object objs[] = { 137439e7271SJoe Lawrence { 138439e7271SJoe Lawrence .name = "livepatch_shadow_mod", 139439e7271SJoe Lawrence .funcs = funcs, 140439e7271SJoe Lawrence }, { } 141439e7271SJoe Lawrence }; 142439e7271SJoe Lawrence 143439e7271SJoe Lawrence static struct klp_patch patch = { 144439e7271SJoe Lawrence .mod = THIS_MODULE, 145439e7271SJoe Lawrence .objs = objs, 146439e7271SJoe Lawrence }; 147439e7271SJoe Lawrence 148439e7271SJoe Lawrence static int livepatch_shadow_fix1_init(void) 149439e7271SJoe Lawrence { 150439e7271SJoe Lawrence int ret; 151439e7271SJoe Lawrence 152439e7271SJoe Lawrence ret = klp_register_patch(&patch); 153439e7271SJoe Lawrence if (ret) 154439e7271SJoe Lawrence return ret; 155439e7271SJoe Lawrence ret = klp_enable_patch(&patch); 156439e7271SJoe Lawrence if (ret) { 157439e7271SJoe Lawrence WARN_ON(klp_unregister_patch(&patch)); 158439e7271SJoe Lawrence return ret; 159439e7271SJoe Lawrence } 160439e7271SJoe Lawrence return 0; 161439e7271SJoe Lawrence } 162439e7271SJoe Lawrence 163439e7271SJoe Lawrence static void livepatch_shadow_fix1_exit(void) 164439e7271SJoe Lawrence { 165439e7271SJoe Lawrence /* Cleanup any existing SV_LEAK shadow variables */ 166439e7271SJoe Lawrence klp_shadow_free_all(SV_LEAK); 167439e7271SJoe Lawrence 168439e7271SJoe Lawrence WARN_ON(klp_unregister_patch(&patch)); 169439e7271SJoe Lawrence } 170439e7271SJoe Lawrence 171439e7271SJoe Lawrence module_init(livepatch_shadow_fix1_init); 172439e7271SJoe Lawrence module_exit(livepatch_shadow_fix1_exit); 173439e7271SJoe Lawrence MODULE_LICENSE("GPL"); 174439e7271SJoe Lawrence MODULE_INFO(livepatch, "Y"); 175