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

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

DEFINITIONS

This source file includes following definitions.
  1. shadow_leak_ctor
  2. livepatch_fix1_dummy_alloc
  3. livepatch_fix1_dummy_leak_dtor
  4. livepatch_fix1_dummy_free
  5. livepatch_shadow_fix1_init
  6. livepatch_shadow_fix1_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-fix1.c - Shadow variables, livepatch demo
   8  *
   9  * Purpose
  10  * -------
  11  *
  12  * Fixes the memory leak introduced in livepatch-shadow-mod through the
  13  * use of a shadow variable.  This fix demonstrates the "extending" of
  14  * short-lived data structures by patching its allocation and release
  15  * functions.
  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 
  35 /* Allocate new dummies every second */
  36 #define ALLOC_PERIOD    1
  37 /* Check for expired dummies after a few new ones have been allocated */
  38 #define CLEANUP_PERIOD  (3 * ALLOC_PERIOD)
  39 /* Dummies expire after a few cleanup instances */
  40 #define EXPIRE_PERIOD   (4 * CLEANUP_PERIOD)
  41 
  42 struct dummy {
  43         struct list_head list;
  44         unsigned long jiffies_expire;
  45 };
  46 
  47 /*
  48  * The constructor makes more sense together with klp_shadow_get_or_alloc().
  49  * In this example, it would be safe to assign the pointer also to the shadow
  50  * variable returned by klp_shadow_alloc().  But we wanted to show the more
  51  * complicated use of the API.
  52  */
  53 static int shadow_leak_ctor(void *obj, void *shadow_data, void *ctor_data)
  54 {
  55         void **shadow_leak = shadow_data;
  56         void *leak = ctor_data;
  57 
  58         *shadow_leak = leak;
  59         return 0;
  60 }
  61 
  62 static struct dummy *livepatch_fix1_dummy_alloc(void)
  63 {
  64         struct dummy *d;
  65         void *leak;
  66 
  67         d = kzalloc(sizeof(*d), GFP_KERNEL);
  68         if (!d)
  69                 return NULL;
  70 
  71         d->jiffies_expire = jiffies +
  72                 msecs_to_jiffies(1000 * EXPIRE_PERIOD);
  73 
  74         /*
  75          * Patch: save the extra memory location into a SV_LEAK shadow
  76          * variable.  A patched dummy_free routine can later fetch this
  77          * pointer to handle resource release.
  78          */
  79         leak = kzalloc(sizeof(int), GFP_KERNEL);
  80         if (!leak) {
  81                 kfree(d);
  82                 return NULL;
  83         }
  84 
  85         klp_shadow_alloc(d, SV_LEAK, sizeof(leak), GFP_KERNEL,
  86                          shadow_leak_ctor, leak);
  87 
  88         pr_info("%s: dummy @ %p, expires @ %lx\n",
  89                 __func__, d, d->jiffies_expire);
  90 
  91         return d;
  92 }
  93 
  94 static void livepatch_fix1_dummy_leak_dtor(void *obj, void *shadow_data)
  95 {
  96         void *d = obj;
  97         void **shadow_leak = shadow_data;
  98 
  99         kfree(*shadow_leak);
 100         pr_info("%s: dummy @ %p, prevented leak @ %p\n",
 101                          __func__, d, *shadow_leak);
 102 }
 103 
 104 static void livepatch_fix1_dummy_free(struct dummy *d)
 105 {
 106         void **shadow_leak;
 107 
 108         /*
 109          * Patch: fetch the saved SV_LEAK shadow variable, detach and
 110          * free it.  Note: handle cases where this shadow variable does
 111          * not exist (ie, dummy structures allocated before this livepatch
 112          * was loaded.)
 113          */
 114         shadow_leak = klp_shadow_get(d, SV_LEAK);
 115         if (shadow_leak)
 116                 klp_shadow_free(d, SV_LEAK, livepatch_fix1_dummy_leak_dtor);
 117         else
 118                 pr_info("%s: dummy @ %p leaked!\n", __func__, d);
 119 
 120         kfree(d);
 121 }
 122 
 123 static struct klp_func funcs[] = {
 124         {
 125                 .old_name = "dummy_alloc",
 126                 .new_func = livepatch_fix1_dummy_alloc,
 127         },
 128         {
 129                 .old_name = "dummy_free",
 130                 .new_func = livepatch_fix1_dummy_free,
 131         }, { }
 132 };
 133 
 134 static struct klp_object objs[] = {
 135         {
 136                 .name = "livepatch_shadow_mod",
 137                 .funcs = funcs,
 138         }, { }
 139 };
 140 
 141 static struct klp_patch patch = {
 142         .mod = THIS_MODULE,
 143         .objs = objs,
 144 };
 145 
 146 static int livepatch_shadow_fix1_init(void)
 147 {
 148         return klp_enable_patch(&patch);
 149 }
 150 
 151 static void livepatch_shadow_fix1_exit(void)
 152 {
 153         /* Cleanup any existing SV_LEAK shadow variables */
 154         klp_shadow_free_all(SV_LEAK, livepatch_fix1_dummy_leak_dtor);
 155 }
 156 
 157 module_init(livepatch_shadow_fix1_init);
 158 module_exit(livepatch_shadow_fix1_exit);
 159 MODULE_LICENSE("GPL");
 160 MODULE_INFO(livepatch, "Y");

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