Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright (C) 2017 Joe Lawrence <joe.lawrence@redhat.com>
0004  */
0005 
0006 /*
0007  * livepatch-shadow-fix1.c - Shadow variables, livepatch demo
0008  *
0009  * Purpose
0010  * -------
0011  *
0012  * Fixes the memory leak introduced in livepatch-shadow-mod through the
0013  * use of a shadow variable.  This fix demonstrates the "extending" of
0014  * short-lived data structures by patching its allocation and release
0015  * functions.
0016  *
0017  *
0018  * Usage
0019  * -----
0020  *
0021  * This module is not intended to be standalone.  See the "Usage"
0022  * section of livepatch-shadow-mod.c.
0023  */
0024 
0025 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0026 
0027 #include <linux/module.h>
0028 #include <linux/kernel.h>
0029 #include <linux/livepatch.h>
0030 #include <linux/slab.h>
0031 
0032 /* Shadow variable enums */
0033 #define SV_LEAK     1
0034 
0035 /* Allocate new dummies every second */
0036 #define ALLOC_PERIOD    1
0037 /* Check for expired dummies after a few new ones have been allocated */
0038 #define CLEANUP_PERIOD  (3 * ALLOC_PERIOD)
0039 /* Dummies expire after a few cleanup instances */
0040 #define EXPIRE_PERIOD   (4 * CLEANUP_PERIOD)
0041 
0042 struct dummy {
0043     struct list_head list;
0044     unsigned long jiffies_expire;
0045 };
0046 
0047 /*
0048  * The constructor makes more sense together with klp_shadow_get_or_alloc().
0049  * In this example, it would be safe to assign the pointer also to the shadow
0050  * variable returned by klp_shadow_alloc().  But we wanted to show the more
0051  * complicated use of the API.
0052  */
0053 static int shadow_leak_ctor(void *obj, void *shadow_data, void *ctor_data)
0054 {
0055     int **shadow_leak = shadow_data;
0056     int **leak = ctor_data;
0057 
0058     if (!ctor_data)
0059         return -EINVAL;
0060 
0061     *shadow_leak = *leak;
0062     return 0;
0063 }
0064 
0065 static struct dummy *livepatch_fix1_dummy_alloc(void)
0066 {
0067     struct dummy *d;
0068     int *leak;
0069     int **shadow_leak;
0070 
0071     d = kzalloc(sizeof(*d), GFP_KERNEL);
0072     if (!d)
0073         return NULL;
0074 
0075     d->jiffies_expire = jiffies +
0076         msecs_to_jiffies(1000 * EXPIRE_PERIOD);
0077 
0078     /*
0079      * Patch: save the extra memory location into a SV_LEAK shadow
0080      * variable.  A patched dummy_free routine can later fetch this
0081      * pointer to handle resource release.
0082      */
0083     leak = kzalloc(sizeof(*leak), GFP_KERNEL);
0084     if (!leak)
0085         goto err_leak;
0086 
0087     shadow_leak = klp_shadow_alloc(d, SV_LEAK, sizeof(leak), GFP_KERNEL,
0088                        shadow_leak_ctor, &leak);
0089     if (!shadow_leak) {
0090         pr_err("%s: failed to allocate shadow variable for the leaking pointer: dummy @ %p, leak @ %p\n",
0091                __func__, d, leak);
0092         goto err_shadow;
0093     }
0094 
0095     pr_info("%s: dummy @ %p, expires @ %lx\n",
0096         __func__, d, d->jiffies_expire);
0097 
0098     return d;
0099 
0100 err_shadow:
0101     kfree(leak);
0102 err_leak:
0103     kfree(d);
0104     return NULL;
0105 }
0106 
0107 static void livepatch_fix1_dummy_leak_dtor(void *obj, void *shadow_data)
0108 {
0109     void *d = obj;
0110     int **shadow_leak = shadow_data;
0111 
0112     pr_info("%s: dummy @ %p, prevented leak @ %p\n",
0113              __func__, d, *shadow_leak);
0114     kfree(*shadow_leak);
0115 }
0116 
0117 static void livepatch_fix1_dummy_free(struct dummy *d)
0118 {
0119     int **shadow_leak;
0120 
0121     /*
0122      * Patch: fetch the saved SV_LEAK shadow variable, detach and
0123      * free it.  Note: handle cases where this shadow variable does
0124      * not exist (ie, dummy structures allocated before this livepatch
0125      * was loaded.)
0126      */
0127     shadow_leak = klp_shadow_get(d, SV_LEAK);
0128     if (shadow_leak)
0129         klp_shadow_free(d, SV_LEAK, livepatch_fix1_dummy_leak_dtor);
0130     else
0131         pr_info("%s: dummy @ %p leaked!\n", __func__, d);
0132 
0133     kfree(d);
0134 }
0135 
0136 static struct klp_func funcs[] = {
0137     {
0138         .old_name = "dummy_alloc",
0139         .new_func = livepatch_fix1_dummy_alloc,
0140     },
0141     {
0142         .old_name = "dummy_free",
0143         .new_func = livepatch_fix1_dummy_free,
0144     }, { }
0145 };
0146 
0147 static struct klp_object objs[] = {
0148     {
0149         .name = "livepatch_shadow_mod",
0150         .funcs = funcs,
0151     }, { }
0152 };
0153 
0154 static struct klp_patch patch = {
0155     .mod = THIS_MODULE,
0156     .objs = objs,
0157 };
0158 
0159 static int livepatch_shadow_fix1_init(void)
0160 {
0161     return klp_enable_patch(&patch);
0162 }
0163 
0164 static void livepatch_shadow_fix1_exit(void)
0165 {
0166     /* Cleanup any existing SV_LEAK shadow variables */
0167     klp_shadow_free_all(SV_LEAK, livepatch_fix1_dummy_leak_dtor);
0168 }
0169 
0170 module_init(livepatch_shadow_fix1_init);
0171 module_exit(livepatch_shadow_fix1_exit);
0172 MODULE_LICENSE("GPL");
0173 MODULE_INFO(livepatch, "Y");