11ccea77eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2439e7271SJoe Lawrence /* 3439e7271SJoe Lawrence * Copyright (C) 2017 Joe Lawrence <joe.lawrence@redhat.com> 4439e7271SJoe Lawrence */ 5439e7271SJoe Lawrence 6439e7271SJoe Lawrence /* 7439e7271SJoe Lawrence * livepatch-shadow-fix2.c - Shadow variables, livepatch demo 8439e7271SJoe Lawrence * 9439e7271SJoe Lawrence * Purpose 10439e7271SJoe Lawrence * ------- 11439e7271SJoe Lawrence * 12439e7271SJoe Lawrence * Adds functionality to livepatch-shadow-mod's in-flight data 13439e7271SJoe Lawrence * structures through a shadow variable. The livepatch patches a 14439e7271SJoe Lawrence * routine that periodically inspects data structures, incrementing a 15439e7271SJoe Lawrence * per-data-structure counter, creating the counter if needed. 16439e7271SJoe Lawrence * 17439e7271SJoe Lawrence * 18439e7271SJoe Lawrence * Usage 19439e7271SJoe Lawrence * ----- 20439e7271SJoe Lawrence * 21439e7271SJoe Lawrence * This module is not intended to be standalone. See the "Usage" 22439e7271SJoe Lawrence * section of livepatch-shadow-mod.c. 23439e7271SJoe Lawrence */ 24439e7271SJoe Lawrence 25439e7271SJoe Lawrence #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 26439e7271SJoe Lawrence 27439e7271SJoe Lawrence #include <linux/module.h> 28439e7271SJoe Lawrence #include <linux/kernel.h> 29439e7271SJoe Lawrence #include <linux/livepatch.h> 30439e7271SJoe Lawrence #include <linux/slab.h> 31439e7271SJoe Lawrence 32439e7271SJoe Lawrence /* Shadow variable enums */ 33439e7271SJoe Lawrence #define SV_LEAK 1 34439e7271SJoe Lawrence #define SV_COUNTER 2 35439e7271SJoe Lawrence 36439e7271SJoe Lawrence struct dummy { 37439e7271SJoe Lawrence struct list_head list; 38439e7271SJoe Lawrence unsigned long jiffies_expire; 39439e7271SJoe Lawrence }; 40439e7271SJoe Lawrence 41b73d5dc7SNicholas Mc Guire static bool livepatch_fix2_dummy_check(struct dummy *d, unsigned long jiffies) 42439e7271SJoe Lawrence { 43439e7271SJoe Lawrence int *shadow_count; 44439e7271SJoe Lawrence 45439e7271SJoe Lawrence /* 46439e7271SJoe Lawrence * Patch: handle in-flight dummy structures, if they do not 47439e7271SJoe Lawrence * already have a SV_COUNTER shadow variable, then attach a 48439e7271SJoe Lawrence * new one. 49439e7271SJoe Lawrence */ 50439e7271SJoe Lawrence shadow_count = klp_shadow_get_or_alloc(d, SV_COUNTER, 51e91c2518SPetr Mladek sizeof(*shadow_count), GFP_NOWAIT, 52e91c2518SPetr Mladek NULL, NULL); 53439e7271SJoe Lawrence if (shadow_count) 54439e7271SJoe Lawrence *shadow_count += 1; 55439e7271SJoe Lawrence 56439e7271SJoe Lawrence return time_after(jiffies, d->jiffies_expire); 57439e7271SJoe Lawrence } 58439e7271SJoe Lawrence 593b2c77d0SPetr Mladek static void livepatch_fix2_dummy_leak_dtor(void *obj, void *shadow_data) 603b2c77d0SPetr Mladek { 613b2c77d0SPetr Mladek void *d = obj; 62*8f6b8866SPetr Mladek int **shadow_leak = shadow_data; 633b2c77d0SPetr Mladek 643b2c77d0SPetr Mladek kfree(*shadow_leak); 653b2c77d0SPetr Mladek pr_info("%s: dummy @ %p, prevented leak @ %p\n", 663b2c77d0SPetr Mladek __func__, d, *shadow_leak); 673b2c77d0SPetr Mladek } 683b2c77d0SPetr Mladek 69b73d5dc7SNicholas Mc Guire static void livepatch_fix2_dummy_free(struct dummy *d) 70439e7271SJoe Lawrence { 71*8f6b8866SPetr Mladek int **shadow_leak; 72439e7271SJoe Lawrence int *shadow_count; 73439e7271SJoe Lawrence 74439e7271SJoe Lawrence /* Patch: copy the memory leak patch from the fix1 module. */ 75439e7271SJoe Lawrence shadow_leak = klp_shadow_get(d, SV_LEAK); 763b2c77d0SPetr Mladek if (shadow_leak) 773b2c77d0SPetr Mladek klp_shadow_free(d, SV_LEAK, livepatch_fix2_dummy_leak_dtor); 783b2c77d0SPetr Mladek else 79439e7271SJoe Lawrence pr_info("%s: dummy @ %p leaked!\n", __func__, d); 80439e7271SJoe Lawrence 81439e7271SJoe Lawrence /* 82439e7271SJoe Lawrence * Patch: fetch the SV_COUNTER shadow variable and display 83439e7271SJoe Lawrence * the final count. Detach the shadow variable. 84439e7271SJoe Lawrence */ 85439e7271SJoe Lawrence shadow_count = klp_shadow_get(d, SV_COUNTER); 86439e7271SJoe Lawrence if (shadow_count) { 87439e7271SJoe Lawrence pr_info("%s: dummy @ %p, check counter = %d\n", 88439e7271SJoe Lawrence __func__, d, *shadow_count); 893b2c77d0SPetr Mladek klp_shadow_free(d, SV_COUNTER, NULL); 90439e7271SJoe Lawrence } 91439e7271SJoe Lawrence 92439e7271SJoe Lawrence kfree(d); 93439e7271SJoe Lawrence } 94439e7271SJoe Lawrence 95439e7271SJoe Lawrence static struct klp_func funcs[] = { 96439e7271SJoe Lawrence { 97439e7271SJoe Lawrence .old_name = "dummy_check", 98439e7271SJoe Lawrence .new_func = livepatch_fix2_dummy_check, 99439e7271SJoe Lawrence }, 100439e7271SJoe Lawrence { 101439e7271SJoe Lawrence .old_name = "dummy_free", 102439e7271SJoe Lawrence .new_func = livepatch_fix2_dummy_free, 103439e7271SJoe Lawrence }, { } 104439e7271SJoe Lawrence }; 105439e7271SJoe Lawrence 106439e7271SJoe Lawrence static struct klp_object objs[] = { 107439e7271SJoe Lawrence { 108439e7271SJoe Lawrence .name = "livepatch_shadow_mod", 109439e7271SJoe Lawrence .funcs = funcs, 110439e7271SJoe Lawrence }, { } 111439e7271SJoe Lawrence }; 112439e7271SJoe Lawrence 113439e7271SJoe Lawrence static struct klp_patch patch = { 114439e7271SJoe Lawrence .mod = THIS_MODULE, 115439e7271SJoe Lawrence .objs = objs, 116439e7271SJoe Lawrence }; 117439e7271SJoe Lawrence 118439e7271SJoe Lawrence static int livepatch_shadow_fix2_init(void) 119439e7271SJoe Lawrence { 120958ef1e3SPetr Mladek return klp_enable_patch(&patch); 121439e7271SJoe Lawrence } 122439e7271SJoe Lawrence 123439e7271SJoe Lawrence static void livepatch_shadow_fix2_exit(void) 124439e7271SJoe Lawrence { 125439e7271SJoe Lawrence /* Cleanup any existing SV_COUNTER shadow variables */ 1263b2c77d0SPetr Mladek klp_shadow_free_all(SV_COUNTER, NULL); 127439e7271SJoe Lawrence } 128439e7271SJoe Lawrence 129439e7271SJoe Lawrence module_init(livepatch_shadow_fix2_init); 130439e7271SJoe Lawrence module_exit(livepatch_shadow_fix2_exit); 131439e7271SJoe Lawrence MODULE_LICENSE("GPL"); 132439e7271SJoe Lawrence MODULE_INFO(livepatch, "Y"); 133