diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/livepatch/shadow.c | 26 |
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 | } |
| 244 | EXPORT_SYMBOL_GPL(klp_shadow_get_or_alloc); | 244 | EXPORT_SYMBOL_GPL(klp_shadow_get_or_alloc); |
| 245 | 245 | ||
| 246 | static 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 | */ |
| 254 | void klp_shadow_free(void *obj, unsigned long id) | 265 | void 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 | */ |
| 283 | void klp_shadow_free_all(unsigned long id) | 295 | void 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); |
