diff options
-rw-r--r-- | Documentation/livepatch/shadow-vars.txt | 192 | ||||
-rw-r--r-- | include/linux/livepatch.h | 8 | ||||
-rw-r--r-- | kernel/livepatch/Makefile | 2 | ||||
-rw-r--r-- | kernel/livepatch/shadow.c | 277 | ||||
-rw-r--r-- | samples/Kconfig | 5 | ||||
-rw-r--r-- | samples/livepatch/Makefile | 3 | ||||
-rw-r--r-- | samples/livepatch/livepatch-shadow-fix1.c | 173 | ||||
-rw-r--r-- | samples/livepatch/livepatch-shadow-fix2.c | 168 | ||||
-rw-r--r-- | samples/livepatch/livepatch-shadow-mod.c | 224 |
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 | ================ | ||
2 | Shadow Variables | ||
3 | ================ | ||
4 | |||
5 | Shadow variables are a simple way for livepatch modules to associate | ||
6 | additional "shadow" data with existing data structures. Shadow data is | ||
7 | allocated separately from parent data structures, which are left | ||
8 | unmodified. The shadow variable API described in this document is used | ||
9 | to allocate/add and remove/free shadow variables to/from their parents. | ||
10 | |||
11 | The implementation introduces a global, in-kernel hashtable that | ||
12 | associates pointers to parent objects and a numeric identifier of the | ||
13 | shadow data. The numeric identifier is a simple enumeration that may be | ||
14 | used to describe shadow variable version, class or type, etc. More | ||
15 | specifically, the parent pointer serves as the hashtable key while the | ||
16 | numeric id subsequently filters hashtable queries. Multiple shadow | ||
17 | variables may attach to the same parent object, but their numeric | ||
18 | identifier distinguishes between them. | ||
19 | |||
20 | |||
21 | 1. Brief API summary | ||
22 | ==================== | ||
23 | |||
24 | (See the full API usage docbook notes in livepatch/shadow.c.) | ||
25 | |||
26 | A hashtable references all shadow variables. These references are | ||
27 | stored and retrieved through a <obj, id> pair. | ||
28 | |||
29 | * The klp_shadow variable data structure encapsulates both tracking | ||
30 | meta-data and shadow-data: | ||
31 | - meta-data | ||
32 | - obj - pointer to parent object | ||
33 | - id - data identifier | ||
34 | - data[] - storage for shadow data | ||
35 | |||
36 | It is important to note that the klp_shadow_alloc() and | ||
37 | klp_shadow_get_or_alloc() calls, described below, store a *copy* of the | ||
38 | data that the functions are provided. Callers should provide whatever | ||
39 | mutual 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 | |||
71 | 2. Use cases | ||
72 | ============ | ||
73 | |||
74 | (See the example shadow variable livepatch modules in samples/livepatch/ | ||
75 | for full working demonstrations.) | ||
76 | |||
77 | For the following use-case examples, consider commit 1d147bfa6429 | ||
78 | ("mac80211: fix AP powersave TX vs. wakeup race"), which added a | ||
79 | spinlock to net/mac80211/sta_info.h :: struct sta_info. Each use-case | ||
80 | example can be considered a stand-alone livepatch implementation of this | ||
81 | fix. | ||
82 | |||
83 | |||
84 | Matching parent's lifecycle | ||
85 | --------------------------- | ||
86 | |||
87 | If parent data structures are frequently created and destroyed, it may | ||
88 | be easiest to align their shadow variables lifetimes to the same | ||
89 | allocation and release functions. In this case, the parent data | ||
90 | structure is typically allocated, initialized, then registered in some | ||
91 | manner. Shadow variable allocation and setup can then be considered | ||
92 | part of the parent's initialization and should be completed before the | ||
93 | parent "goes live" (ie, any shadow variable get-API requests are made | ||
94 | for this <obj, id> pair.) | ||
95 | |||
96 | For commit 1d147bfa6429, when a parent sta_info structure is allocated, | ||
97 | allocate a shadow copy of the ps_lock pointer, then initialize it: | ||
98 | |||
99 | #define PS_LOCK 1 | ||
100 | struct 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 | |||
116 | When requiring a ps_lock, query the shadow variable API to retrieve one | ||
117 | for a specific struct sta_info: | ||
118 | |||
119 | void 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 | |||
129 | When the parent sta_info structure is freed, first free the shadow | ||
130 | variable: | ||
131 | |||
132 | void 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 | |||
139 | In-flight parent objects | ||
140 | ------------------------ | ||
141 | |||
142 | Sometimes it may not be convenient or possible to allocate shadow | ||
143 | variables alongside their parent objects. Or a livepatch fix may | ||
144 | require shadow varibles to only a subset of parent object instances. In | ||
145 | these cases, the klp_shadow_get_or_alloc() call can be used to attach | ||
146 | shadow variables to parents already in-flight. | ||
147 | |||
148 | For commit 1d147bfa6429, a good spot to allocate a shadow spinlock is | ||
149 | inside ieee80211_sta_ps_deliver_wakeup(): | ||
150 | |||
151 | #define PS_LOCK 1 | ||
152 | void 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 | |||
165 | This usage will create a shadow variable, only if needed, otherwise it | ||
166 | will use one that was already created for this <obj, id> pair. | ||
167 | |||
168 | Like the previous use-case, the shadow spinlock needs to be cleaned up. | ||
169 | A shadow variable can be freed just before its parent object is freed, | ||
170 | or even when the shadow variable itself is no longer required. | ||
171 | |||
172 | |||
173 | Other use-cases | ||
174 | --------------- | ||
175 | |||
176 | Shadow variables can also be used as a flag indicating that a data | ||
177 | structure was allocated by new, livepatched code. In this case, it | ||
178 | doesn't matter what data value the shadow variable holds, its existence | ||
179 | suggests how to handle the parent object. | ||
180 | |||
181 | |||
182 | 3. References | ||
183 | ============= | ||
184 | |||
185 | * https://github.com/dynup/kpatch | ||
186 | The livepatch implementation is based on the kpatch version of shadow | ||
187 | variables. | ||
188 | |||
189 | * http://files.mkgnu.net/files/dynamos/doc/papers/dynamos_eurosys_07.pdf | ||
190 | Dynamic and Adaptive Updates of Non-Quiescent Subsystems in Commodity | ||
191 | Operating System Kernels (Kritis Makris, Kyung Dong Ryu 2007) presented | ||
192 | a 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 | ||
167 | void *klp_shadow_get(void *obj, unsigned long id); | ||
168 | void *klp_shadow_alloc(void *obj, unsigned long id, void *data, | ||
169 | size_t size, gfp_t gfp_flags); | ||
170 | void *klp_shadow_get_or_alloc(void *obj, unsigned long id, void *data, | ||
171 | size_t size, gfp_t gfp_flags); | ||
172 | void klp_shadow_free(void *obj, unsigned long id); | ||
173 | void klp_shadow_free_all(unsigned long id); | ||
174 | |||
167 | #else /* !CONFIG_LIVEPATCH */ | 175 | #else /* !CONFIG_LIVEPATCH */ |
168 | 176 | ||
169 | static inline int klp_module_coming(struct module *mod) { return 0; } | 177 | static 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 @@ | |||
1 | obj-$(CONFIG_LIVEPATCH) += livepatch.o | 1 | obj-$(CONFIG_LIVEPATCH) += livepatch.o |
2 | 2 | ||
3 | livepatch-objs := core.o patch.o transition.o | 3 | livepatch-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 | |||
50 | static 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 | */ | ||
56 | static 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 | */ | ||
66 | struct 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 | */ | ||
82 | static 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 | */ | ||
95 | void *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 | } | ||
114 | EXPORT_SYMBOL_GPL(klp_shadow_get); | ||
115 | |||
116 | static 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 | |||
160 | exists: | ||
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 | */ | ||
189 | void *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 | } | ||
194 | EXPORT_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 | */ | ||
215 | void *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 | } | ||
220 | EXPORT_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 | */ | ||
230 | void 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 | } | ||
250 | EXPORT_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 | */ | ||
259 | void 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 | } | ||
277 | EXPORT_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 | ||
73 | config SAMPLE_LIVEPATCH | 73 | config 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 | ||
80 | config SAMPLE_CONFIGFS | 79 | config 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 @@ | |||
1 | obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch-sample.o | 1 | obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch-sample.o |
2 | obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch-shadow-mod.o | ||
3 | obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch-shadow-fix1.o | ||
4 | obj-$(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 | |||
54 | struct dummy { | ||
55 | struct list_head list; | ||
56 | unsigned long jiffies_expire; | ||
57 | }; | ||
58 | |||
59 | struct 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 | |||
85 | void 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 | |||
109 | static 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 | |||
120 | static struct klp_object objs[] = { | ||
121 | { | ||
122 | .name = "livepatch_shadow_mod", | ||
123 | .funcs = funcs, | ||
124 | }, { } | ||
125 | }; | ||
126 | |||
127 | static struct klp_patch patch = { | ||
128 | .mod = THIS_MODULE, | ||
129 | .objs = objs, | ||
130 | }; | ||
131 | |||
132 | static 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 | |||
162 | static 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 | |||
170 | module_init(livepatch_shadow_fix1_init); | ||
171 | module_exit(livepatch_shadow_fix1_exit); | ||
172 | MODULE_LICENSE("GPL"); | ||
173 | MODULE_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 | |||
48 | struct dummy { | ||
49 | struct list_head list; | ||
50 | unsigned long jiffies_expire; | ||
51 | }; | ||
52 | |||
53 | bool 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 | |||
73 | void 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 | |||
104 | static 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 | |||
115 | static struct klp_object objs[] = { | ||
116 | { | ||
117 | .name = "livepatch_shadow_mod", | ||
118 | .funcs = funcs, | ||
119 | }, { } | ||
120 | }; | ||
121 | |||
122 | static struct klp_patch patch = { | ||
123 | .mod = THIS_MODULE, | ||
124 | .objs = objs, | ||
125 | }; | ||
126 | |||
127 | static 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 | |||
157 | static 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 | |||
165 | module_init(livepatch_shadow_fix2_init); | ||
166 | module_exit(livepatch_shadow_fix2_exit); | ||
167 | MODULE_LICENSE("GPL"); | ||
168 | MODULE_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 | |||
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); | ||