aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/livepatch/shadow.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/livepatch/shadow.c')
-rw-r--r--kernel/livepatch/shadow.c26
1 files changed, 18 insertions, 8 deletions
diff --git a/kernel/livepatch/shadow.c b/kernel/livepatch/shadow.c
index b10a0bbb7f84..83958c814439 100644
--- a/kernel/livepatch/shadow.c
+++ b/kernel/livepatch/shadow.c
@@ -243,15 +243,26 @@ void *klp_shadow_get_or_alloc(void *obj, unsigned long id,
243} 243}
244EXPORT_SYMBOL_GPL(klp_shadow_get_or_alloc); 244EXPORT_SYMBOL_GPL(klp_shadow_get_or_alloc);
245 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
246/** 255/**
247 * klp_shadow_free() - detach and free a <obj, id> shadow variable 256 * klp_shadow_free() - detach and free a <obj, id> shadow variable
248 * @obj: pointer to parent object 257 * @obj: pointer to parent object
249 * @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)
250 * 261 *
251 * This function releases the memory for this <obj, id> shadow variable 262 * This function releases the memory for this <obj, id> shadow variable
252 * instance, callers should stop referencing it accordingly. 263 * instance, callers should stop referencing it accordingly.
253 */ 264 */
254void klp_shadow_free(void *obj, unsigned long id) 265void klp_shadow_free(void *obj, unsigned long id, klp_shadow_dtor_t dtor)
255{ 266{
256 struct klp_shadow *shadow; 267 struct klp_shadow *shadow;
257 unsigned long flags; 268 unsigned long flags;
@@ -263,8 +274,7 @@ void klp_shadow_free(void *obj, unsigned long id)
263 (unsigned long)obj) { 274 (unsigned long)obj) {
264 275
265 if (klp_shadow_match(shadow, obj, id)) { 276 if (klp_shadow_match(shadow, obj, id)) {
266 hash_del_rcu(&shadow->node); 277 klp_shadow_free_struct(shadow, dtor);
267 kfree_rcu(shadow, rcu_head);
268 break; 278 break;
269 } 279 }
270 } 280 }
@@ -276,11 +286,13 @@ EXPORT_SYMBOL_GPL(klp_shadow_free);
276/** 286/**
277 * klp_shadow_free_all() - detach and free all <*, id> shadow variables 287 * klp_shadow_free_all() - detach and free all <*, id> shadow variables
278 * @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)
279 * 291 *
280 * This function releases the memory for all <*, id> shadow variable 292 * This function releases the memory for all <*, id> shadow variable
281 * instances, callers should stop referencing them accordingly. 293 * instances, callers should stop referencing them accordingly.
282 */ 294 */
283void klp_shadow_free_all(unsigned long id) 295void klp_shadow_free_all(unsigned long id, klp_shadow_dtor_t dtor)
284{ 296{
285 struct klp_shadow *shadow; 297 struct klp_shadow *shadow;
286 unsigned long flags; 298 unsigned long flags;
@@ -290,10 +302,8 @@ void klp_shadow_free_all(unsigned long id)
290 302
291 /* Delete all <*, id> from hash */ 303 /* Delete all <*, id> from hash */
292 hash_for_each(klp_shadow_hash, i, shadow, node) { 304 hash_for_each(klp_shadow_hash, i, shadow, node) {
293 if (klp_shadow_match(shadow, shadow->obj, id)) { 305 if (klp_shadow_match(shadow, shadow->obj, id))
294 hash_del_rcu(&shadow->node); 306 klp_shadow_free_struct(shadow, dtor);
295 kfree_rcu(shadow, rcu_head);
296 }
297 } 307 }
298 308
299 spin_unlock_irqrestore(&klp_shadow_lock, flags); 309 spin_unlock_irqrestore(&klp_shadow_lock, flags);