~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/samples/livepatch/livepatch-shadow-mod.c

Version: ~ [ linux-5.1-rc2 ] ~ [ linux-5.0.4 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.31 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.108 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.165 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.177 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.137 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.63 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.39.4 ] ~ [ linux-2.6.38.8 ] ~ [ linux-2.6.37.6 ] ~ [ linux-2.6.36.4 ] ~ [ linux-2.6.35.14 ] ~ [ linux-2.6.34.15 ] ~ [ linux-2.6.33.20 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * Copyright (C) 2017 Joe Lawrence <joe.lawrence@redhat.com>
  3  *
  4  * This program is free software; you can redistribute it and/or
  5  * modify it under the terms of the GNU General Public License
  6  * as published by the Free Software Foundation; either version 2
  7  * of the License, or (at your option) any later version.
  8  *
  9  * This program is distributed in the hope that it will be useful,
 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12  * GNU General Public License for more details.
 13  *
 14  * You should have received a copy of the GNU General Public License
 15  * along with this program; if not, see <http://www.gnu.org/licenses/>.
 16  */
 17 
 18 /*
 19  * livepatch-shadow-mod.c - Shadow variables, buggy module demo
 20  *
 21  * Purpose
 22  * -------
 23  *
 24  * As a demonstration of livepatch shadow variable API, this module
 25  * introduces memory leak behavior that livepatch modules
 26  * livepatch-shadow-fix1.ko and livepatch-shadow-fix2.ko correct and
 27  * enhance.
 28  *
 29  * WARNING - even though the livepatch-shadow-fix modules patch the
 30  * memory leak, please load these modules at your own risk -- some
 31  * amount of memory may leaked before the bug is patched.
 32  *
 33  *
 34  * Usage
 35  * -----
 36  *
 37  * Step 1 - Load the buggy demonstration module:
 38  *
 39  *   insmod samples/livepatch/livepatch-shadow-mod.ko
 40  *
 41  * Watch dmesg output for a few moments to see new dummy being allocated
 42  * and a periodic cleanup check.  (Note: a small amount of memory is
 43  * being leaked.)
 44  *
 45  *
 46  * Step 2 - Load livepatch fix1:
 47  *
 48  *   insmod samples/livepatch/livepatch-shadow-fix1.ko
 49  *
 50  * Continue watching dmesg and note that now livepatch_fix1_dummy_free()
 51  * and livepatch_fix1_dummy_alloc() are logging messages about leaked
 52  * memory and eventually leaks prevented.
 53  *
 54  *
 55  * Step 3 - Load livepatch fix2 (on top of fix1):
 56  *
 57  *   insmod samples/livepatch/livepatch-shadow-fix2.ko
 58  *
 59  * This module extends functionality through shadow variables, as a new
 60  * "check" counter is added to the dummy structure.  Periodic dmesg
 61  * messages will log these as dummies are cleaned up.
 62  *
 63  *
 64  * Step 4 - Cleanup
 65  *
 66  * Unwind the demonstration by disabling the livepatch fix modules, then
 67  * removing them and the demo module:
 68  *
 69  *   echo 0 > /sys/kernel/livepatch/livepatch_shadow_fix2/enabled
 70  *   echo 0 > /sys/kernel/livepatch/livepatch_shadow_fix1/enabled
 71  *   rmmod livepatch-shadow-fix2
 72  *   rmmod livepatch-shadow-fix1
 73  *   rmmod livepatch-shadow-mod
 74  */
 75 
 76 
 77 #include <linux/kernel.h>
 78 #include <linux/module.h>
 79 #include <linux/sched.h>
 80 #include <linux/slab.h>
 81 #include <linux/stat.h>
 82 #include <linux/workqueue.h>
 83 
 84 MODULE_LICENSE("GPL");
 85 MODULE_AUTHOR("Joe Lawrence <joe.lawrence@redhat.com>");
 86 MODULE_DESCRIPTION("Buggy module for shadow variable demo");
 87 
 88 /* Allocate new dummies every second */
 89 #define ALLOC_PERIOD    1
 90 /* Check for expired dummies after a few new ones have been allocated */
 91 #define CLEANUP_PERIOD  (3 * ALLOC_PERIOD)
 92 /* Dummies expire after a few cleanup instances */
 93 #define EXPIRE_PERIOD   (4 * CLEANUP_PERIOD)
 94 
 95 /*
 96  * Keep a list of all the dummies so we can clean up any residual ones
 97  * on module exit
 98  */
 99 LIST_HEAD(dummy_list);
100 DEFINE_MUTEX(dummy_list_mutex);
101 
102 struct dummy {
103         struct list_head list;
104         unsigned long jiffies_expire;
105 };
106 
107 noinline struct dummy *dummy_alloc(void)
108 {
109         struct dummy *d;
110         void *leak;
111 
112         d = kzalloc(sizeof(*d), GFP_KERNEL);
113         if (!d)
114                 return NULL;
115 
116         d->jiffies_expire = jiffies +
117                 msecs_to_jiffies(1000 * EXPIRE_PERIOD);
118 
119         /* Oops, forgot to save leak! */
120         leak = kzalloc(sizeof(int), GFP_KERNEL);
121 
122         pr_info("%s: dummy @ %p, expires @ %lx\n",
123                 __func__, d, d->jiffies_expire);
124 
125         return d;
126 }
127 
128 noinline void dummy_free(struct dummy *d)
129 {
130         pr_info("%s: dummy @ %p, expired = %lx\n",
131                 __func__, d, d->jiffies_expire);
132 
133         kfree(d);
134 }
135 
136 noinline bool dummy_check(struct dummy *d, unsigned long jiffies)
137 {
138         return time_after(jiffies, d->jiffies_expire);
139 }
140 
141 /*
142  * alloc_work_func: allocates new dummy structures, allocates additional
143  *                  memory, aptly named "leak", but doesn't keep
144  *                  permanent record of it.
145  */
146 
147 static void alloc_work_func(struct work_struct *work);
148 static DECLARE_DELAYED_WORK(alloc_dwork, alloc_work_func);
149 
150 static void alloc_work_func(struct work_struct *work)
151 {
152         struct dummy *d;
153 
154         d = dummy_alloc();
155         if (!d)
156                 return;
157 
158         mutex_lock(&dummy_list_mutex);
159         list_add(&d->list, &dummy_list);
160         mutex_unlock(&dummy_list_mutex);
161 
162         schedule_delayed_work(&alloc_dwork,
163                 msecs_to_jiffies(1000 * ALLOC_PERIOD));
164 }
165 
166 /*
167  * cleanup_work_func: frees dummy structures.  Without knownledge of
168  *                    "leak", it leaks the additional memory that
169  *                    alloc_work_func created.
170  */
171 
172 static void cleanup_work_func(struct work_struct *work);
173 static DECLARE_DELAYED_WORK(cleanup_dwork, cleanup_work_func);
174 
175 static void cleanup_work_func(struct work_struct *work)
176 {
177         struct dummy *d, *tmp;
178         unsigned long j;
179 
180         j = jiffies;
181         pr_info("%s: jiffies = %lx\n", __func__, j);
182 
183         mutex_lock(&dummy_list_mutex);
184         list_for_each_entry_safe(d, tmp, &dummy_list, list) {
185 
186                 /* Kick out and free any expired dummies */
187                 if (dummy_check(d, j)) {
188                         list_del(&d->list);
189                         dummy_free(d);
190                 }
191         }
192         mutex_unlock(&dummy_list_mutex);
193 
194         schedule_delayed_work(&cleanup_dwork,
195                 msecs_to_jiffies(1000 * CLEANUP_PERIOD));
196 }
197 
198 static int livepatch_shadow_mod_init(void)
199 {
200         schedule_delayed_work(&alloc_dwork,
201                 msecs_to_jiffies(1000 * ALLOC_PERIOD));
202         schedule_delayed_work(&cleanup_dwork,
203                 msecs_to_jiffies(1000 * CLEANUP_PERIOD));
204 
205         return 0;
206 }
207 
208 static void livepatch_shadow_mod_exit(void)
209 {
210         struct dummy *d, *tmp;
211 
212         /* Wait for any dummies at work */
213         cancel_delayed_work_sync(&alloc_dwork);
214         cancel_delayed_work_sync(&cleanup_dwork);
215 
216         /* Cleanup residual dummies */
217         list_for_each_entry_safe(d, tmp, &dummy_list, list) {
218                 list_del(&d->list);
219                 dummy_free(d);
220         }
221 }
222 
223 module_init(livepatch_shadow_mod_init);
224 module_exit(livepatch_shadow_mod_exit);
225 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp