11ccea77eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2439e7271SJoe Lawrence /*
3439e7271SJoe Lawrence  * Copyright (C) 2017 Joe Lawrence <[email protected]>
4439e7271SJoe Lawrence  */
5439e7271SJoe Lawrence 
6439e7271SJoe Lawrence /*
7439e7271SJoe Lawrence  * livepatch-shadow-fix1.c - Shadow variables, livepatch demo
8439e7271SJoe Lawrence  *
9439e7271SJoe Lawrence  * Purpose
10439e7271SJoe Lawrence  * -------
11439e7271SJoe Lawrence  *
12439e7271SJoe Lawrence  * Fixes the memory leak introduced in livepatch-shadow-mod through the
13439e7271SJoe Lawrence  * use of a shadow variable.  This fix demonstrates the "extending" of
14439e7271SJoe Lawrence  * short-lived data structures by patching its allocation and release
15439e7271SJoe Lawrence  * functions.
16439e7271SJoe Lawrence  *
17439e7271SJoe Lawrence  *
18439e7271SJoe Lawrence  * Usage
19439e7271SJoe Lawrence  * -----
20439e7271SJoe Lawrence  *
21439e7271SJoe Lawrence  * This module is not intended to be standalone.  See the "Usage"
22439e7271SJoe Lawrence  * section of livepatch-shadow-mod.c.
23439e7271SJoe Lawrence  */
24439e7271SJoe Lawrence 
25439e7271SJoe Lawrence #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
26439e7271SJoe Lawrence 
27439e7271SJoe Lawrence #include <linux/module.h>
28439e7271SJoe Lawrence #include <linux/kernel.h>
29439e7271SJoe Lawrence #include <linux/livepatch.h>
30439e7271SJoe Lawrence #include <linux/slab.h>
31439e7271SJoe Lawrence 
32439e7271SJoe Lawrence /* Shadow variable enums */
33439e7271SJoe Lawrence #define SV_LEAK		1
34439e7271SJoe Lawrence 
35439e7271SJoe Lawrence /* Allocate new dummies every second */
36439e7271SJoe Lawrence #define ALLOC_PERIOD	1
37439e7271SJoe Lawrence /* Check for expired dummies after a few new ones have been allocated */
38439e7271SJoe Lawrence #define CLEANUP_PERIOD	(3 * ALLOC_PERIOD)
39439e7271SJoe Lawrence /* Dummies expire after a few cleanup instances */
40439e7271SJoe Lawrence #define EXPIRE_PERIOD	(4 * CLEANUP_PERIOD)
41439e7271SJoe Lawrence 
42439e7271SJoe Lawrence struct dummy {
43439e7271SJoe Lawrence 	struct list_head list;
44439e7271SJoe Lawrence 	unsigned long jiffies_expire;
45439e7271SJoe Lawrence };
46439e7271SJoe Lawrence 
47e91c2518SPetr Mladek /*
48e91c2518SPetr Mladek  * The constructor makes more sense together with klp_shadow_get_or_alloc().
49e91c2518SPetr Mladek  * In this example, it would be safe to assign the pointer also to the shadow
50e91c2518SPetr Mladek  * variable returned by klp_shadow_alloc().  But we wanted to show the more
51e91c2518SPetr Mladek  * complicated use of the API.
52e91c2518SPetr Mladek  */
shadow_leak_ctor(void * obj,void * shadow_data,void * ctor_data)53e91c2518SPetr Mladek static int shadow_leak_ctor(void *obj, void *shadow_data, void *ctor_data)
54e91c2518SPetr Mladek {
558f6b8866SPetr Mladek 	int **shadow_leak = shadow_data;
56be6da984SPetr Mladek 	int **leak = ctor_data;
57e91c2518SPetr Mladek 
58be6da984SPetr Mladek 	if (!ctor_data)
59be6da984SPetr Mladek 		return -EINVAL;
60be6da984SPetr Mladek 
61be6da984SPetr Mladek 	*shadow_leak = *leak;
62e91c2518SPetr Mladek 	return 0;
63e91c2518SPetr Mladek }
64e91c2518SPetr Mladek 
livepatch_fix1_dummy_alloc(void)65b73d5dc7SNicholas Mc Guire static struct dummy *livepatch_fix1_dummy_alloc(void)
66439e7271SJoe Lawrence {
67439e7271SJoe Lawrence 	struct dummy *d;
688f6b8866SPetr Mladek 	int *leak;
69f46e49a9SPetr Mladek 	int **shadow_leak;
70439e7271SJoe Lawrence 
71439e7271SJoe Lawrence 	d = kzalloc(sizeof(*d), GFP_KERNEL);
72439e7271SJoe Lawrence 	if (!d)
73439e7271SJoe Lawrence 		return NULL;
74439e7271SJoe Lawrence 
756d072c0bSEaswar Hariharan 	d->jiffies_expire = jiffies + secs_to_jiffies(EXPIRE_PERIOD);
76439e7271SJoe Lawrence 
77439e7271SJoe Lawrence 	/*
78439e7271SJoe Lawrence 	 * Patch: save the extra memory location into a SV_LEAK shadow
79439e7271SJoe Lawrence 	 * variable.  A patched dummy_free routine can later fetch this
80439e7271SJoe Lawrence 	 * pointer to handle resource release.
81439e7271SJoe Lawrence 	 */
828f6b8866SPetr Mladek 	leak = kzalloc(sizeof(*leak), GFP_KERNEL);
83f46e49a9SPetr Mladek 	if (!leak)
84f46e49a9SPetr Mladek 		goto err_leak;
855f30b2e8SNicholas Mc Guire 
86f46e49a9SPetr Mladek 	shadow_leak = klp_shadow_alloc(d, SV_LEAK, sizeof(leak), GFP_KERNEL,
87be6da984SPetr Mladek 				       shadow_leak_ctor, &leak);
88f46e49a9SPetr Mladek 	if (!shadow_leak) {
89f46e49a9SPetr Mladek 		pr_err("%s: failed to allocate shadow variable for the leaking pointer: dummy @ %p, leak @ %p\n",
90f46e49a9SPetr Mladek 		       __func__, d, leak);
91f46e49a9SPetr Mladek 		goto err_shadow;
92f46e49a9SPetr Mladek 	}
93439e7271SJoe Lawrence 
94439e7271SJoe Lawrence 	pr_info("%s: dummy @ %p, expires @ %lx\n",
95439e7271SJoe Lawrence 		__func__, d, d->jiffies_expire);
96439e7271SJoe Lawrence 
97439e7271SJoe Lawrence 	return d;
98f46e49a9SPetr Mladek 
99f46e49a9SPetr Mladek err_shadow:
100f46e49a9SPetr Mladek 	kfree(leak);
101f46e49a9SPetr Mladek err_leak:
102f46e49a9SPetr Mladek 	kfree(d);
103f46e49a9SPetr Mladek 	return NULL;
104439e7271SJoe Lawrence }
105439e7271SJoe Lawrence 
livepatch_fix1_dummy_leak_dtor(void * obj,void * shadow_data)1063b2c77d0SPetr Mladek static void livepatch_fix1_dummy_leak_dtor(void *obj, void *shadow_data)
1073b2c77d0SPetr Mladek {
1083b2c77d0SPetr Mladek 	void *d = obj;
1098f6b8866SPetr Mladek 	int **shadow_leak = shadow_data;
1103b2c77d0SPetr Mladek 
1113b2c77d0SPetr Mladek 	pr_info("%s: dummy @ %p, prevented leak @ %p\n",
1123b2c77d0SPetr Mladek 			 __func__, d, *shadow_leak);
1135e6ded2eSTom Rix 	kfree(*shadow_leak);
1143b2c77d0SPetr Mladek }
1153b2c77d0SPetr Mladek 
livepatch_fix1_dummy_free(struct dummy * d)116b73d5dc7SNicholas Mc Guire static void livepatch_fix1_dummy_free(struct dummy *d)
117439e7271SJoe Lawrence {
1188f6b8866SPetr Mladek 	int **shadow_leak;
119439e7271SJoe Lawrence 
120439e7271SJoe Lawrence 	/*
121439e7271SJoe Lawrence 	 * Patch: fetch the saved SV_LEAK shadow variable, detach and
122439e7271SJoe Lawrence 	 * free it.  Note: handle cases where this shadow variable does
123439e7271SJoe Lawrence 	 * not exist (ie, dummy structures allocated before this livepatch
124439e7271SJoe Lawrence 	 * was loaded.)
125439e7271SJoe Lawrence 	 */
126439e7271SJoe Lawrence 	shadow_leak = klp_shadow_get(d, SV_LEAK);
1273b2c77d0SPetr Mladek 	if (shadow_leak)
1283b2c77d0SPetr Mladek 		klp_shadow_free(d, SV_LEAK, livepatch_fix1_dummy_leak_dtor);
1293b2c77d0SPetr Mladek 	else
130439e7271SJoe Lawrence 		pr_info("%s: dummy @ %p leaked!\n", __func__, d);
131439e7271SJoe Lawrence 
132439e7271SJoe Lawrence 	kfree(d);
133439e7271SJoe Lawrence }
134439e7271SJoe Lawrence 
135439e7271SJoe Lawrence static struct klp_func funcs[] = {
136439e7271SJoe Lawrence 	{
137439e7271SJoe Lawrence 		.old_name = "dummy_alloc",
138439e7271SJoe Lawrence 		.new_func = livepatch_fix1_dummy_alloc,
139439e7271SJoe Lawrence 	},
140439e7271SJoe Lawrence 	{
141439e7271SJoe Lawrence 		.old_name = "dummy_free",
142439e7271SJoe Lawrence 		.new_func = livepatch_fix1_dummy_free,
143439e7271SJoe Lawrence 	}, { }
144439e7271SJoe Lawrence };
145439e7271SJoe Lawrence 
146439e7271SJoe Lawrence static struct klp_object objs[] = {
147439e7271SJoe Lawrence 	{
148439e7271SJoe Lawrence 		.name = "livepatch_shadow_mod",
149439e7271SJoe Lawrence 		.funcs = funcs,
150439e7271SJoe Lawrence 	}, { }
151439e7271SJoe Lawrence };
152439e7271SJoe Lawrence 
153439e7271SJoe Lawrence static struct klp_patch patch = {
154439e7271SJoe Lawrence 	.mod = THIS_MODULE,
155439e7271SJoe Lawrence 	.objs = objs,
156439e7271SJoe Lawrence };
157439e7271SJoe Lawrence 
livepatch_shadow_fix1_init(void)158439e7271SJoe Lawrence static int livepatch_shadow_fix1_init(void)
159439e7271SJoe Lawrence {
160958ef1e3SPetr Mladek 	return klp_enable_patch(&patch);
161439e7271SJoe Lawrence }
162439e7271SJoe Lawrence 
livepatch_shadow_fix1_exit(void)163439e7271SJoe Lawrence static void livepatch_shadow_fix1_exit(void)
164439e7271SJoe Lawrence {
165439e7271SJoe Lawrence 	/* Cleanup any existing SV_LEAK shadow variables */
1663b2c77d0SPetr Mladek 	klp_shadow_free_all(SV_LEAK, livepatch_fix1_dummy_leak_dtor);
167439e7271SJoe Lawrence }
168439e7271SJoe Lawrence 
169439e7271SJoe Lawrence module_init(livepatch_shadow_fix1_init);
170439e7271SJoe Lawrence module_exit(livepatch_shadow_fix1_exit);
171*10764175SArnd Bergmann MODULE_DESCRIPTION("Live patching demo for shadow variables");
172439e7271SJoe Lawrence MODULE_LICENSE("GPL");
173439e7271SJoe Lawrence MODULE_INFO(livepatch, "Y");
174