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