aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2017-11-15 04:49:14 -0500
committerJiri Kosina <jkosina@suse.cz>2017-11-15 04:49:14 -0500
commitcb65dc7b89043a66d4459a6a811645d43185b5f0 (patch)
tree7246fb9b5a97405520008e6f6984db9bdd126629
parentef8daf8eeb5b8ab6bc356656163d19f20fb827ed (diff)
parent19205da6a0da701787d42ad754edd1ffb514c956 (diff)
Merge branch 'for-4.15/shadow-variables' into for-linus
Shadow variables allow callers to associate new shadow fields to existing data structures. This is intended to be used by livepatch modules seeking to emulate additions to data structure definitions.
-rw-r--r--Documentation/livepatch/shadow-vars.txt192
-rw-r--r--include/linux/livepatch.h8
-rw-r--r--kernel/livepatch/Makefile2
-rw-r--r--kernel/livepatch/shadow.c277
-rw-r--r--samples/Kconfig5
-rw-r--r--samples/livepatch/Makefile3
-rw-r--r--samples/livepatch/livepatch-shadow-fix1.c173
-rw-r--r--samples/livepatch/livepatch-shadow-fix2.c168
-rw-r--r--samples/livepatch/livepatch-shadow-mod.c224
9 files changed, 1048 insertions, 4 deletions
diff --git a/Documentation/livepatch/shadow-vars.txt b/Documentation/livepatch/shadow-vars.txt
new file mode 100644
index 000000000000..89c66634d600
--- /dev/null
+++ b/Documentation/livepatch/shadow-vars.txt
@@ -0,0 +1,192 @@
1================
2Shadow Variables
3================
4
5Shadow variables are a simple way for livepatch modules to associate
6additional "shadow" data with existing data structures. Shadow data is
7allocated separately from parent data structures, which are left
8unmodified. The shadow variable API described in this document is used
9to allocate/add and remove/free shadow variables to/from their parents.
10
11The implementation introduces a global, in-kernel hashtable that
12associates pointers to parent objects and a numeric identifier of the
13shadow data. The numeric identifier is a simple enumeration that may be
14used to describe shadow variable version, class or type, etc. More
15specifically, the parent pointer serves as the hashtable key while the
16numeric id subsequently filters hashtable queries. Multiple shadow
17variables may attach to the same parent object, but their numeric
18identifier distinguishes between them.
19
20
211. Brief API summary
22====================
23
24(See the full API usage docbook notes in livepatch/shadow.c.)
25
26A hashtable references all shadow variables. These references are
27stored and retrieved through a <obj, id> pair.
28
29* The klp_shadow variable data structure encapsulates both tracking
30meta-data and shadow-data:
31 - meta-data
32 - obj - pointer to parent object
33 - id - data identifier
34 - data[] - storage for shadow data
35
36It is important to note that the klp_shadow_alloc() and
37klp_shadow_get_or_alloc() calls, described below, store a *copy* of the
38data that the functions are provided. Callers should provide whatever
39mutual exclusion is required of the shadow data.
40
41* klp_shadow_get() - retrieve a shadow variable data pointer
42 - search hashtable for <obj, id> pair
43
44* klp_shadow_alloc() - allocate and add a new shadow variable
45 - search hashtable for <obj, id> pair
46 - if exists
47 - WARN and return NULL
48 - if <obj, id> doesn't already exist
49 - allocate a new shadow variable
50 - copy data into the new shadow variable
51 - add <obj, id> to the global hashtable
52
53* klp_shadow_get_or_alloc() - get existing or alloc a new shadow variable
54 - search hashtable for <obj, id> pair
55 - if exists
56 - return existing shadow variable
57 - if <obj, id> doesn't already exist
58 - allocate a new shadow variable
59 - copy data into the new shadow variable
60 - add <obj, id> pair to the global hashtable
61
62* klp_shadow_free() - detach and free a <obj, id> shadow variable
63 - find and remove a <obj, id> reference from global hashtable
64 - if found, free shadow variable
65
66* klp_shadow_free_all() - detach and free all <*, id> shadow variables
67 - find and remove any <*, id> references from global hashtable
68 - if found, free shadow variable
69
70
712. Use cases
72============
73
74(See the example shadow variable livepatch modules in samples/livepatch/
75for full working demonstrations.)
76
77For the following use-case examples, consider commit 1d147bfa6429
78("mac80211: fix AP powersave TX vs. wakeup race"), which added a
79spinlock to net/mac80211/sta_info.h :: struct sta_info. Each use-case
80example can be considered a stand-alone livepatch implementation of this
81fix.
82
83
84Matching parent's lifecycle
85---------------------------
86
87If parent data structures are frequently created and destroyed, it may
88be easiest to align their shadow variables lifetimes to the same
89allocation and release functions. In this case, the parent data
90structure is typically allocated, initialized, then registered in some
91manner. Shadow variable allocation and setup can then be considered
92part of the parent's initialization and should be completed before the
93parent "goes live" (ie, any shadow variable get-API requests are made
94for this <obj, id> pair.)
95
96For commit 1d147bfa6429, when a parent sta_info structure is allocated,
97allocate a shadow copy of the ps_lock pointer, then initialize it:
98
99#define PS_LOCK 1
100struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
101 const u8 *addr, gfp_t gfp)
102{
103 struct sta_info *sta;
104 spinlock_t *ps_lock;
105
106 /* Parent structure is created */
107 sta = kzalloc(sizeof(*sta) + hw->sta_data_size, gfp);
108
109 /* Attach a corresponding shadow variable, then initialize it */
110 ps_lock = klp_shadow_alloc(sta, PS_LOCK, NULL, sizeof(*ps_lock), gfp);
111 if (!ps_lock)
112 goto shadow_fail;
113 spin_lock_init(ps_lock);
114 ...
115
116When requiring a ps_lock, query the shadow variable API to retrieve one
117for a specific struct sta_info:
118
119void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
120{
121 spinlock_t *ps_lock;
122
123 /* sync with ieee80211_tx_h_unicast_ps_buf */
124 ps_lock = klp_shadow_get(sta, PS_LOCK);
125 if (ps_lock)
126 spin_lock(ps_lock);
127 ...
128
129When the parent sta_info structure is freed, first free the shadow
130variable:
131
132void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
133{
134 klp_shadow_free(sta, PS_LOCK);
135 kfree(sta);
136 ...
137
138
139In-flight parent objects
140------------------------
141
142Sometimes it may not be convenient or possible to allocate shadow
143variables alongside their parent objects. Or a livepatch fix may
144require shadow varibles to only a subset of parent object instances. In
145these cases, the klp_shadow_get_or_alloc() call can be used to attach
146shadow variables to parents already in-flight.
147
148For commit 1d147bfa6429, a good spot to allocate a shadow spinlock is
149inside ieee80211_sta_ps_deliver_wakeup():
150
151#define PS_LOCK 1
152void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
153{
154 DEFINE_SPINLOCK(ps_lock_fallback);
155 spinlock_t *ps_lock;
156
157 /* sync with ieee80211_tx_h_unicast_ps_buf */
158 ps_lock = klp_shadow_get_or_alloc(sta, PS_LOCK,
159 &ps_lock_fallback, sizeof(ps_lock_fallback),
160 GFP_ATOMIC);
161 if (ps_lock)
162 spin_lock(ps_lock);
163 ...
164
165This usage will create a shadow variable, only if needed, otherwise it
166will use one that was already created for this <obj, id> pair.
167
168Like the previous use-case, the shadow spinlock needs to be cleaned up.
169A shadow variable can be freed just before its parent object is freed,
170or even when the shadow variable itself is no longer required.
171
172
173Other use-cases
174---------------
175
176Shadow variables can also be used as a flag indicating that a data
177structure was allocated by new, livepatched code. In this case, it
178doesn't matter what data value the shadow variable holds, its existence
179suggests how to handle the parent object.
180
181
1823. References
183=============
184
185* https://github.com/dynup/kpatch
186The livepatch implementation is based on the kpatch version of shadow
187variables.
188
189* http://files.mkgnu.net/files/dynamos/doc/papers/dynamos_eurosys_07.pdf
190Dynamic and Adaptive Updates of Non-Quiescent Subsystems in Commodity
191Operating System Kernels (Kritis Makris, Kyung Dong Ryu 2007) presented
192a datatype update technique called "shadow data structures".
diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
index 194991ef9347..d08eddc00497 100644
--- a/include/linux/livepatch.h
+++ b/include/linux/livepatch.h
@@ -164,6 +164,14 @@ static inline bool klp_have_reliable_stack(void)
164 IS_ENABLED(CONFIG_HAVE_RELIABLE_STACKTRACE); 164 IS_ENABLED(CONFIG_HAVE_RELIABLE_STACKTRACE);
165} 165}
166 166
167void *klp_shadow_get(void *obj, unsigned long id);
168void *klp_shadow_alloc(void *obj, unsigned long id, void *data,
169 size_t size, gfp_t gfp_flags);
170void *klp_shadow_get_or_alloc(void *obj, unsigned long id, void *data,
171 size_t size, gfp_t gfp_flags);
172void klp_shadow_free(void *obj, unsigned long id);
173void klp_shadow_free_all(unsigned long id);
174
167#else /* !CONFIG_LIVEPATCH */ 175#else /* !CONFIG_LIVEPATCH */
168 176
169static inline int klp_module_coming(struct module *mod) { return 0; } 177static inline int klp_module_coming(struct module *mod) { return 0; }
diff --git a/kernel/livepatch/Makefile b/kernel/livepatch/Makefile
index 2b8bdb1925da..b36ceda6488e 100644
--- a/kernel/livepatch/Makefile
+++ b/kernel/livepatch/Makefile
@@ -1,3 +1,3 @@
1obj-$(CONFIG_LIVEPATCH) += livepatch.o 1obj-$(CONFIG_LIVEPATCH) += livepatch.o
2 2
3livepatch-objs := core.o patch.o transition.o 3livepatch-objs := core.o patch.o shadow.o transition.o
diff --git a/kernel/livepatch/shadow.c b/kernel/livepatch/shadow.c
new file mode 100644
index 000000000000..fdac27588d60
--- /dev/null
+++ b/kernel/livepatch/shadow.c
@@ -0,0 +1,277 @@
1/*
2 * shadow.c - Shadow Variables
3 *
4 * Copyright (C) 2014 Josh Poimboeuf <jpoimboe@redhat.com>
5 * Copyright (C) 2014 Seth Jennings <sjenning@redhat.com>
6 * Copyright (C) 2017 Joe Lawrence <joe.lawrence@redhat.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 */
21
22/**
23 * DOC: Shadow variable API concurrency notes:
24 *
25 * The shadow variable API provides a simple relationship between an
26 * <obj, id> pair and a pointer value. It is the responsibility of the
27 * caller to provide any mutual exclusion required of the shadow data.
28 *
29 * Once a shadow variable is attached to its parent object via the
30 * klp_shadow_*alloc() API calls, it is considered live: any subsequent
31 * call to klp_shadow_get() may then return the shadow variable's data
32 * pointer. Callers of klp_shadow_*alloc() should prepare shadow data
33 * accordingly.
34 *
35 * The klp_shadow_*alloc() API calls may allocate memory for new shadow
36 * variable structures. Their implementation does not call kmalloc
37 * inside any spinlocks, but API callers should pass GFP flags according
38 * to their specific needs.
39 *
40 * The klp_shadow_hash is an RCU-enabled hashtable and is safe against
41 * concurrent klp_shadow_free() and klp_shadow_get() operations.
42 */
43
44#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
45
46#include <linux/hashtable.h>
47#include <linux/slab.h>
48#include <linux/livepatch.h>
49
50static DEFINE_HASHTABLE(klp_shadow_hash, 12);
51
52/*
53 * klp_shadow_lock provides exclusive access to the klp_shadow_hash and
54 * the shadow variables it references.
55 */
56static DEFINE_SPINLOCK(klp_shadow_lock);
57
58/**
59 * struct klp_shadow - shadow variable structure
60 * @node: klp_shadow_hash hash table node
61 * @rcu_head: RCU is used to safely free this structure
62 * @obj: pointer to parent object
63 * @id: data identifier
64 * @data: data area
65 */
66struct klp_shadow {
67 struct hlist_node node;
68 struct rcu_head rcu_head;
69 void *obj;
70 unsigned long id;
71 char data[];
72};
73
74/**
75 * klp_shadow_match() - verify a shadow variable matches given <obj, id>
76 * @shadow: shadow variable to match
77 * @obj: pointer to parent object
78 * @id: data identifier
79 *
80 * Return: true if the shadow variable matches.
81 */
82static inline bool klp_shadow_match(struct klp_shadow *shadow, void *obj,
83 unsigned long id)
84{
85 return shadow->obj == obj && shadow->id == id;
86}
87
88/**
89 * klp_shadow_get() - retrieve a shadow variable data pointer
90 * @obj: pointer to parent object
91 * @id: data identifier
92 *
93 * Return: the shadow variable data element, NULL on failure.
94 */
95void *klp_shadow_get(void *obj, unsigned long id)
96{
97 struct klp_shadow *shadow;
98
99 rcu_read_lock();
100
101 hash_for_each_possible_rcu(klp_shadow_hash, shadow, node,
102 (unsigned long)obj) {
103
104 if (klp_shadow_match(shadow, obj, id)) {
105 rcu_read_unlock();
106 return shadow->data;
107 }
108 }
109
110 rcu_read_unlock();
111
112 return NULL;
113}
114EXPORT_SYMBOL_GPL(klp_shadow_get);
115
116static void *__klp_shadow_get_or_alloc(void *obj, unsigned long id, void *data,
117 size_t size, gfp_t gfp_flags, bool warn_on_exist)
118{
119 struct klp_shadow *new_shadow;
120 void *shadow_data;
121 unsigned long flags;
122
123 /* Check if the shadow variable already exists */
124 shadow_data = klp_shadow_get(obj, id);
125 if (shadow_data)
126 goto exists;
127
128 /* Allocate a new shadow variable for use inside the lock below */
129 new_shadow = kzalloc(size + sizeof(*new_shadow), gfp_flags);
130 if (!new_shadow)
131 return NULL;
132
133 new_shadow->obj = obj;
134 new_shadow->id = id;
135
136 /* Initialize the shadow variable if data provided */
137 if (data)
138 memcpy(new_shadow->data, data, size);
139
140 /* Look for <obj, id> again under the lock */
141 spin_lock_irqsave(&klp_shadow_lock, flags);
142 shadow_data = klp_shadow_get(obj, id);
143 if (unlikely(shadow_data)) {
144 /*
145 * Shadow variable was found, throw away speculative
146 * allocation.
147 */
148 spin_unlock_irqrestore(&klp_shadow_lock, flags);
149 kfree(new_shadow);
150 goto exists;
151 }
152
153 /* No <obj, id> found, so attach the newly allocated one */
154 hash_add_rcu(klp_shadow_hash, &new_shadow->node,
155 (unsigned long)new_shadow->obj);
156 spin_unlock_irqrestore(&klp_shadow_lock, flags);
157
158 return new_shadow->data;
159
160exists:
161 if (warn_on_exist) {
162 WARN(1, "Duplicate shadow variable <%p, %lx>\n", obj, id);
163 return NULL;
164 }
165
166 return shadow_data;
167}
168
169/**
170 * klp_shadow_alloc() - allocate and add a new shadow variable
171 * @obj: pointer to parent object
172 * @id: data identifier
173 * @data: pointer to data to attach to parent
174 * @size: size of attached data
175 * @gfp_flags: GFP mask for allocation
176 *
177 * Allocates @size bytes for new shadow variable data using @gfp_flags
178 * and copies @size bytes from @data into the new shadow variable's own
179 * data space. If @data is NULL, @size bytes are still allocated, but
180 * no copy is performed. The new shadow variable is then added to the
181 * global hashtable.
182 *
183 * If an existing <obj, id> shadow variable can be found, this routine
184 * will issue a WARN, exit early and return NULL.
185 *
186 * Return: the shadow variable data element, NULL on duplicate or
187 * failure.
188 */
189void *klp_shadow_alloc(void *obj, unsigned long id, void *data,
190 size_t size, gfp_t gfp_flags)
191{
192 return __klp_shadow_get_or_alloc(obj, id, data, size, gfp_flags, true);
193}
194EXPORT_SYMBOL_GPL(klp_shadow_alloc);
195
196/**
197 * klp_shadow_get_or_alloc() - get existing or allocate a new shadow variable
198 * @obj: pointer to parent object
199 * @id: data identifier
200 * @data: pointer to data to attach to parent
201 * @size: size of attached data
202 * @gfp_flags: GFP mask for allocation
203 *
204 * Returns a pointer to existing shadow data if an <obj, id> shadow
205 * variable is already present. Otherwise, it creates a new shadow
206 * variable like klp_shadow_alloc().
207 *
208 * This function guarantees that only one shadow variable exists with
209 * the given @id for the given @obj. It also guarantees that the shadow
210 * variable will be initialized by the given @data only when it did not
211 * exist before.
212 *
213 * Return: the shadow variable data element, NULL on failure.
214 */
215void *klp_shadow_get_or_alloc(void *obj, unsigned long id, void *data,
216 size_t size, gfp_t gfp_flags)
217{
218 return __klp_shadow_get_or_alloc(obj, id, data, size, gfp_flags, false);
219}
220EXPORT_SYMBOL_GPL(klp_shadow_get_or_alloc);
221
222/**
223 * klp_shadow_free() - detach and free a <obj, id> shadow variable
224 * @obj: pointer to parent object
225 * @id: data identifier
226 *
227 * This function releases the memory for this <obj, id> shadow variable
228 * instance, callers should stop referencing it accordingly.
229 */
230void klp_shadow_free(void *obj, unsigned long id)
231{
232 struct klp_shadow *shadow;
233 unsigned long flags;
234
235 spin_lock_irqsave(&klp_shadow_lock, flags);
236
237 /* Delete <obj, id> from hash */
238 hash_for_each_possible(klp_shadow_hash, shadow, node,
239 (unsigned long)obj) {
240
241 if (klp_shadow_match(shadow, obj, id)) {
242 hash_del_rcu(&shadow->node);
243 kfree_rcu(shadow, rcu_head);
244 break;
245 }
246 }
247
248 spin_unlock_irqrestore(&klp_shadow_lock, flags);
249}
250EXPORT_SYMBOL_GPL(klp_shadow_free);
251
252/**
253 * klp_shadow_free_all() - detach and free all <*, id> shadow variables
254 * @id: data identifier
255 *
256 * This function releases the memory for all <*, id> shadow variable
257 * instances, callers should stop referencing them accordingly.
258 */
259void klp_shadow_free_all(unsigned long id)
260{
261 struct klp_shadow *shadow;
262 unsigned long flags;
263 int i;
264
265 spin_lock_irqsave(&klp_shadow_lock, flags);
266
267 /* Delete all <*, id> from hash */
268 hash_for_each(klp_shadow_hash, i, shadow, node) {
269 if (klp_shadow_match(shadow, shadow->obj, id)) {
270 hash_del_rcu(&shadow->node);
271 kfree_rcu(shadow, rcu_head);
272 }
273 }
274
275 spin_unlock_irqrestore(&klp_shadow_lock, flags);
276}
277EXPORT_SYMBOL_GPL(klp_shadow_free_all);
diff --git a/samples/Kconfig b/samples/Kconfig
index 9cb63188d3ef..c332a3b9de05 100644
--- a/samples/Kconfig
+++ b/samples/Kconfig
@@ -71,11 +71,10 @@ config SAMPLE_RPMSG_CLIENT
71 the rpmsg bus. 71 the rpmsg bus.
72 72
73config SAMPLE_LIVEPATCH 73config SAMPLE_LIVEPATCH
74 tristate "Build live patching sample -- loadable modules only" 74 tristate "Build live patching samples -- loadable modules only"
75 depends on LIVEPATCH && m 75 depends on LIVEPATCH && m
76 help 76 help
77 Builds a sample live patch that replaces the procfs handler 77 Build sample live patch demonstrations.
78 for /proc/cmdline to print "this has been live patched".
79 78
80config SAMPLE_CONFIGFS 79config SAMPLE_CONFIGFS
81 tristate "Build configfs patching sample -- loadable modules only" 80 tristate "Build configfs patching sample -- loadable modules only"
diff --git a/samples/livepatch/Makefile b/samples/livepatch/Makefile
index 10319d7ea0b1..539e81d433cd 100644
--- a/samples/livepatch/Makefile
+++ b/samples/livepatch/Makefile
@@ -1 +1,4 @@
1obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch-sample.o 1obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch-sample.o
2obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch-shadow-mod.o
3obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch-shadow-fix1.o
4obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch-shadow-fix2.o
diff --git a/samples/livepatch/livepatch-shadow-fix1.c b/samples/livepatch/livepatch-shadow-fix1.c
new file mode 100644
index 000000000000..fbe0a1f3d99b
--- /dev/null
+++ b/samples/livepatch/livepatch-shadow-fix1.c
@@ -0,0 +1,173 @@
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-fix1.c - Shadow variables, livepatch demo
20 *
21 * Purpose
22 * -------
23 *
24 * Fixes the memory leak introduced in livepatch-shadow-mod through the
25 * use of a shadow variable. This fix demonstrates the "extending" of
26 * short-lived data structures by patching its allocation and release
27 * functions.
28 *
29 *
30 * Usage
31 * -----
32 *
33 * This module is not intended to be standalone. See the "Usage"
34 * section of livepatch-shadow-mod.c.
35 */
36
37#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
38
39#include <linux/module.h>
40#include <linux/kernel.h>
41#include <linux/livepatch.h>
42#include <linux/slab.h>
43
44/* Shadow variable enums */
45#define SV_LEAK 1
46
47/* Allocate new dummies every second */
48#define ALLOC_PERIOD 1
49/* Check for expired dummies after a few new ones have been allocated */
50#define CLEANUP_PERIOD (3 * ALLOC_PERIOD)
51/* Dummies expire after a few cleanup instances */
52#define EXPIRE_PERIOD (4 * CLEANUP_PERIOD)
53
54struct dummy {
55 struct list_head list;
56 unsigned long jiffies_expire;
57};
58
59struct dummy *livepatch_fix1_dummy_alloc(void)
60{
61 struct dummy *d;
62 void *leak;
63
64 d = kzalloc(sizeof(*d), GFP_KERNEL);
65 if (!d)
66 return NULL;
67
68 d->jiffies_expire = jiffies +
69 msecs_to_jiffies(1000 * EXPIRE_PERIOD);
70
71 /*
72 * Patch: save the extra memory location into a SV_LEAK shadow
73 * variable. A patched dummy_free routine can later fetch this
74 * pointer to handle resource release.
75 */
76 leak = kzalloc(sizeof(int), GFP_KERNEL);
77 klp_shadow_alloc(d, SV_LEAK, &leak, sizeof(leak), GFP_KERNEL);
78
79 pr_info("%s: dummy @ %p, expires @ %lx\n",
80 __func__, d, d->jiffies_expire);
81
82 return d;
83}
84
85void livepatch_fix1_dummy_free(struct dummy *d)
86{
87 void **shadow_leak, *leak;
88
89 /*
90 * Patch: fetch the saved SV_LEAK shadow variable, detach and
91 * free it. Note: handle cases where this shadow variable does
92 * not exist (ie, dummy structures allocated before this livepatch
93 * was loaded.)
94 */
95 shadow_leak = klp_shadow_get(d, SV_LEAK);
96 if (shadow_leak) {
97 leak = *shadow_leak;
98 klp_shadow_free(d, SV_LEAK);
99 kfree(leak);
100 pr_info("%s: dummy @ %p, prevented leak @ %p\n",
101 __func__, d, leak);
102 } else {
103 pr_info("%s: dummy @ %p leaked!\n", __func__, d);
104 }
105
106 kfree(d);
107}
108
109static struct klp_func funcs[] = {
110 {
111 .old_name = "dummy_alloc",
112 .new_func = livepatch_fix1_dummy_alloc,
113 },
114 {
115 .old_name = "dummy_free",
116 .new_func = livepatch_fix1_dummy_free,
117 }, { }
118};
119
120static struct klp_object objs[] = {
121 {
122 .name = "livepatch_shadow_mod",
123 .funcs = funcs,
124 }, { }
125};
126
127static struct klp_patch patch = {
128 .mod = THIS_MODULE,
129 .objs = objs,
130};
131
132static int livepatch_shadow_fix1_init(void)
133{
134 int ret;
135
136 if (!klp_have_reliable_stack() && !patch.immediate) {
137 /*
138 * WARNING: Be very careful when using 'patch.immediate' in
139 * your patches. It's ok to use it for simple patches like
140 * this, but for more complex patches which change function
141 * semantics, locking semantics, or data structures, it may not
142 * be safe. Use of this option will also prevent removal of
143 * the patch.
144 *
145 * See Documentation/livepatch/livepatch.txt for more details.
146 */
147 patch.immediate = true;
148 pr_notice("The consistency model isn't supported for your architecture. Bypassing safety mechanisms and applying the patch immediately.\n");
149 }
150
151 ret = klp_register_patch(&patch);
152 if (ret)
153 return ret;
154 ret = klp_enable_patch(&patch);
155 if (ret) {
156 WARN_ON(klp_unregister_patch(&patch));
157 return ret;
158 }
159 return 0;
160}
161
162static void livepatch_shadow_fix1_exit(void)
163{
164 /* Cleanup any existing SV_LEAK shadow variables */
165 klp_shadow_free_all(SV_LEAK);
166
167 WARN_ON(klp_unregister_patch(&patch));
168}
169
170module_init(livepatch_shadow_fix1_init);
171module_exit(livepatch_shadow_fix1_exit);
172MODULE_LICENSE("GPL");
173MODULE_INFO(livepatch, "Y");
diff --git a/samples/livepatch/livepatch-shadow-fix2.c b/samples/livepatch/livepatch-shadow-fix2.c
new file mode 100644
index 000000000000..53c1794bdc5f
--- /dev/null
+++ b/samples/livepatch/livepatch-shadow-fix2.c
@@ -0,0 +1,168 @@
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-fix2.c - Shadow variables, livepatch demo
20 *
21 * Purpose
22 * -------
23 *
24 * Adds functionality to livepatch-shadow-mod's in-flight data
25 * structures through a shadow variable. The livepatch patches a
26 * routine that periodically inspects data structures, incrementing a
27 * per-data-structure counter, creating the counter if needed.
28 *
29 *
30 * Usage
31 * -----
32 *
33 * This module is not intended to be standalone. See the "Usage"
34 * section of livepatch-shadow-mod.c.
35 */
36
37#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
38
39#include <linux/module.h>
40#include <linux/kernel.h>
41#include <linux/livepatch.h>
42#include <linux/slab.h>
43
44/* Shadow variable enums */
45#define SV_LEAK 1
46#define SV_COUNTER 2
47
48struct dummy {
49 struct list_head list;
50 unsigned long jiffies_expire;
51};
52
53bool livepatch_fix2_dummy_check(struct dummy *d, unsigned long jiffies)
54{
55 int *shadow_count;
56 int count;
57
58 /*
59 * Patch: handle in-flight dummy structures, if they do not
60 * already have a SV_COUNTER shadow variable, then attach a
61 * new one.
62 */
63 count = 0;
64 shadow_count = klp_shadow_get_or_alloc(d, SV_COUNTER,
65 &count, sizeof(count),
66 GFP_NOWAIT);
67 if (shadow_count)
68 *shadow_count += 1;
69
70 return time_after(jiffies, d->jiffies_expire);
71}
72
73void livepatch_fix2_dummy_free(struct dummy *d)
74{
75 void **shadow_leak, *leak;
76 int *shadow_count;
77
78 /* Patch: copy the memory leak patch from the fix1 module. */
79 shadow_leak = klp_shadow_get(d, SV_LEAK);
80 if (shadow_leak) {
81 leak = *shadow_leak;
82 klp_shadow_free(d, SV_LEAK);
83 kfree(leak);
84 pr_info("%s: dummy @ %p, prevented leak @ %p\n",
85 __func__, d, leak);
86 } else {
87 pr_info("%s: dummy @ %p leaked!\n", __func__, d);
88 }
89
90 /*
91 * Patch: fetch the SV_COUNTER shadow variable and display
92 * the final count. Detach the shadow variable.
93 */
94 shadow_count = klp_shadow_get(d, SV_COUNTER);
95 if (shadow_count) {
96 pr_info("%s: dummy @ %p, check counter = %d\n",
97 __func__, d, *shadow_count);
98 klp_shadow_free(d, SV_COUNTER);
99 }
100
101 kfree(d);
102}
103
104static struct klp_func funcs[] = {
105 {
106 .old_name = "dummy_check",
107 .new_func = livepatch_fix2_dummy_check,
108 },
109 {
110 .old_name = "dummy_free",
111 .new_func = livepatch_fix2_dummy_free,
112 }, { }
113};
114
115static struct klp_object objs[] = {
116 {
117 .name = "livepatch_shadow_mod",
118 .funcs = funcs,
119 }, { }
120};
121
122static struct klp_patch patch = {
123 .mod = THIS_MODULE,
124 .objs = objs,
125};
126
127static int livepatch_shadow_fix2_init(void)
128{
129 int ret;
130
131 if (!klp_have_reliable_stack() && !patch.immediate) {
132 /*
133 * WARNING: Be very careful when using 'patch.immediate' in
134 * your patches. It's ok to use it for simple patches like
135 * this, but for more complex patches which change function
136 * semantics, locking semantics, or data structures, it may not
137 * be safe. Use of this option will also prevent removal of
138 * the patch.
139 *
140 * See Documentation/livepatch/livepatch.txt for more details.
141 */
142 patch.immediate = true;
143 pr_notice("The consistency model isn't supported for your architecture. Bypassing safety mechanisms and applying the patch immediately.\n");
144 }
145
146 ret = klp_register_patch(&patch);
147 if (ret)
148 return ret;
149 ret = klp_enable_patch(&patch);
150 if (ret) {
151 WARN_ON(klp_unregister_patch(&patch));
152 return ret;
153 }
154 return 0;
155}
156
157static void livepatch_shadow_fix2_exit(void)
158{
159 /* Cleanup any existing SV_COUNTER shadow variables */
160 klp_shadow_free_all(SV_COUNTER);
161
162 WARN_ON(klp_unregister_patch(&patch));
163}
164
165module_init(livepatch_shadow_fix2_init);
166module_exit(livepatch_shadow_fix2_exit);
167MODULE_LICENSE("GPL");
168MODULE_INFO(livepatch, "Y");
diff --git a/samples/livepatch/livepatch-shadow-mod.c b/samples/livepatch/livepatch-shadow-mod.c
new file mode 100644
index 000000000000..4c54b250332d
--- /dev/null
+++ b/samples/livepatch/livepatch-shadow-mod.c
@@ -0,0 +1,224 @@
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
84MODULE_LICENSE("GPL");
85MODULE_AUTHOR("Joe Lawrence <joe.lawrence@redhat.com>");
86MODULE_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 */
99LIST_HEAD(dummy_list);
100DEFINE_MUTEX(dummy_list_mutex);
101
102struct dummy {
103 struct list_head list;
104 unsigned long jiffies_expire;
105};
106
107noinline 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
128noinline 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
136noinline 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
147static void alloc_work_func(struct work_struct *work);
148static DECLARE_DELAYED_WORK(alloc_dwork, alloc_work_func);
149
150static 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
172static void cleanup_work_func(struct work_struct *work);
173static DECLARE_DELAYED_WORK(cleanup_dwork, cleanup_work_func);
174
175static 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
198static 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
208static 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
223module_init(livepatch_shadow_mod_init);
224module_exit(livepatch_shadow_mod_exit);