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 59e91c2518SPetr Mladek /* 60e91c2518SPetr Mladek * The constructor makes more sense together with klp_shadow_get_or_alloc(). 61e91c2518SPetr Mladek * In this example, it would be safe to assign the pointer also to the shadow 62e91c2518SPetr Mladek * variable returned by klp_shadow_alloc(). But we wanted to show the more 63e91c2518SPetr Mladek * complicated use of the API. 64e91c2518SPetr Mladek */ 65e91c2518SPetr Mladek static int shadow_leak_ctor(void *obj, void *shadow_data, void *ctor_data) 66e91c2518SPetr Mladek { 67e91c2518SPetr Mladek void **shadow_leak = shadow_data; 68e91c2518SPetr Mladek void *leak = ctor_data; 69e91c2518SPetr Mladek 70e91c2518SPetr Mladek *shadow_leak = leak; 71e91c2518SPetr Mladek return 0; 72e91c2518SPetr Mladek } 73e91c2518SPetr 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); 92e91c2518SPetr Mladek klp_shadow_alloc(d, SV_LEAK, sizeof(leak), GFP_KERNEL, 93e91c2518SPetr 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 101*3b2c77d0SPetr Mladek static void livepatch_fix1_dummy_leak_dtor(void *obj, void *shadow_data) 102*3b2c77d0SPetr Mladek { 103*3b2c77d0SPetr Mladek void *d = obj; 104*3b2c77d0SPetr Mladek void **shadow_leak = shadow_data; 105*3b2c77d0SPetr Mladek 106*3b2c77d0SPetr Mladek kfree(*shadow_leak); 107*3b2c77d0SPetr Mladek pr_info("%s: dummy @ %p, prevented leak @ %p\n", 108*3b2c77d0SPetr Mladek __func__, d, *shadow_leak); 109*3b2c77d0SPetr Mladek } 110*3b2c77d0SPetr Mladek 111439e7271SJoe Lawrence void livepatch_fix1_dummy_free(struct dummy *d) 112439e7271SJoe Lawrence { 113*3b2c77d0SPetr Mladek void **shadow_leak; 114439e7271SJoe Lawrence 115439e7271SJoe Lawrence /* 116439e7271SJoe Lawrence * Patch: fetch the saved SV_LEAK shadow variable, detach and 117439e7271SJoe Lawrence * free it. Note: handle cases where this shadow variable does 118439e7271SJoe Lawrence * not exist (ie, dummy structures allocated before this livepatch 119439e7271SJoe Lawrence * was loaded.) 120439e7271SJoe Lawrence */ 121439e7271SJoe Lawrence shadow_leak = klp_shadow_get(d, SV_LEAK); 122*3b2c77d0SPetr Mladek if (shadow_leak) 123*3b2c77d0SPetr Mladek klp_shadow_free(d, SV_LEAK, livepatch_fix1_dummy_leak_dtor); 124*3b2c77d0SPetr Mladek else 125439e7271SJoe Lawrence pr_info("%s: dummy @ %p leaked!\n", __func__, d); 126439e7271SJoe Lawrence 127439e7271SJoe Lawrence kfree(d); 128439e7271SJoe Lawrence } 129439e7271SJoe Lawrence 130439e7271SJoe Lawrence static struct klp_func funcs[] = { 131439e7271SJoe Lawrence { 132439e7271SJoe Lawrence .old_name = "dummy_alloc", 133439e7271SJoe Lawrence .new_func = livepatch_fix1_dummy_alloc, 134439e7271SJoe Lawrence }, 135439e7271SJoe Lawrence { 136439e7271SJoe Lawrence .old_name = "dummy_free", 137439e7271SJoe Lawrence .new_func = livepatch_fix1_dummy_free, 138439e7271SJoe Lawrence }, { } 139439e7271SJoe Lawrence }; 140439e7271SJoe Lawrence 141439e7271SJoe Lawrence static struct klp_object objs[] = { 142439e7271SJoe Lawrence { 143439e7271SJoe Lawrence .name = "livepatch_shadow_mod", 144439e7271SJoe Lawrence .funcs = funcs, 145439e7271SJoe Lawrence }, { } 146439e7271SJoe Lawrence }; 147439e7271SJoe Lawrence 148439e7271SJoe Lawrence static struct klp_patch patch = { 149439e7271SJoe Lawrence .mod = THIS_MODULE, 150439e7271SJoe Lawrence .objs = objs, 151439e7271SJoe Lawrence }; 152439e7271SJoe Lawrence 153439e7271SJoe Lawrence static int livepatch_shadow_fix1_init(void) 154439e7271SJoe Lawrence { 155439e7271SJoe Lawrence int ret; 156439e7271SJoe Lawrence 157439e7271SJoe Lawrence ret = klp_register_patch(&patch); 158439e7271SJoe Lawrence if (ret) 159439e7271SJoe Lawrence return ret; 160439e7271SJoe Lawrence ret = klp_enable_patch(&patch); 161439e7271SJoe Lawrence if (ret) { 162439e7271SJoe Lawrence WARN_ON(klp_unregister_patch(&patch)); 163439e7271SJoe Lawrence return ret; 164439e7271SJoe Lawrence } 165439e7271SJoe Lawrence return 0; 166439e7271SJoe Lawrence } 167439e7271SJoe Lawrence 168439e7271SJoe Lawrence static void livepatch_shadow_fix1_exit(void) 169439e7271SJoe Lawrence { 170439e7271SJoe Lawrence /* Cleanup any existing SV_LEAK shadow variables */ 171*3b2c77d0SPetr Mladek klp_shadow_free_all(SV_LEAK, livepatch_fix1_dummy_leak_dtor); 172439e7271SJoe Lawrence 173439e7271SJoe Lawrence WARN_ON(klp_unregister_patch(&patch)); 174439e7271SJoe Lawrence } 175439e7271SJoe Lawrence 176439e7271SJoe Lawrence module_init(livepatch_shadow_fix1_init); 177439e7271SJoe Lawrence module_exit(livepatch_shadow_fix1_exit); 178439e7271SJoe Lawrence MODULE_LICENSE("GPL"); 179439e7271SJoe Lawrence MODULE_INFO(livepatch, "Y"); 180