root/samples/livepatch/livepatch-shadow-fix2.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. livepatch_fix2_dummy_check
  2. livepatch_fix2_dummy_leak_dtor
  3. livepatch_fix2_dummy_free
  4. livepatch_shadow_fix2_init
  5. livepatch_shadow_fix2_exit

   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         void **shadow_leak = shadow_data;
  63 
  64         kfree(*shadow_leak);
  65         pr_info("%s: dummy @ %p, prevented leak @ %p\n",
  66                          __func__, d, *shadow_leak);
  67 }
  68 
  69 static void livepatch_fix2_dummy_free(struct dummy *d)
  70 {
  71         void **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");

/* [<][>][^][v][top][bottom][index][help] */