aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-04-20 11:51:55 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-04-20 11:51:55 -0400
commit41e3bef52e42c03cb7234f2d8419352478c92926 (patch)
treefb704ba35a9263084a4606d1d326c90cd1591c40
parent36e584de256a8155a292a96288bd78a3a328aa4f (diff)
parent3b2c77d000fe9f7d02e9e726e00dccf9f92b256f (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/livepatching
Pull livepatching fix from Jiri Kosina: "Shadow variable API list_head initialization fix from Petr Mladek" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/livepatching: livepatch: Allow to call a custom callback when freeing shadow variables livepatch: Initialize shadow variables safely by a custom callback
-rw-r--r--Documentation/livepatch/shadow-vars.txt41
-rw-r--r--include/linux/livepatch.h19
-rw-r--r--kernel/livepatch/shadow.c108
-rw-r--r--samples/livepatch/livepatch-shadow-fix1.c43
-rw-r--r--samples/livepatch/livepatch-shadow-fix2.c33
5 files changed, 163 insertions, 81 deletions
diff --git a/Documentation/livepatch/shadow-vars.txt b/Documentation/livepatch/shadow-vars.txt
index 89c66634d600..ecc09a7be5dd 100644
--- a/Documentation/livepatch/shadow-vars.txt
+++ b/Documentation/livepatch/shadow-vars.txt
@@ -34,9 +34,13 @@ meta-data and shadow-data:
34 - data[] - storage for shadow data 34 - data[] - storage for shadow data
35 35
36It is important to note that the klp_shadow_alloc() and 36It is important to note that the klp_shadow_alloc() and
37klp_shadow_get_or_alloc() calls, described below, store a *copy* of the 37klp_shadow_get_or_alloc() are zeroing the variable by default.
38data that the functions are provided. Callers should provide whatever 38They also allow to call a custom constructor function when a non-zero
39mutual exclusion is required of the shadow data. 39value is needed. Callers should provide whatever mutual exclusion
40is required.
41
42Note that the constructor is called under klp_shadow_lock spinlock. It allows
43to do actions that can be done only once when a new variable is allocated.
40 44
41* klp_shadow_get() - retrieve a shadow variable data pointer 45* klp_shadow_get() - retrieve a shadow variable data pointer
42 - search hashtable for <obj, id> pair 46 - search hashtable for <obj, id> pair
@@ -47,7 +51,7 @@ mutual exclusion is required of the shadow data.
47 - WARN and return NULL 51 - WARN and return NULL
48 - if <obj, id> doesn't already exist 52 - if <obj, id> doesn't already exist
49 - allocate a new shadow variable 53 - allocate a new shadow variable
50 - copy data into the new shadow variable 54 - initialize the variable using a custom constructor and data when provided
51 - add <obj, id> to the global hashtable 55 - add <obj, id> to the global hashtable
52 56
53* klp_shadow_get_or_alloc() - get existing or alloc a new shadow variable 57* klp_shadow_get_or_alloc() - get existing or alloc a new shadow variable
@@ -56,16 +60,20 @@ mutual exclusion is required of the shadow data.
56 - return existing shadow variable 60 - return existing shadow variable
57 - if <obj, id> doesn't already exist 61 - if <obj, id> doesn't already exist
58 - allocate a new shadow variable 62 - allocate a new shadow variable
59 - copy data into the new shadow variable 63 - initialize the variable using a custom constructor and data when provided
60 - add <obj, id> pair to the global hashtable 64 - add <obj, id> pair to the global hashtable
61 65
62* klp_shadow_free() - detach and free a <obj, id> shadow variable 66* klp_shadow_free() - detach and free a <obj, id> shadow variable
63 - find and remove a <obj, id> reference from global hashtable 67 - find and remove a <obj, id> reference from global hashtable
64 - if found, free shadow variable 68 - if found
69 - call destructor function if defined
70 - free shadow variable
65 71
66* klp_shadow_free_all() - detach and free all <*, id> shadow variables 72* klp_shadow_free_all() - detach and free all <*, id> shadow variables
67 - find and remove any <*, id> references from global hashtable 73 - find and remove any <*, id> references from global hashtable
68 - if found, free shadow variable 74 - if found
75 - call destructor function if defined
76 - free shadow variable
69 77
70 78
712. Use cases 792. Use cases
@@ -107,7 +115,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
107 sta = kzalloc(sizeof(*sta) + hw->sta_data_size, gfp); 115 sta = kzalloc(sizeof(*sta) + hw->sta_data_size, gfp);
108 116
109 /* Attach a corresponding shadow variable, then initialize it */ 117 /* Attach a corresponding shadow variable, then initialize it */
110 ps_lock = klp_shadow_alloc(sta, PS_LOCK, NULL, sizeof(*ps_lock), gfp); 118 ps_lock = klp_shadow_alloc(sta, PS_LOCK, sizeof(*ps_lock), gfp,
119 NULL, NULL);
111 if (!ps_lock) 120 if (!ps_lock)
112 goto shadow_fail; 121 goto shadow_fail;
113 spin_lock_init(ps_lock); 122 spin_lock_init(ps_lock);
@@ -131,7 +140,7 @@ variable:
131 140
132void sta_info_free(struct ieee80211_local *local, struct sta_info *sta) 141void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
133{ 142{
134 klp_shadow_free(sta, PS_LOCK); 143 klp_shadow_free(sta, PS_LOCK, NULL);
135 kfree(sta); 144 kfree(sta);
136 ... 145 ...
137 146
@@ -148,16 +157,24 @@ shadow variables to parents already in-flight.
148For commit 1d147bfa6429, a good spot to allocate a shadow spinlock is 157For commit 1d147bfa6429, a good spot to allocate a shadow spinlock is
149inside ieee80211_sta_ps_deliver_wakeup(): 158inside ieee80211_sta_ps_deliver_wakeup():
150 159
160int ps_lock_shadow_ctor(void *obj, void *shadow_data, void *ctor_data)
161{
162 spinlock_t *lock = shadow_data;
163
164 spin_lock_init(lock);
165 return 0;
166}
167
151#define PS_LOCK 1 168#define PS_LOCK 1
152void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) 169void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
153{ 170{
154 DEFINE_SPINLOCK(ps_lock_fallback);
155 spinlock_t *ps_lock; 171 spinlock_t *ps_lock;
156 172
157 /* sync with ieee80211_tx_h_unicast_ps_buf */ 173 /* sync with ieee80211_tx_h_unicast_ps_buf */
158 ps_lock = klp_shadow_get_or_alloc(sta, PS_LOCK, 174 ps_lock = klp_shadow_get_or_alloc(sta, PS_LOCK,
159 &ps_lock_fallback, sizeof(ps_lock_fallback), 175 sizeof(*ps_lock), GFP_ATOMIC,
160 GFP_ATOMIC); 176 ps_lock_shadow_ctor, NULL);
177
161 if (ps_lock) 178 if (ps_lock)
162 spin_lock(ps_lock); 179 spin_lock(ps_lock);
163 ... 180 ...
diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
index 4754f01c1abb..aec44b1d9582 100644
--- a/include/linux/livepatch.h
+++ b/include/linux/livepatch.h
@@ -186,13 +186,20 @@ static inline bool klp_have_reliable_stack(void)
186 IS_ENABLED(CONFIG_HAVE_RELIABLE_STACKTRACE); 186 IS_ENABLED(CONFIG_HAVE_RELIABLE_STACKTRACE);
187} 187}
188 188
189typedef int (*klp_shadow_ctor_t)(void *obj,
190 void *shadow_data,
191 void *ctor_data);
192typedef void (*klp_shadow_dtor_t)(void *obj, void *shadow_data);
193
189void *klp_shadow_get(void *obj, unsigned long id); 194void *klp_shadow_get(void *obj, unsigned long id);
190void *klp_shadow_alloc(void *obj, unsigned long id, void *data, 195void *klp_shadow_alloc(void *obj, unsigned long id,
191 size_t size, gfp_t gfp_flags); 196 size_t size, gfp_t gfp_flags,
192void *klp_shadow_get_or_alloc(void *obj, unsigned long id, void *data, 197 klp_shadow_ctor_t ctor, void *ctor_data);
193 size_t size, gfp_t gfp_flags); 198void *klp_shadow_get_or_alloc(void *obj, unsigned long id,
194void klp_shadow_free(void *obj, unsigned long id); 199 size_t size, gfp_t gfp_flags,
195void klp_shadow_free_all(unsigned long id); 200 klp_shadow_ctor_t ctor, void *ctor_data);
201void klp_shadow_free(void *obj, unsigned long id, klp_shadow_dtor_t dtor);
202void klp_shadow_free_all(unsigned long id, klp_shadow_dtor_t dtor);
196 203
197#else /* !CONFIG_LIVEPATCH */ 204#else /* !CONFIG_LIVEPATCH */
198 205
diff --git a/kernel/livepatch/shadow.c b/kernel/livepatch/shadow.c
index fdac27588d60..83958c814439 100644
--- a/kernel/livepatch/shadow.c
+++ b/kernel/livepatch/shadow.c
@@ -113,8 +113,10 @@ void *klp_shadow_get(void *obj, unsigned long id)
113} 113}
114EXPORT_SYMBOL_GPL(klp_shadow_get); 114EXPORT_SYMBOL_GPL(klp_shadow_get);
115 115
116static void *__klp_shadow_get_or_alloc(void *obj, unsigned long id, void *data, 116static void *__klp_shadow_get_or_alloc(void *obj, unsigned long id,
117 size_t size, gfp_t gfp_flags, bool warn_on_exist) 117 size_t size, gfp_t gfp_flags,
118 klp_shadow_ctor_t ctor, void *ctor_data,
119 bool warn_on_exist)
118{ 120{
119 struct klp_shadow *new_shadow; 121 struct klp_shadow *new_shadow;
120 void *shadow_data; 122 void *shadow_data;
@@ -125,18 +127,15 @@ static void *__klp_shadow_get_or_alloc(void *obj, unsigned long id, void *data,
125 if (shadow_data) 127 if (shadow_data)
126 goto exists; 128 goto exists;
127 129
128 /* Allocate a new shadow variable for use inside the lock below */ 130 /*
131 * Allocate a new shadow variable. Fill it with zeroes by default.
132 * More complex setting can be done by @ctor function. But it is
133 * called only when the buffer is really used (under klp_shadow_lock).
134 */
129 new_shadow = kzalloc(size + sizeof(*new_shadow), gfp_flags); 135 new_shadow = kzalloc(size + sizeof(*new_shadow), gfp_flags);
130 if (!new_shadow) 136 if (!new_shadow)
131 return NULL; 137 return NULL;
132 138
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 */ 139 /* Look for <obj, id> again under the lock */
141 spin_lock_irqsave(&klp_shadow_lock, flags); 140 spin_lock_irqsave(&klp_shadow_lock, flags);
142 shadow_data = klp_shadow_get(obj, id); 141 shadow_data = klp_shadow_get(obj, id);
@@ -150,6 +149,22 @@ static void *__klp_shadow_get_or_alloc(void *obj, unsigned long id, void *data,
150 goto exists; 149 goto exists;
151 } 150 }
152 151
152 new_shadow->obj = obj;
153 new_shadow->id = id;
154
155 if (ctor) {
156 int err;
157
158 err = ctor(obj, new_shadow->data, ctor_data);
159 if (err) {
160 spin_unlock_irqrestore(&klp_shadow_lock, flags);
161 kfree(new_shadow);
162 pr_err("Failed to construct shadow variable <%p, %lx> (%d)\n",
163 obj, id, err);
164 return NULL;
165 }
166 }
167
153 /* No <obj, id> found, so attach the newly allocated one */ 168 /* No <obj, id> found, so attach the newly allocated one */
154 hash_add_rcu(klp_shadow_hash, &new_shadow->node, 169 hash_add_rcu(klp_shadow_hash, &new_shadow->node,
155 (unsigned long)new_shadow->obj); 170 (unsigned long)new_shadow->obj);
@@ -170,26 +185,32 @@ exists:
170 * klp_shadow_alloc() - allocate and add a new shadow variable 185 * klp_shadow_alloc() - allocate and add a new shadow variable
171 * @obj: pointer to parent object 186 * @obj: pointer to parent object
172 * @id: data identifier 187 * @id: data identifier
173 * @data: pointer to data to attach to parent
174 * @size: size of attached data 188 * @size: size of attached data
175 * @gfp_flags: GFP mask for allocation 189 * @gfp_flags: GFP mask for allocation
190 * @ctor: custom constructor to initialize the shadow data (optional)
191 * @ctor_data: pointer to any data needed by @ctor (optional)
192 *
193 * Allocates @size bytes for new shadow variable data using @gfp_flags.
194 * The data are zeroed by default. They are further initialized by @ctor
195 * function if it is not NULL. The new shadow variable is then added
196 * to the global hashtable.
176 * 197 *
177 * Allocates @size bytes for new shadow variable data using @gfp_flags 198 * If an existing <obj, id> shadow variable can be found, this routine will
178 * and copies @size bytes from @data into the new shadow variable's own 199 * issue a WARN, exit early and return NULL.
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 * 200 *
183 * If an existing <obj, id> shadow variable can be found, this routine 201 * This function guarantees that the constructor function is called only when
184 * will issue a WARN, exit early and return NULL. 202 * the variable did not exist before. The cost is that @ctor is called
203 * in atomic context under a spin lock.
185 * 204 *
186 * Return: the shadow variable data element, NULL on duplicate or 205 * Return: the shadow variable data element, NULL on duplicate or
187 * failure. 206 * failure.
188 */ 207 */
189void *klp_shadow_alloc(void *obj, unsigned long id, void *data, 208void *klp_shadow_alloc(void *obj, unsigned long id,
190 size_t size, gfp_t gfp_flags) 209 size_t size, gfp_t gfp_flags,
210 klp_shadow_ctor_t ctor, void *ctor_data)
191{ 211{
192 return __klp_shadow_get_or_alloc(obj, id, data, size, gfp_flags, true); 212 return __klp_shadow_get_or_alloc(obj, id, size, gfp_flags,
213 ctor, ctor_data, true);
193} 214}
194EXPORT_SYMBOL_GPL(klp_shadow_alloc); 215EXPORT_SYMBOL_GPL(klp_shadow_alloc);
195 216
@@ -197,37 +218,51 @@ EXPORT_SYMBOL_GPL(klp_shadow_alloc);
197 * klp_shadow_get_or_alloc() - get existing or allocate a new shadow variable 218 * klp_shadow_get_or_alloc() - get existing or allocate a new shadow variable
198 * @obj: pointer to parent object 219 * @obj: pointer to parent object
199 * @id: data identifier 220 * @id: data identifier
200 * @data: pointer to data to attach to parent
201 * @size: size of attached data 221 * @size: size of attached data
202 * @gfp_flags: GFP mask for allocation 222 * @gfp_flags: GFP mask for allocation
223 * @ctor: custom constructor to initialize the shadow data (optional)
224 * @ctor_data: pointer to any data needed by @ctor (optional)
203 * 225 *
204 * Returns a pointer to existing shadow data if an <obj, id> shadow 226 * Returns a pointer to existing shadow data if an <obj, id> shadow
205 * variable is already present. Otherwise, it creates a new shadow 227 * variable is already present. Otherwise, it creates a new shadow
206 * variable like klp_shadow_alloc(). 228 * variable like klp_shadow_alloc().
207 * 229 *
208 * This function guarantees that only one shadow variable exists with 230 * This function guarantees that only one shadow variable exists with the given
209 * the given @id for the given @obj. It also guarantees that the shadow 231 * @id for the given @obj. It also guarantees that the constructor function
210 * variable will be initialized by the given @data only when it did not 232 * will be called only when the variable did not exist before. The cost is
211 * exist before. 233 * that @ctor is called in atomic context under a spin lock.
212 * 234 *
213 * Return: the shadow variable data element, NULL on failure. 235 * Return: the shadow variable data element, NULL on failure.
214 */ 236 */
215void *klp_shadow_get_or_alloc(void *obj, unsigned long id, void *data, 237void *klp_shadow_get_or_alloc(void *obj, unsigned long id,
216 size_t size, gfp_t gfp_flags) 238 size_t size, gfp_t gfp_flags,
239 klp_shadow_ctor_t ctor, void *ctor_data)
217{ 240{
218 return __klp_shadow_get_or_alloc(obj, id, data, size, gfp_flags, false); 241 return __klp_shadow_get_or_alloc(obj, id, size, gfp_flags,
242 ctor, ctor_data, false);
219} 243}
220EXPORT_SYMBOL_GPL(klp_shadow_get_or_alloc); 244EXPORT_SYMBOL_GPL(klp_shadow_get_or_alloc);
221 245
246static void klp_shadow_free_struct(struct klp_shadow *shadow,
247 klp_shadow_dtor_t dtor)
248{
249 hash_del_rcu(&shadow->node);
250 if (dtor)
251 dtor(shadow->obj, shadow->data);
252 kfree_rcu(shadow, rcu_head);
253}
254
222/** 255/**
223 * klp_shadow_free() - detach and free a <obj, id> shadow variable 256 * klp_shadow_free() - detach and free a <obj, id> shadow variable
224 * @obj: pointer to parent object 257 * @obj: pointer to parent object
225 * @id: data identifier 258 * @id: data identifier
259 * @dtor: custom callback that can be used to unregister the variable
260 * and/or free data that the shadow variable points to (optional)
226 * 261 *
227 * This function releases the memory for this <obj, id> shadow variable 262 * This function releases the memory for this <obj, id> shadow variable
228 * instance, callers should stop referencing it accordingly. 263 * instance, callers should stop referencing it accordingly.
229 */ 264 */
230void klp_shadow_free(void *obj, unsigned long id) 265void klp_shadow_free(void *obj, unsigned long id, klp_shadow_dtor_t dtor)
231{ 266{
232 struct klp_shadow *shadow; 267 struct klp_shadow *shadow;
233 unsigned long flags; 268 unsigned long flags;
@@ -239,8 +274,7 @@ void klp_shadow_free(void *obj, unsigned long id)
239 (unsigned long)obj) { 274 (unsigned long)obj) {
240 275
241 if (klp_shadow_match(shadow, obj, id)) { 276 if (klp_shadow_match(shadow, obj, id)) {
242 hash_del_rcu(&shadow->node); 277 klp_shadow_free_struct(shadow, dtor);
243 kfree_rcu(shadow, rcu_head);
244 break; 278 break;
245 } 279 }
246 } 280 }
@@ -252,11 +286,13 @@ EXPORT_SYMBOL_GPL(klp_shadow_free);
252/** 286/**
253 * klp_shadow_free_all() - detach and free all <*, id> shadow variables 287 * klp_shadow_free_all() - detach and free all <*, id> shadow variables
254 * @id: data identifier 288 * @id: data identifier
289 * @dtor: custom callback that can be used to unregister the variable
290 * and/or free data that the shadow variable points to (optional)
255 * 291 *
256 * This function releases the memory for all <*, id> shadow variable 292 * This function releases the memory for all <*, id> shadow variable
257 * instances, callers should stop referencing them accordingly. 293 * instances, callers should stop referencing them accordingly.
258 */ 294 */
259void klp_shadow_free_all(unsigned long id) 295void klp_shadow_free_all(unsigned long id, klp_shadow_dtor_t dtor)
260{ 296{
261 struct klp_shadow *shadow; 297 struct klp_shadow *shadow;
262 unsigned long flags; 298 unsigned long flags;
@@ -266,10 +302,8 @@ void klp_shadow_free_all(unsigned long id)
266 302
267 /* Delete all <*, id> from hash */ 303 /* Delete all <*, id> from hash */
268 hash_for_each(klp_shadow_hash, i, shadow, node) { 304 hash_for_each(klp_shadow_hash, i, shadow, node) {
269 if (klp_shadow_match(shadow, shadow->obj, id)) { 305 if (klp_shadow_match(shadow, shadow->obj, id))
270 hash_del_rcu(&shadow->node); 306 klp_shadow_free_struct(shadow, dtor);
271 kfree_rcu(shadow, rcu_head);
272 }
273 } 307 }
274 308
275 spin_unlock_irqrestore(&klp_shadow_lock, flags); 309 spin_unlock_irqrestore(&klp_shadow_lock, flags);
diff --git a/samples/livepatch/livepatch-shadow-fix1.c b/samples/livepatch/livepatch-shadow-fix1.c
index 830c55514f9f..49b13553eaae 100644
--- a/samples/livepatch/livepatch-shadow-fix1.c
+++ b/samples/livepatch/livepatch-shadow-fix1.c
@@ -56,6 +56,21 @@ struct dummy {
56 unsigned long jiffies_expire; 56 unsigned long jiffies_expire;
57}; 57};
58 58
59/*
60 * The constructor makes more sense together with klp_shadow_get_or_alloc().
61 * In this example, it would be safe to assign the pointer also to the shadow
62 * variable returned by klp_shadow_alloc(). But we wanted to show the more
63 * complicated use of the API.
64 */
65static int shadow_leak_ctor(void *obj, void *shadow_data, void *ctor_data)
66{
67 void **shadow_leak = shadow_data;
68 void *leak = ctor_data;
69
70 *shadow_leak = leak;
71 return 0;
72}
73
59struct dummy *livepatch_fix1_dummy_alloc(void) 74struct dummy *livepatch_fix1_dummy_alloc(void)
60{ 75{
61 struct dummy *d; 76 struct dummy *d;
@@ -74,7 +89,8 @@ struct dummy *livepatch_fix1_dummy_alloc(void)
74 * pointer to handle resource release. 89 * pointer to handle resource release.
75 */ 90 */
76 leak = kzalloc(sizeof(int), GFP_KERNEL); 91 leak = kzalloc(sizeof(int), GFP_KERNEL);
77 klp_shadow_alloc(d, SV_LEAK, &leak, sizeof(leak), GFP_KERNEL); 92 klp_shadow_alloc(d, SV_LEAK, sizeof(leak), GFP_KERNEL,
93 shadow_leak_ctor, leak);
78 94
79 pr_info("%s: dummy @ %p, expires @ %lx\n", 95 pr_info("%s: dummy @ %p, expires @ %lx\n",
80 __func__, d, d->jiffies_expire); 96 __func__, d, d->jiffies_expire);
@@ -82,9 +98,19 @@ struct dummy *livepatch_fix1_dummy_alloc(void)
82 return d; 98 return d;
83} 99}
84 100
101static void livepatch_fix1_dummy_leak_dtor(void *obj, void *shadow_data)
102{
103 void *d = obj;
104 void **shadow_leak = shadow_data;
105
106 kfree(*shadow_leak);
107 pr_info("%s: dummy @ %p, prevented leak @ %p\n",
108 __func__, d, *shadow_leak);
109}
110
85void livepatch_fix1_dummy_free(struct dummy *d) 111void livepatch_fix1_dummy_free(struct dummy *d)
86{ 112{
87 void **shadow_leak, *leak; 113 void **shadow_leak;
88 114
89 /* 115 /*
90 * Patch: fetch the saved SV_LEAK shadow variable, detach and 116 * Patch: fetch the saved SV_LEAK shadow variable, detach and
@@ -93,15 +119,10 @@ void livepatch_fix1_dummy_free(struct dummy *d)
93 * was loaded.) 119 * was loaded.)
94 */ 120 */
95 shadow_leak = klp_shadow_get(d, SV_LEAK); 121 shadow_leak = klp_shadow_get(d, SV_LEAK);
96 if (shadow_leak) { 122 if (shadow_leak)
97 leak = *shadow_leak; 123 klp_shadow_free(d, SV_LEAK, livepatch_fix1_dummy_leak_dtor);
98 klp_shadow_free(d, SV_LEAK); 124 else
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); 125 pr_info("%s: dummy @ %p leaked!\n", __func__, d);
104 }
105 126
106 kfree(d); 127 kfree(d);
107} 128}
@@ -147,7 +168,7 @@ static int livepatch_shadow_fix1_init(void)
147static void livepatch_shadow_fix1_exit(void) 168static void livepatch_shadow_fix1_exit(void)
148{ 169{
149 /* Cleanup any existing SV_LEAK shadow variables */ 170 /* Cleanup any existing SV_LEAK shadow variables */
150 klp_shadow_free_all(SV_LEAK); 171 klp_shadow_free_all(SV_LEAK, livepatch_fix1_dummy_leak_dtor);
151 172
152 WARN_ON(klp_unregister_patch(&patch)); 173 WARN_ON(klp_unregister_patch(&patch));
153} 174}
diff --git a/samples/livepatch/livepatch-shadow-fix2.c b/samples/livepatch/livepatch-shadow-fix2.c
index ff9948f0ec00..b34c7bf83356 100644
--- a/samples/livepatch/livepatch-shadow-fix2.c
+++ b/samples/livepatch/livepatch-shadow-fix2.c
@@ -53,39 +53,42 @@ struct dummy {
53bool livepatch_fix2_dummy_check(struct dummy *d, unsigned long jiffies) 53bool livepatch_fix2_dummy_check(struct dummy *d, unsigned long jiffies)
54{ 54{
55 int *shadow_count; 55 int *shadow_count;
56 int count;
57 56
58 /* 57 /*
59 * Patch: handle in-flight dummy structures, if they do not 58 * Patch: handle in-flight dummy structures, if they do not
60 * already have a SV_COUNTER shadow variable, then attach a 59 * already have a SV_COUNTER shadow variable, then attach a
61 * new one. 60 * new one.
62 */ 61 */
63 count = 0;
64 shadow_count = klp_shadow_get_or_alloc(d, SV_COUNTER, 62 shadow_count = klp_shadow_get_or_alloc(d, SV_COUNTER,
65 &count, sizeof(count), 63 sizeof(*shadow_count), GFP_NOWAIT,
66 GFP_NOWAIT); 64 NULL, NULL);
67 if (shadow_count) 65 if (shadow_count)
68 *shadow_count += 1; 66 *shadow_count += 1;
69 67
70 return time_after(jiffies, d->jiffies_expire); 68 return time_after(jiffies, d->jiffies_expire);
71} 69}
72 70
71static void livepatch_fix2_dummy_leak_dtor(void *obj, void *shadow_data)
72{
73 void *d = obj;
74 void **shadow_leak = shadow_data;
75
76 kfree(*shadow_leak);
77 pr_info("%s: dummy @ %p, prevented leak @ %p\n",
78 __func__, d, *shadow_leak);
79}
80
73void livepatch_fix2_dummy_free(struct dummy *d) 81void livepatch_fix2_dummy_free(struct dummy *d)
74{ 82{
75 void **shadow_leak, *leak; 83 void **shadow_leak;
76 int *shadow_count; 84 int *shadow_count;
77 85
78 /* Patch: copy the memory leak patch from the fix1 module. */ 86 /* Patch: copy the memory leak patch from the fix1 module. */
79 shadow_leak = klp_shadow_get(d, SV_LEAK); 87 shadow_leak = klp_shadow_get(d, SV_LEAK);
80 if (shadow_leak) { 88 if (shadow_leak)
81 leak = *shadow_leak; 89 klp_shadow_free(d, SV_LEAK, livepatch_fix2_dummy_leak_dtor);
82 klp_shadow_free(d, SV_LEAK); 90 else
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); 91 pr_info("%s: dummy @ %p leaked!\n", __func__, d);
88 }
89 92
90 /* 93 /*
91 * Patch: fetch the SV_COUNTER shadow variable and display 94 * Patch: fetch the SV_COUNTER shadow variable and display
@@ -95,7 +98,7 @@ void livepatch_fix2_dummy_free(struct dummy *d)
95 if (shadow_count) { 98 if (shadow_count) {
96 pr_info("%s: dummy @ %p, check counter = %d\n", 99 pr_info("%s: dummy @ %p, check counter = %d\n",
97 __func__, d, *shadow_count); 100 __func__, d, *shadow_count);
98 klp_shadow_free(d, SV_COUNTER); 101 klp_shadow_free(d, SV_COUNTER, NULL);
99 } 102 }
100 103
101 kfree(d); 104 kfree(d);
@@ -142,7 +145,7 @@ static int livepatch_shadow_fix2_init(void)
142static void livepatch_shadow_fix2_exit(void) 145static void livepatch_shadow_fix2_exit(void)
143{ 146{
144 /* Cleanup any existing SV_COUNTER shadow variables */ 147 /* Cleanup any existing SV_COUNTER shadow variables */
145 klp_shadow_free_all(SV_COUNTER); 148 klp_shadow_free_all(SV_COUNTER, NULL);
146 149
147 WARN_ON(klp_unregister_patch(&patch)); 150 WARN_ON(klp_unregister_patch(&patch));
148} 151}