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-fix2.c - Shadow variables, livepatch demo
0008  *
0009  * Purpose
0010  * -------
0011  *
0012  * Adds functionality to livepatch-shadow-mod's in-flight data
0013  * structures through a shadow variable.  The livepatch patches a
0014  * routine that periodically inspects data structures, incrementing a
0015  * per-data-structure counter, creating the counter if needed.
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 #define SV_COUNTER  2
0035 
0036 struct dummy {
0037     struct list_head list;
0038     unsigned long jiffies_expire;
0039 };
0040 
0041 static bool livepatch_fix2_dummy_check(struct dummy *d, unsigned long jiffies)
0042 {
0043     int *shadow_count;
0044 
0045     /*
0046      * Patch: handle in-flight dummy structures, if they do not
0047      * already have a SV_COUNTER shadow variable, then attach a
0048      * new one.
0049      */
0050     shadow_count = klp_shadow_get_or_alloc(d, SV_COUNTER,
0051                 sizeof(*shadow_count), GFP_NOWAIT,
0052                 NULL, NULL);
0053     if (shadow_count)
0054         *shadow_count += 1;
0055 
0056     return time_after(jiffies, d->jiffies_expire);
0057 }
0058 
0059 static void livepatch_fix2_dummy_leak_dtor(void *obj, void *shadow_data)
0060 {
0061     void *d = obj;
0062     int **shadow_leak = shadow_data;
0063 
0064     pr_info("%s: dummy @ %p, prevented leak @ %p\n",
0065              __func__, d, *shadow_leak);
0066     kfree(*shadow_leak);
0067 }
0068 
0069 static void livepatch_fix2_dummy_free(struct dummy *d)
0070 {
0071     int **shadow_leak;
0072     int *shadow_count;
0073 
0074     /* Patch: copy the memory leak patch from the fix1 module. */
0075     shadow_leak = klp_shadow_get(d, SV_LEAK);
0076     if (shadow_leak)
0077         klp_shadow_free(d, SV_LEAK, livepatch_fix2_dummy_leak_dtor);
0078     else
0079         pr_info("%s: dummy @ %p leaked!\n", __func__, d);
0080 
0081     /*
0082      * Patch: fetch the SV_COUNTER shadow variable and display
0083      * the final count.  Detach the shadow variable.
0084      */
0085     shadow_count = klp_shadow_get(d, SV_COUNTER);
0086     if (shadow_count) {
0087         pr_info("%s: dummy @ %p, check counter = %d\n",
0088             __func__, d, *shadow_count);
0089         klp_shadow_free(d, SV_COUNTER, NULL);
0090     }
0091 
0092     kfree(d);
0093 }
0094 
0095 static struct klp_func funcs[] = {
0096     {
0097         .old_name = "dummy_check",
0098         .new_func = livepatch_fix2_dummy_check,
0099     },
0100     {
0101         .old_name = "dummy_free",
0102         .new_func = livepatch_fix2_dummy_free,
0103     }, { }
0104 };
0105 
0106 static struct klp_object objs[] = {
0107     {
0108         .name = "livepatch_shadow_mod",
0109         .funcs = funcs,
0110     }, { }
0111 };
0112 
0113 static struct klp_patch patch = {
0114     .mod = THIS_MODULE,
0115     .objs = objs,
0116 };
0117 
0118 static int livepatch_shadow_fix2_init(void)
0119 {
0120     return klp_enable_patch(&patch);
0121 }
0122 
0123 static void livepatch_shadow_fix2_exit(void)
0124 {
0125     /* Cleanup any existing SV_COUNTER shadow variables */
0126     klp_shadow_free_all(SV_COUNTER, NULL);
0127 }
0128 
0129 module_init(livepatch_shadow_fix2_init);
0130 module_exit(livepatch_shadow_fix2_exit);
0131 MODULE_LICENSE("GPL");
0132 MODULE_INFO(livepatch, "Y");